blob: ecd61323d816841cb51168212ed67b281f7021ee [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 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]6624b4622010-03-29 19:58:3614#include "base/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]80d6524d2009-08-18 03:58:0997 scoped_refptr<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();
109 params.proxy_service = session_deps->proxy_service;
110 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]9f95c692011-02-11 19:20:19277 ClientSocket* socket,
278 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]2d731a32010-04-29 01:04:06298typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11299CaptureGroupNameTCPSocketPool;
[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]31a2bfe2010-02-09 08:03:391195 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1196 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591197 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321198
1199 TestCompletionCallback callback1;
1200
[email protected]0b0bf032010-09-21 18:08:501201 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271202 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421203 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321204
1205 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421206 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321207
[email protected]1c773ea12009-04-28 19:58:421208 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321209 EXPECT_FALSE(response == NULL);
1210
1211 // The password prompt info should have been set in response->auth_challenge.
1212 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1213
[email protected]71e4573a2009-05-21 22:03:001214 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321215 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1216 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1217
1218 TestCompletionCallback callback2;
1219
[email protected]13c8a092010-07-29 06:15:441220 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421221 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321222
1223 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421224 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321225
1226 response = trans->GetResponseInfo();
1227 EXPECT_FALSE(response == NULL);
1228 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501229 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321230}
1231
1232// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1233// connection and with no response body to drain.
1234TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421235 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321236 request.method = "GET";
1237 request.url = GURL("http://www.google.com/");
1238 request.load_flags = 0;
1239
[email protected]cb9bf6ca2011-01-28 13:15:271240 SessionDependencies session_deps;
1241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1242
[email protected]2d2697f92009-02-18 21:00:321243 MockWrite data_writes1[] = {
1244 MockWrite("GET / HTTP/1.1\r\n"
1245 "Host: www.google.com\r\n"
1246 "Connection: keep-alive\r\n\r\n"),
1247
1248 // After calling trans->RestartWithAuth(), this is the request we should
1249 // be issuing -- the final header line contains the credentials.
1250 MockWrite("GET / HTTP/1.1\r\n"
1251 "Host: www.google.com\r\n"
1252 "Connection: keep-alive\r\n"
1253 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1254 };
1255
[email protected]2d2697f92009-02-18 21:00:321256 MockRead data_reads1[] = {
1257 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1258 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311259 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321260
1261 // Lastly, the server responds with the actual content.
1262 MockRead("HTTP/1.1 200 OK\r\n"),
1263 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501264 MockRead("Content-Length: 5\r\n\r\n"),
1265 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321266 };
1267
[email protected]31a2bfe2010-02-09 08:03:391268 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1269 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591270 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321271
1272 TestCompletionCallback callback1;
1273
[email protected]0b0bf032010-09-21 18:08:501274 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271275 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421276 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321277
1278 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421279 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321280
[email protected]1c773ea12009-04-28 19:58:421281 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321282 EXPECT_FALSE(response == NULL);
1283
1284 // The password prompt info should have been set in response->auth_challenge.
1285 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1286
[email protected]71e4573a2009-05-21 22:03:001287 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321288 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1289 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1290
1291 TestCompletionCallback callback2;
1292
[email protected]13c8a092010-07-29 06:15:441293 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421294 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321295
1296 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421297 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321298
1299 response = trans->GetResponseInfo();
1300 EXPECT_FALSE(response == NULL);
1301 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501302 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321303}
1304
1305// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1306// connection and with a large response body to drain.
1307TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421308 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321309 request.method = "GET";
1310 request.url = GURL("http://www.google.com/");
1311 request.load_flags = 0;
1312
[email protected]cb9bf6ca2011-01-28 13:15:271313 SessionDependencies session_deps;
1314 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1315
[email protected]2d2697f92009-02-18 21:00:321316 MockWrite data_writes1[] = {
1317 MockWrite("GET / HTTP/1.1\r\n"
1318 "Host: www.google.com\r\n"
1319 "Connection: keep-alive\r\n\r\n"),
1320
1321 // After calling trans->RestartWithAuth(), this is the request we should
1322 // be issuing -- the final header line contains the credentials.
1323 MockWrite("GET / HTTP/1.1\r\n"
1324 "Host: www.google.com\r\n"
1325 "Connection: keep-alive\r\n"
1326 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1327 };
1328
1329 // Respond with 5 kb of response body.
1330 std::string large_body_string("Unauthorized");
1331 large_body_string.append(5 * 1024, ' ');
1332 large_body_string.append("\r\n");
1333
1334 MockRead data_reads1[] = {
1335 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1336 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1337 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1338 // 5134 = 12 + 5 * 1024 + 2
1339 MockRead("Content-Length: 5134\r\n\r\n"),
1340 MockRead(true, large_body_string.data(), large_body_string.size()),
1341
1342 // Lastly, the server responds with the actual content.
1343 MockRead("HTTP/1.1 200 OK\r\n"),
1344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501345 MockRead("Content-Length: 5\r\n\r\n"),
1346 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321347 };
1348
[email protected]31a2bfe2010-02-09 08:03:391349 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1350 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591351 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321352
1353 TestCompletionCallback callback1;
1354
[email protected]0b0bf032010-09-21 18:08:501355 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271356 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421357 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321358
1359 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421360 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321361
[email protected]1c773ea12009-04-28 19:58:421362 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321363 EXPECT_FALSE(response == NULL);
1364
1365 // The password prompt info should have been set in response->auth_challenge.
1366 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1367
[email protected]71e4573a2009-05-21 22:03:001368 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321369 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1370 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1371
1372 TestCompletionCallback callback2;
1373
[email protected]13c8a092010-07-29 06:15:441374 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421375 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321376
1377 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421378 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321379
1380 response = trans->GetResponseInfo();
1381 EXPECT_FALSE(response == NULL);
1382 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501383 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321384}
1385
1386// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311387// connection, but the server gets impatient and closes the connection.
1388TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311389 HttpRequestInfo request;
1390 request.method = "GET";
1391 request.url = GURL("http://www.google.com/");
1392 request.load_flags = 0;
1393
[email protected]cb9bf6ca2011-01-28 13:15:271394 SessionDependencies session_deps;
1395 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1396
[email protected]11203f012009-11-12 23:02:311397 MockWrite data_writes1[] = {
1398 MockWrite("GET / HTTP/1.1\r\n"
1399 "Host: www.google.com\r\n"
1400 "Connection: keep-alive\r\n\r\n"),
1401 // This simulates the seemingly successful write to a closed connection
1402 // if the bug is not fixed.
1403 MockWrite("GET / HTTP/1.1\r\n"
1404 "Host: www.google.com\r\n"
1405 "Connection: keep-alive\r\n"
1406 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1407 };
1408
1409 MockRead data_reads1[] = {
1410 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1411 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1413 MockRead("Content-Length: 14\r\n\r\n"),
1414 // Tell MockTCPClientSocket to simulate the server closing the connection.
1415 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1416 MockRead("Unauthorized\r\n"),
1417 MockRead(false, OK), // The server closes the connection.
1418 };
1419
1420 // After calling trans->RestartWithAuth(), this is the request we should
1421 // be issuing -- the final header line contains the credentials.
1422 MockWrite data_writes2[] = {
1423 MockWrite("GET / HTTP/1.1\r\n"
1424 "Host: www.google.com\r\n"
1425 "Connection: keep-alive\r\n"
1426 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1427 };
1428
1429 // Lastly, the server responds with the actual content.
1430 MockRead data_reads2[] = {
1431 MockRead("HTTP/1.1 200 OK\r\n"),
1432 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501433 MockRead("Content-Length: 5\r\n\r\n"),
1434 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311435 };
1436
[email protected]31a2bfe2010-02-09 08:03:391437 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1438 data_writes1, arraysize(data_writes1));
1439 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1440 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311441 session_deps.socket_factory.AddSocketDataProvider(&data1);
1442 session_deps.socket_factory.AddSocketDataProvider(&data2);
1443
1444 TestCompletionCallback callback1;
1445
[email protected]0b0bf032010-09-21 18:08:501446 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271447 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311448 EXPECT_EQ(ERR_IO_PENDING, rv);
1449
1450 rv = callback1.WaitForResult();
1451 EXPECT_EQ(OK, rv);
1452
1453 const HttpResponseInfo* response = trans->GetResponseInfo();
1454 EXPECT_FALSE(response == NULL);
1455
1456 // The password prompt info should have been set in response->auth_challenge.
1457 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1458
1459 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1460 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1461 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1462
1463 TestCompletionCallback callback2;
1464
[email protected]13c8a092010-07-29 06:15:441465 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311466 EXPECT_EQ(ERR_IO_PENDING, rv);
1467
1468 rv = callback2.WaitForResult();
1469 EXPECT_EQ(OK, rv);
1470
1471 response = trans->GetResponseInfo();
1472 ASSERT_FALSE(response == NULL);
1473 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501474 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311475}
1476
[email protected]394816e92010-08-03 07:38:591477// Test the request-challenge-retry sequence for basic auth, over a connection
1478// that requires a restart when setting up an SSL tunnel.
1479TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591480 HttpRequestInfo request;
1481 request.method = "GET";
1482 request.url = GURL("https://www.google.com/");
1483 // when the no authentication data flag is set.
1484 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1485
[email protected]cb9bf6ca2011-01-28 13:15:271486 // Configure against proxy server "myproxy:70".
1487 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1488 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1489 session_deps.net_log = log.bound().net_log();
1490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1491
[email protected]394816e92010-08-03 07:38:591492 // Since we have proxy, should try to establish tunnel.
1493 MockWrite data_writes1[] = {
1494 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1495 "Host: www.google.com\r\n"
1496 "Proxy-Connection: keep-alive\r\n\r\n"),
1497
1498 // After calling trans->RestartWithAuth(), this is the request we should
1499 // be issuing -- the final header line contains the credentials.
1500 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1501 "Host: www.google.com\r\n"
1502 "Proxy-Connection: keep-alive\r\n"
1503 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1504
1505 MockWrite("GET / HTTP/1.1\r\n"
1506 "Host: www.google.com\r\n"
1507 "Connection: keep-alive\r\n\r\n"),
1508 };
1509
1510 // The proxy responds to the connect with a 407, using a persistent
1511 // connection.
1512 MockRead data_reads1[] = {
1513 // No credentials.
1514 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1515 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1516 MockRead("Proxy-Connection: close\r\n\r\n"),
1517
1518 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1519
1520 MockRead("HTTP/1.1 200 OK\r\n"),
1521 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501522 MockRead("Content-Length: 5\r\n\r\n"),
1523 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591524 };
1525
1526 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1527 data_writes1, arraysize(data_writes1));
1528 session_deps.socket_factory.AddSocketDataProvider(&data1);
1529 SSLSocketDataProvider ssl(true, OK);
1530 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1531
1532 TestCompletionCallback callback1;
1533
[email protected]0b0bf032010-09-21 18:08:501534 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1535
[email protected]394816e92010-08-03 07:38:591536 int rv = trans->Start(&request, &callback1, log.bound());
1537 EXPECT_EQ(ERR_IO_PENDING, rv);
1538
1539 rv = callback1.WaitForResult();
1540 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401541 net::CapturingNetLog::EntryList entries;
1542 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591543 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401544 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591545 NetLog::PHASE_NONE);
1546 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401547 entries, pos,
[email protected]394816e92010-08-03 07:38:591548 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1549 NetLog::PHASE_NONE);
1550
1551 const HttpResponseInfo* response = trans->GetResponseInfo();
1552 ASSERT_FALSE(response == NULL);
1553
1554 EXPECT_EQ(407, response->headers->response_code());
1555 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1556
1557 // The password prompt info should have been set in response->auth_challenge.
1558 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1559
1560 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1561 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1562 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1563
1564 TestCompletionCallback callback2;
1565
1566 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1567 EXPECT_EQ(ERR_IO_PENDING, rv);
1568
1569 rv = callback2.WaitForResult();
1570 EXPECT_EQ(OK, rv);
1571
1572 response = trans->GetResponseInfo();
1573 ASSERT_FALSE(response == NULL);
1574
1575 EXPECT_TRUE(response->headers->IsKeepAlive());
1576 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501577 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591578 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1579
1580 // The password prompt info should not be set.
1581 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501582
1583 trans.reset();
[email protected]102e27c2011-02-23 01:01:311584 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591585}
1586
[email protected]11203f012009-11-12 23:02:311587// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321588// proxy connection, when setting up an SSL tunnel.
1589TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271590 HttpRequestInfo request;
1591 request.method = "GET";
1592 request.url = GURL("https://www.google.com/");
1593 // Ensure that proxy authentication is attempted even
1594 // when the no authentication data flag is set.
1595 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1596
[email protected]2d2697f92009-02-18 21:00:321597 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001598 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541599 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1600 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591601 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321602
[email protected]5695b8c2009-09-30 21:36:431603 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321604
[email protected]2d2697f92009-02-18 21:00:321605 // Since we have proxy, should try to establish tunnel.
1606 MockWrite data_writes1[] = {
1607 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451608 "Host: www.google.com\r\n"
1609 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321610
1611 // After calling trans->RestartWithAuth(), this is the request we should
1612 // be issuing -- the final header line contains the credentials.
1613 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1614 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451615 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321616 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1617 };
1618
1619 // The proxy responds to the connect with a 407, using a persistent
1620 // connection.
1621 MockRead data_reads1[] = {
1622 // No credentials.
1623 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1624 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1625 MockRead("Content-Length: 10\r\n\r\n"),
1626 MockRead("0123456789"),
1627
1628 // Wrong credentials (wrong password).
1629 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1630 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1631 MockRead("Content-Length: 10\r\n\r\n"),
1632 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421633 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321634 };
1635
[email protected]31a2bfe2010-02-09 08:03:391636 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1637 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591638 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321639
1640 TestCompletionCallback callback1;
1641
[email protected]dbb83db2010-05-11 18:13:391642 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421643 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321644
1645 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421646 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401647 net::CapturingNetLog::EntryList entries;
1648 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391649 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401650 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391651 NetLog::PHASE_NONE);
1652 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401653 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391654 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1655 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321656
[email protected]1c773ea12009-04-28 19:58:421657 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321658 EXPECT_FALSE(response == NULL);
1659
1660 EXPECT_TRUE(response->headers->IsKeepAlive());
1661 EXPECT_EQ(407, response->headers->response_code());
1662 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421663 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321664
1665 // The password prompt info should have been set in response->auth_challenge.
1666 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1667
[email protected]71e4573a2009-05-21 22:03:001668 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321669 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1670 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1671
1672 TestCompletionCallback callback2;
1673
1674 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441675 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421676 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321677
1678 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421679 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321680
1681 response = trans->GetResponseInfo();
1682 EXPECT_FALSE(response == NULL);
1683
1684 EXPECT_TRUE(response->headers->IsKeepAlive());
1685 EXPECT_EQ(407, response->headers->response_code());
1686 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421687 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321688
1689 // The password prompt info should have been set in response->auth_challenge.
1690 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1691
[email protected]71e4573a2009-05-21 22:03:001692 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321693 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1694 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131695
[email protected]e60e47a2010-07-14 03:37:181696 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1697 // out of scope.
[email protected]102e27c2011-02-23 01:01:311698 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321699}
1700
[email protected]a8e9b162009-03-12 00:06:441701// Test that we don't read the response body when we fail to establish a tunnel,
1702// even if the user cancels the proxy's auth attempt.
1703TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271704 HttpRequestInfo request;
1705 request.method = "GET";
1706 request.url = GURL("https://www.google.com/");
1707 request.load_flags = 0;
1708
[email protected]a8e9b162009-03-12 00:06:441709 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001710 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441711
[email protected]e44de5d2009-06-05 20:12:451712 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441713
[email protected]5695b8c2009-09-30 21:36:431714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441715
[email protected]a8e9b162009-03-12 00:06:441716 // Since we have proxy, should try to establish tunnel.
1717 MockWrite data_writes[] = {
1718 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451719 "Host: www.google.com\r\n"
1720 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441721 };
1722
1723 // The proxy responds to the connect with a 407.
1724 MockRead data_reads[] = {
1725 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1726 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1727 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421728 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441729 };
1730
[email protected]31a2bfe2010-02-09 08:03:391731 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1732 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591733 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441734
1735 TestCompletionCallback callback;
1736
[email protected]5a1d7ca2010-04-28 20:12:271737 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421738 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441739
1740 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421741 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441742
[email protected]1c773ea12009-04-28 19:58:421743 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441744 EXPECT_FALSE(response == NULL);
1745
1746 EXPECT_TRUE(response->headers->IsKeepAlive());
1747 EXPECT_EQ(407, response->headers->response_code());
1748 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421749 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441750
1751 std::string response_data;
1752 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421753 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181754
1755 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311756 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441757}
1758
[email protected]8fdbcd22010-05-05 02:54:521759// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1760// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1761TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521762 HttpRequestInfo request;
1763 request.method = "GET";
1764 request.url = GURL("http://www.google.com/");
1765 request.load_flags = 0;
1766
[email protected]cb9bf6ca2011-01-28 13:15:271767 // We are using a DIRECT connection (i.e. no proxy) for this session.
1768 SessionDependencies session_deps;
1769 scoped_ptr<HttpTransaction> trans(
1770 new HttpNetworkTransaction(CreateSession(&session_deps)));
1771
[email protected]8fdbcd22010-05-05 02:54:521772 MockWrite data_writes1[] = {
1773 MockWrite("GET / HTTP/1.1\r\n"
1774 "Host: www.google.com\r\n"
1775 "Connection: keep-alive\r\n\r\n"),
1776 };
1777
1778 MockRead data_reads1[] = {
1779 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1780 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1781 // Large content-length -- won't matter, as connection will be reset.
1782 MockRead("Content-Length: 10000\r\n\r\n"),
1783 MockRead(false, ERR_FAILED),
1784 };
1785
1786 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1787 data_writes1, arraysize(data_writes1));
1788 session_deps.socket_factory.AddSocketDataProvider(&data1);
1789
1790 TestCompletionCallback callback;
1791
1792 int rv = trans->Start(&request, &callback, BoundNetLog());
1793 EXPECT_EQ(ERR_IO_PENDING, rv);
1794
1795 rv = callback.WaitForResult();
1796 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1797}
1798
[email protected]7a67a8152010-11-05 18:31:101799// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1800// through a non-authenticating proxy. The request should fail with
1801// ERR_UNEXPECTED_PROXY_AUTH.
1802// Note that it is impossible to detect if an HTTP server returns a 407 through
1803// a non-authenticating proxy - there is nothing to indicate whether the
1804// response came from the proxy or the server, so it is treated as if the proxy
1805// issued the challenge.
1806TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271807 HttpRequestInfo request;
1808 request.method = "GET";
1809 request.url = GURL("https://www.google.com/");
1810
[email protected]7a67a8152010-11-05 18:31:101811 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1812 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1813 session_deps.net_log = log.bound().net_log();
1814 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1815
[email protected]7a67a8152010-11-05 18:31:101816 // Since we have proxy, should try to establish tunnel.
1817 MockWrite data_writes1[] = {
1818 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1819 "Host: www.google.com\r\n"
1820 "Proxy-Connection: keep-alive\r\n\r\n"),
1821
1822 MockWrite("GET / HTTP/1.1\r\n"
1823 "Host: www.google.com\r\n"
1824 "Connection: keep-alive\r\n\r\n"),
1825 };
1826
1827 MockRead data_reads1[] = {
1828 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1829
1830 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1831 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1832 MockRead("\r\n"),
1833 MockRead(false, OK),
1834 };
1835
1836 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1837 data_writes1, arraysize(data_writes1));
1838 session_deps.socket_factory.AddSocketDataProvider(&data1);
1839 SSLSocketDataProvider ssl(true, OK);
1840 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1841
1842 TestCompletionCallback callback1;
1843
1844 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1845
1846 int rv = trans->Start(&request, &callback1, log.bound());
1847 EXPECT_EQ(ERR_IO_PENDING, rv);
1848
1849 rv = callback1.WaitForResult();
1850 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401851 net::CapturingNetLog::EntryList entries;
1852 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101853 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401854 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101855 NetLog::PHASE_NONE);
1856 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401857 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101858 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1859 NetLog::PHASE_NONE);
1860}
[email protected]2df19bb2010-08-25 20:13:461861
1862// Test a simple get through an HTTPS Proxy.
1863TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271864 HttpRequestInfo request;
1865 request.method = "GET";
1866 request.url = GURL("http://www.google.com/");
1867
[email protected]2df19bb2010-08-25 20:13:461868 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001869 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461870 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1871 session_deps.net_log = log.bound().net_log();
1872 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1873
[email protected]2df19bb2010-08-25 20:13:461874 // Since we have proxy, should use full url
1875 MockWrite data_writes1[] = {
1876 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1877 "Host: www.google.com\r\n"
1878 "Proxy-Connection: keep-alive\r\n\r\n"),
1879 };
1880
1881 MockRead data_reads1[] = {
1882 MockRead("HTTP/1.1 200 OK\r\n"),
1883 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1884 MockRead("Content-Length: 100\r\n\r\n"),
1885 MockRead(false, OK),
1886 };
1887
1888 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1889 data_writes1, arraysize(data_writes1));
1890 session_deps.socket_factory.AddSocketDataProvider(&data1);
1891 SSLSocketDataProvider ssl(true, OK);
1892 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1893
1894 TestCompletionCallback callback1;
1895
[email protected]0b0bf032010-09-21 18:08:501896 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1897
[email protected]2df19bb2010-08-25 20:13:461898 int rv = trans->Start(&request, &callback1, log.bound());
1899 EXPECT_EQ(ERR_IO_PENDING, rv);
1900
1901 rv = callback1.WaitForResult();
1902 EXPECT_EQ(OK, rv);
1903
1904 const HttpResponseInfo* response = trans->GetResponseInfo();
1905 ASSERT_FALSE(response == NULL);
1906
1907 EXPECT_TRUE(response->headers->IsKeepAlive());
1908 EXPECT_EQ(200, response->headers->response_code());
1909 EXPECT_EQ(100, response->headers->GetContentLength());
1910 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1911
1912 // The password prompt info should not be set.
1913 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1914}
1915
[email protected]7642b5ae2010-09-01 20:55:171916// Test a SPDY get through an HTTPS Proxy.
1917TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271918 HttpRequestInfo request;
1919 request.method = "GET";
1920 request.url = GURL("http://www.google.com/");
1921 request.load_flags = 0;
1922
[email protected]7642b5ae2010-09-01 20:55:171923 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001924 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171925 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1926 session_deps.net_log = log.bound().net_log();
1927 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1928
[email protected]7642b5ae2010-09-01 20:55:171929 // fetch http://www.google.com/ via SPDY
1930 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1931 false));
1932 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1933
1934 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1935 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1936 MockRead spdy_reads[] = {
1937 CreateMockRead(*resp),
1938 CreateMockRead(*data),
1939 MockRead(true, 0, 0),
1940 };
1941
1942 scoped_refptr<DelayedSocketData> spdy_data(
1943 new DelayedSocketData(
1944 1, // wait for one write to finish before reading.
1945 spdy_reads, arraysize(spdy_reads),
1946 spdy_writes, arraysize(spdy_writes)));
1947 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1948
1949 SSLSocketDataProvider ssl(true, OK);
1950 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1951 ssl.next_proto = "spdy/2";
1952 ssl.was_npn_negotiated = true;
1953 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1954
1955 TestCompletionCallback callback1;
1956
[email protected]0b0bf032010-09-21 18:08:501957 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1958
[email protected]7642b5ae2010-09-01 20:55:171959 int rv = trans->Start(&request, &callback1, log.bound());
1960 EXPECT_EQ(ERR_IO_PENDING, rv);
1961
1962 rv = callback1.WaitForResult();
1963 EXPECT_EQ(OK, rv);
1964
1965 const HttpResponseInfo* response = trans->GetResponseInfo();
1966 ASSERT_TRUE(response != NULL);
1967 ASSERT_TRUE(response->headers != NULL);
1968 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1969
1970 std::string response_data;
1971 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1972 EXPECT_EQ(net::kUploadData, response_data);
1973}
1974
[email protected]dc7bd1c52010-11-12 00:01:131975// Test a SPDY get through an HTTPS Proxy.
1976TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:271977 HttpRequestInfo request;
1978 request.method = "GET";
1979 request.url = GURL("http://www.google.com/");
1980 request.load_flags = 0;
1981
[email protected]dc7bd1c52010-11-12 00:01:131982 // Configure against https proxy server "proxy:70".
1983 SessionDependencies session_deps(
1984 ProxyService::CreateFixed("https://proxy:70"));
1985 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1986 session_deps.net_log = log.bound().net_log();
1987 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1988
[email protected]dc7bd1c52010-11-12 00:01:131989 // The first request will be a bare GET, the second request will be a
1990 // GET with a Proxy-Authorization header.
1991 scoped_ptr<spdy::SpdyFrame> req_get(
1992 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
1993 const char* const kExtraAuthorizationHeaders[] = {
1994 "proxy-authorization",
1995 "Basic Zm9vOmJhcg==",
1996 };
1997 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
1998 ConstructSpdyGet(
1999 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2000 false, 3, LOWEST, false));
2001 MockWrite spdy_writes[] = {
2002 CreateMockWrite(*req_get, 1),
2003 CreateMockWrite(*req_get_authorization, 4),
2004 };
2005
2006 // The first response is a 407 proxy authentication challenge, and the second
2007 // response will be a 200 response since the second request includes a valid
2008 // Authorization header.
2009 const char* const kExtraAuthenticationHeaders[] = {
2010 "Proxy-Authenticate",
2011 "Basic realm=\"MyRealm1\""
2012 };
2013 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2014 ConstructSpdySynReplyError(
2015 "407 Proxy Authentication Required",
2016 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2017 1));
2018 scoped_ptr<spdy::SpdyFrame> body_authentication(
2019 ConstructSpdyBodyFrame(1, true));
2020 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2021 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2022 MockRead spdy_reads[] = {
2023 CreateMockRead(*resp_authentication, 2),
2024 CreateMockRead(*body_authentication, 3),
2025 CreateMockRead(*resp_data, 5),
2026 CreateMockRead(*body_data, 6),
2027 MockRead(true, 0, 7),
2028 };
2029
2030 scoped_refptr<OrderedSocketData> data(
2031 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2032 spdy_writes, arraysize(spdy_writes)));
2033 session_deps.socket_factory.AddSocketDataProvider(data);
2034
2035 SSLSocketDataProvider ssl(true, OK);
2036 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2037 ssl.next_proto = "spdy/2";
2038 ssl.was_npn_negotiated = true;
2039 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2040
2041 TestCompletionCallback callback1;
2042
2043 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2044
2045 int rv = trans->Start(&request, &callback1, log.bound());
2046 EXPECT_EQ(ERR_IO_PENDING, rv);
2047
2048 rv = callback1.WaitForResult();
2049 EXPECT_EQ(OK, rv);
2050
2051 const HttpResponseInfo* const response = trans->GetResponseInfo();
2052
2053 ASSERT_TRUE(response != NULL);
2054 ASSERT_TRUE(response->headers != NULL);
2055 EXPECT_EQ(407, response->headers->response_code());
2056 EXPECT_TRUE(response->was_fetched_via_spdy);
2057
2058 // The password prompt info should have been set in response->auth_challenge.
2059 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2060 EXPECT_TRUE(response->auth_challenge->is_proxy);
2061 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2062 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2063 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2064
2065 TestCompletionCallback callback2;
2066
2067 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2068 EXPECT_EQ(ERR_IO_PENDING, rv);
2069
2070 rv = callback2.WaitForResult();
2071 EXPECT_EQ(OK, rv);
2072
2073 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2074
2075 ASSERT_TRUE(response_restart != NULL);
2076 ASSERT_TRUE(response_restart->headers != NULL);
2077 EXPECT_EQ(200, response_restart->headers->response_code());
2078 // The password prompt info should not be set.
2079 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2080}
2081
[email protected]d9da5fe2010-10-13 22:37:162082// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2083TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272084 HttpRequestInfo request;
2085 request.method = "GET";
2086 request.url = GURL("https://www.google.com/");
2087 request.load_flags = 0;
2088
[email protected]d9da5fe2010-10-13 22:37:162089 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002090 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162091 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2092 session_deps.net_log = log.bound().net_log();
2093 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2094
2095 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2096
[email protected]d9da5fe2010-10-13 22:37:162097 // CONNECT to www.google.com:443 via SPDY
2098 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2099 // fetch https://www.google.com/ via HTTP
2100
2101 const char get[] = "GET / HTTP/1.1\r\n"
2102 "Host: www.google.com\r\n"
2103 "Connection: keep-alive\r\n\r\n";
2104 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2105 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2106 MockWrite spdy_writes[] = {
2107 CreateMockWrite(*connect, 1),
2108 CreateMockWrite(*wrapped_get, 3)
2109 };
2110
2111 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2112 const char resp[] = "HTTP/1.1 200 OK\r\n"
2113 "Content-Length: 10\r\n\r\n";
2114
2115 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2116 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2117 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2118 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2119 MockRead spdy_reads[] = {
2120 CreateMockRead(*conn_resp, 2, true),
2121 CreateMockRead(*wrapped_get_resp, 4, true),
2122 CreateMockRead(*wrapped_body, 5, true),
2123 CreateMockRead(*wrapped_body, 6, true),
2124 MockRead(true, 0, 7),
2125 };
2126
2127 scoped_refptr<OrderedSocketData> spdy_data(
2128 new OrderedSocketData(
2129 spdy_reads, arraysize(spdy_reads),
2130 spdy_writes, arraysize(spdy_writes)));
2131 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2132
2133 SSLSocketDataProvider ssl(true, OK);
2134 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2135 ssl.next_proto = "spdy/2";
2136 ssl.was_npn_negotiated = true;
2137 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2138 SSLSocketDataProvider ssl2(true, OK);
2139 ssl2.was_npn_negotiated = false;
2140 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2141
2142 TestCompletionCallback callback1;
2143
2144 int rv = trans->Start(&request, &callback1, log.bound());
2145 EXPECT_EQ(ERR_IO_PENDING, rv);
2146
2147 rv = callback1.WaitForResult();
2148 EXPECT_EQ(OK, rv);
2149
2150 const HttpResponseInfo* response = trans->GetResponseInfo();
2151 ASSERT_TRUE(response != NULL);
2152 ASSERT_TRUE(response->headers != NULL);
2153 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2154
2155 std::string response_data;
2156 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2157 EXPECT_EQ("1234567890", response_data);
2158}
2159
2160// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2161TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272162 HttpRequestInfo request;
2163 request.method = "GET";
2164 request.url = GURL("https://www.google.com/");
2165 request.load_flags = 0;
2166
[email protected]d9da5fe2010-10-13 22:37:162167 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002168 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162169 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2170 session_deps.net_log = log.bound().net_log();
2171 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2172
2173 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2174
[email protected]d9da5fe2010-10-13 22:37:162175 // CONNECT to www.google.com:443 via SPDY
2176 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2177 // fetch https://www.google.com/ via SPDY
2178 const char* const kMyUrl = "https://www.google.com/";
2179 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2180 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2181 MockWrite spdy_writes[] = {
2182 CreateMockWrite(*connect, 1),
2183 CreateMockWrite(*wrapped_get, 3)
2184 };
2185
2186 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2187 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2188 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2189 ConstructWrappedSpdyFrame(get_resp, 1));
2190 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2191 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2192 MockRead spdy_reads[] = {
2193 CreateMockRead(*conn_resp, 2, true),
2194 CreateMockRead(*wrapped_get_resp, 4, true),
2195 CreateMockRead(*wrapped_body, 5, true),
2196 MockRead(true, 0, 1),
2197 };
2198
2199 scoped_refptr<OrderedSocketData> spdy_data(
2200 new OrderedSocketData(
2201 spdy_reads, arraysize(spdy_reads),
2202 spdy_writes, arraysize(spdy_writes)));
2203 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2204
2205 SSLSocketDataProvider ssl(true, OK);
2206 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2207 ssl.next_proto = "spdy/2";
2208 ssl.was_npn_negotiated = true;
2209 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2210 SSLSocketDataProvider ssl2(true, OK);
2211 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2212 ssl2.next_proto = "spdy/2";
2213 ssl2.was_npn_negotiated = true;
2214 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2215
2216 TestCompletionCallback callback1;
2217
2218 int rv = trans->Start(&request, &callback1, log.bound());
2219 EXPECT_EQ(ERR_IO_PENDING, rv);
2220
2221 rv = callback1.WaitForResult();
2222 EXPECT_EQ(OK, rv);
2223
2224 const HttpResponseInfo* response = trans->GetResponseInfo();
2225 ASSERT_TRUE(response != NULL);
2226 ASSERT_TRUE(response->headers != NULL);
2227 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2228
2229 std::string response_data;
2230 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2231 EXPECT_EQ(net::kUploadData, response_data);
2232}
2233
2234// Test a SPDY CONNECT failure through an HTTPS Proxy.
2235TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272236 HttpRequestInfo request;
2237 request.method = "GET";
2238 request.url = GURL("https://www.google.com/");
2239 request.load_flags = 0;
2240
[email protected]d9da5fe2010-10-13 22:37:162241 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002242 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162243 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2244 session_deps.net_log = log.bound().net_log();
2245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2246
2247 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2248
[email protected]d9da5fe2010-10-13 22:37:162249 // CONNECT to www.google.com:443 via SPDY
2250 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2251 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2252
2253 MockWrite spdy_writes[] = {
2254 CreateMockWrite(*connect, 1),
2255 CreateMockWrite(*get, 3),
2256 };
2257
2258 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2259 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2260 MockRead spdy_reads[] = {
2261 CreateMockRead(*resp, 2, true),
2262 MockRead(true, 0, 4),
2263 };
2264
2265 scoped_refptr<OrderedSocketData> spdy_data(
2266 new OrderedSocketData(
2267 spdy_reads, arraysize(spdy_reads),
2268 spdy_writes, arraysize(spdy_writes)));
2269 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2270
2271 SSLSocketDataProvider ssl(true, OK);
2272 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2273 ssl.next_proto = "spdy/2";
2274 ssl.was_npn_negotiated = true;
2275 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2276 SSLSocketDataProvider ssl2(true, OK);
2277 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2278 ssl2.next_proto = "spdy/2";
2279 ssl2.was_npn_negotiated = true;
2280 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2281
2282 TestCompletionCallback callback1;
2283
2284 int rv = trans->Start(&request, &callback1, log.bound());
2285 EXPECT_EQ(ERR_IO_PENDING, rv);
2286
2287 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292288 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162289
2290 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292291 ASSERT_FALSE(response == NULL);
2292 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162293}
2294
[email protected]2df19bb2010-08-25 20:13:462295// Test the challenge-response-retry sequence through an HTTPS Proxy
2296TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462297 HttpRequestInfo request;
2298 request.method = "GET";
2299 request.url = GURL("http://www.google.com/");
2300 // when the no authentication data flag is set.
2301 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2302
[email protected]cb9bf6ca2011-01-28 13:15:272303 // Configure against https proxy server "proxy:70".
2304 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2305 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2306 session_deps.net_log = log.bound().net_log();
2307 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2308
[email protected]2df19bb2010-08-25 20:13:462309 // Since we have proxy, should use full url
2310 MockWrite data_writes1[] = {
2311 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2312 "Host: www.google.com\r\n"
2313 "Proxy-Connection: keep-alive\r\n\r\n"),
2314
2315 // After calling trans->RestartWithAuth(), this is the request we should
2316 // be issuing -- the final header line contains the credentials.
2317 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2318 "Host: www.google.com\r\n"
2319 "Proxy-Connection: keep-alive\r\n"
2320 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2321 };
2322
2323 // The proxy responds to the GET with a 407, using a persistent
2324 // connection.
2325 MockRead data_reads1[] = {
2326 // No credentials.
2327 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2328 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2329 MockRead("Proxy-Connection: keep-alive\r\n"),
2330 MockRead("Content-Length: 0\r\n\r\n"),
2331
2332 MockRead("HTTP/1.1 200 OK\r\n"),
2333 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2334 MockRead("Content-Length: 100\r\n\r\n"),
2335 MockRead(false, OK),
2336 };
2337
2338 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2339 data_writes1, arraysize(data_writes1));
2340 session_deps.socket_factory.AddSocketDataProvider(&data1);
2341 SSLSocketDataProvider ssl(true, OK);
2342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2343
2344 TestCompletionCallback callback1;
2345
[email protected]0b0bf032010-09-21 18:08:502346 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2347
[email protected]2df19bb2010-08-25 20:13:462348 int rv = trans->Start(&request, &callback1, log.bound());
2349 EXPECT_EQ(ERR_IO_PENDING, rv);
2350
2351 rv = callback1.WaitForResult();
2352 EXPECT_EQ(OK, rv);
2353
2354 const HttpResponseInfo* response = trans->GetResponseInfo();
2355 ASSERT_FALSE(response == NULL);
2356
2357 EXPECT_EQ(407, response->headers->response_code());
2358 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2359
2360 // The password prompt info should have been set in response->auth_challenge.
2361 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2362
2363 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2364 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2365 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2366
2367 TestCompletionCallback callback2;
2368
2369 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2370 EXPECT_EQ(ERR_IO_PENDING, rv);
2371
2372 rv = callback2.WaitForResult();
2373 EXPECT_EQ(OK, rv);
2374
2375 response = trans->GetResponseInfo();
2376 ASSERT_FALSE(response == NULL);
2377
2378 EXPECT_TRUE(response->headers->IsKeepAlive());
2379 EXPECT_EQ(200, response->headers->response_code());
2380 EXPECT_EQ(100, response->headers->GetContentLength());
2381 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2382
2383 // The password prompt info should not be set.
2384 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2385}
2386
[email protected]ff007e162009-05-23 09:13:152387void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082388 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422389 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082390 request.method = "GET";
2391 request.url = GURL("https://www.google.com/");
2392 request.load_flags = 0;
2393
[email protected]cb9bf6ca2011-01-28 13:15:272394 // Configure against proxy server "myproxy:70".
2395 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2396
2397 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2398
[email protected]c744cf22009-02-27 07:28:082399 // Since we have proxy, should try to establish tunnel.
2400 MockWrite data_writes[] = {
2401 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452402 "Host: www.google.com\r\n"
2403 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082404 };
2405
2406 MockRead data_reads[] = {
2407 status,
2408 MockRead("Content-Length: 10\r\n\r\n"),
2409 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422410 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082411 };
2412
[email protected]31a2bfe2010-02-09 08:03:392413 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2414 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592415 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082416
2417 TestCompletionCallback callback;
2418
[email protected]0b0bf032010-09-21 18:08:502419 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2420
[email protected]5a1d7ca2010-04-28 20:12:272421 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422422 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082423
2424 rv = callback.WaitForResult();
2425 EXPECT_EQ(expected_status, rv);
2426}
2427
[email protected]ff007e162009-05-23 09:13:152428void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082429 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422430 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082431}
2432
2433TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2434 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2435}
2436
2437TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2438 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2439}
2440
2441TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2442 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2443}
2444
2445TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2446 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2447}
2448
2449TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2450 ConnectStatusHelper(
2451 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2452}
2453
2454TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2455 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2456}
2457
2458TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2459 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2460}
2461
2462TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2463 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2464}
2465
2466TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2467 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2468}
2469
2470TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2471 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2472}
2473
2474TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2475 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2476}
2477
2478TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2479 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2480}
2481
2482TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2483 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2484}
2485
2486TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2487 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2488}
2489
2490TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2491 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2492}
2493
2494TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2495 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2496}
2497
2498TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2499 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2500}
2501
2502TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2503 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2504}
2505
2506TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2507 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2508}
2509
2510TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2511 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2512}
2513
2514TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2515 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2516}
2517
2518TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2519 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2520}
2521
2522TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2523 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2524}
2525
2526TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2527 ConnectStatusHelperWithExpectedStatus(
2528 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542529 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082530}
2531
2532TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2533 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2534}
2535
2536TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2537 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2538}
2539
2540TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2541 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2542}
2543
2544TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2545 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2546}
2547
2548TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2549 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2550}
2551
2552TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2553 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2554}
2555
2556TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2557 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2558}
2559
2560TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2561 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2562}
2563
2564TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2565 ConnectStatusHelper(
2566 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2567}
2568
2569TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2570 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2571}
2572
2573TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2574 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2575}
2576
2577TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2578 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2579}
2580
2581TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2582 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2586 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2590 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2591}
2592
2593TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2594 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2595}
2596
[email protected]038e9a32008-10-08 22:40:162597// Test the flow when both the proxy server AND origin server require
2598// authentication. Again, this uses basic auth for both since that is
2599// the simplest to mock.
2600TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272601 HttpRequestInfo request;
2602 request.method = "GET";
2603 request.url = GURL("http://www.google.com/");
2604 request.load_flags = 0;
2605
[email protected]81cdfcd2010-10-16 00:49:002606 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012607
[email protected]038e9a32008-10-08 22:40:162608 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422609 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432610 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162611
[email protected]f9ee6b52008-11-08 06:46:232612 MockWrite data_writes1[] = {
2613 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2614 "Host: www.google.com\r\n"
2615 "Proxy-Connection: keep-alive\r\n\r\n"),
2616 };
2617
[email protected]038e9a32008-10-08 22:40:162618 MockRead data_reads1[] = {
2619 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2620 // Give a couple authenticate options (only the middle one is actually
2621 // supported).
[email protected]22927ad2009-09-21 19:56:192622 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162623 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2624 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2625 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2626 // Large content-length -- won't matter, as connection will be reset.
2627 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422628 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162629 };
2630
2631 // After calling trans->RestartWithAuth() the first time, this is the
2632 // request we should be issuing -- the final header line contains the
2633 // proxy's credentials.
2634 MockWrite data_writes2[] = {
2635 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2636 "Host: www.google.com\r\n"
2637 "Proxy-Connection: keep-alive\r\n"
2638 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2639 };
2640
2641 // Now the proxy server lets the request pass through to origin server.
2642 // The origin server responds with a 401.
2643 MockRead data_reads2[] = {
2644 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2645 // Note: We are using the same realm-name as the proxy server. This is
2646 // completely valid, as realms are unique across hosts.
2647 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2648 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2649 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422650 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162651 };
2652
2653 // After calling trans->RestartWithAuth() the second time, we should send
2654 // the credentials for both the proxy and origin server.
2655 MockWrite data_writes3[] = {
2656 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2657 "Host: www.google.com\r\n"
2658 "Proxy-Connection: keep-alive\r\n"
2659 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2660 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2661 };
2662
2663 // Lastly we get the desired content.
2664 MockRead data_reads3[] = {
2665 MockRead("HTTP/1.0 200 OK\r\n"),
2666 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2667 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422668 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162669 };
2670
[email protected]31a2bfe2010-02-09 08:03:392671 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2672 data_writes1, arraysize(data_writes1));
2673 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2674 data_writes2, arraysize(data_writes2));
2675 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2676 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592677 session_deps.socket_factory.AddSocketDataProvider(&data1);
2678 session_deps.socket_factory.AddSocketDataProvider(&data2);
2679 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162680
2681 TestCompletionCallback callback1;
2682
[email protected]5a1d7ca2010-04-28 20:12:272683 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422684 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162685
2686 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422687 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162688
[email protected]1c773ea12009-04-28 19:58:422689 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162690 EXPECT_FALSE(response == NULL);
2691
2692 // The password prompt info should have been set in response->auth_challenge.
2693 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2694
[email protected]71e4573a2009-05-21 22:03:002695 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162696 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2697 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2698
2699 TestCompletionCallback callback2;
2700
[email protected]13c8a092010-07-29 06:15:442701 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422702 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162703
2704 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422705 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162706
2707 response = trans->GetResponseInfo();
2708 EXPECT_FALSE(response == NULL);
2709 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2710
[email protected]71e4573a2009-05-21 22:03:002711 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162712 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2713 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2714
2715 TestCompletionCallback callback3;
2716
[email protected]13c8a092010-07-29 06:15:442717 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422718 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162719
2720 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422721 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162722
2723 response = trans->GetResponseInfo();
2724 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2725 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162726}
[email protected]4ddaf2502008-10-23 18:26:192727
[email protected]ea9dc9a2009-09-05 00:43:322728// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2729// can't hook into its internals to cause it to generate predictable NTLM
2730// authorization headers.
2731#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292732// The NTLM authentication unit tests were generated by capturing the HTTP
2733// requests and responses using Fiddler 2 and inspecting the generated random
2734// bytes in the debugger.
2735
2736// Enter the correct password and authenticate successfully.
2737TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422738 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242739 request.method = "GET";
2740 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2741 request.load_flags = 0;
2742
[email protected]cb9bf6ca2011-01-28 13:15:272743 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2744 MockGetHostName);
2745 SessionDependencies session_deps;
2746 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2747
[email protected]3f918782009-02-28 01:29:242748 MockWrite data_writes1[] = {
2749 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2750 "Host: 172.22.68.17\r\n"
2751 "Connection: keep-alive\r\n\r\n"),
2752 };
2753
2754 MockRead data_reads1[] = {
2755 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042756 // Negotiate and NTLM are often requested together. However, we only want
2757 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2758 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242759 MockRead("WWW-Authenticate: NTLM\r\n"),
2760 MockRead("Connection: close\r\n"),
2761 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362762 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242763 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422764 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242765 };
2766
2767 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222768 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242769 // request we should be issuing -- the final header line contains a Type
2770 // 1 message.
2771 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2772 "Host: 172.22.68.17\r\n"
2773 "Connection: keep-alive\r\n"
2774 "Authorization: NTLM "
2775 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2776
2777 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2778 // (the credentials for the origin server). The second request continues
2779 // on the same connection.
2780 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2781 "Host: 172.22.68.17\r\n"
2782 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292783 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2784 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2785 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2786 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2787 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242788 };
2789
2790 MockRead data_reads2[] = {
2791 // The origin server responds with a Type 2 message.
2792 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2793 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292794 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242795 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2796 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2797 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2798 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2799 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2800 "BtAAAAAAA=\r\n"),
2801 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362802 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242803 MockRead("You are not authorized to view this page\r\n"),
2804
2805 // Lastly we get the desired content.
2806 MockRead("HTTP/1.1 200 OK\r\n"),
2807 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2808 MockRead("Content-Length: 13\r\n\r\n"),
2809 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422810 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242811 };
2812
[email protected]31a2bfe2010-02-09 08:03:392813 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2814 data_writes1, arraysize(data_writes1));
2815 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2816 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592817 session_deps.socket_factory.AddSocketDataProvider(&data1);
2818 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242819
2820 TestCompletionCallback callback1;
2821
[email protected]0b0bf032010-09-21 18:08:502822 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2823
[email protected]5a1d7ca2010-04-28 20:12:272824 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422825 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242826
2827 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422828 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242829
[email protected]0757e7702009-03-27 04:00:222830 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2831
[email protected]1c773ea12009-04-28 19:58:422832 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:252833 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:242834
[email protected]aef04272010-06-28 18:03:042835 // The password prompt info should have been set in
2836 // response->auth_challenge.
[email protected]10af5fe72011-01-31 16:17:252837 ASSERT_FALSE(response->auth_challenge.get() == NULL);
[email protected]3f918782009-02-28 01:29:242838
[email protected]71e4573a2009-05-21 22:03:002839 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242840 EXPECT_EQ(L"", response->auth_challenge->realm);
2841 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2842
[email protected]10af5fe72011-01-31 16:17:252843 TestCompletionCallback callback2;
2844
2845 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2846 EXPECT_EQ(ERR_IO_PENDING, rv);
2847
2848 rv = callback2.WaitForResult();
2849 EXPECT_EQ(OK, rv);
2850
2851 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2852
2853 response = trans->GetResponseInfo();
2854 ASSERT_TRUE(response != NULL);
2855
2856 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2857
[email protected]0757e7702009-03-27 04:00:222858 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242859
[email protected]10af5fe72011-01-31 16:17:252860 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422861 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242862
[email protected]0757e7702009-03-27 04:00:222863 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422864 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242865
2866 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042867 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242868 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2869 EXPECT_EQ(13, response->headers->GetContentLength());
2870}
2871
[email protected]385a4672009-03-11 22:21:292872// Enter a wrong password, and then the correct one.
2873TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422874 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292875 request.method = "GET";
2876 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2877 request.load_flags = 0;
2878
[email protected]cb9bf6ca2011-01-28 13:15:272879 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2880 MockGetHostName);
2881 SessionDependencies session_deps;
2882 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2883
[email protected]385a4672009-03-11 22:21:292884 MockWrite data_writes1[] = {
2885 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2886 "Host: 172.22.68.17\r\n"
2887 "Connection: keep-alive\r\n\r\n"),
2888 };
2889
2890 MockRead data_reads1[] = {
2891 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042892 // Negotiate and NTLM are often requested together. However, we only want
2893 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2894 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292895 MockRead("WWW-Authenticate: NTLM\r\n"),
2896 MockRead("Connection: close\r\n"),
2897 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362898 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292899 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422900 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292901 };
2902
2903 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222904 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292905 // request we should be issuing -- the final header line contains a Type
2906 // 1 message.
2907 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2908 "Host: 172.22.68.17\r\n"
2909 "Connection: keep-alive\r\n"
2910 "Authorization: NTLM "
2911 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2912
2913 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2914 // (the credentials for the origin server). The second request continues
2915 // on the same connection.
2916 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2917 "Host: 172.22.68.17\r\n"
2918 "Connection: keep-alive\r\n"
2919 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2920 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2921 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2922 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2923 "4Ww7b7E=\r\n\r\n"),
2924 };
2925
2926 MockRead data_reads2[] = {
2927 // The origin server responds with a Type 2 message.
2928 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2929 MockRead("WWW-Authenticate: NTLM "
2930 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2931 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2932 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2933 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2934 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2935 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2936 "BtAAAAAAA=\r\n"),
2937 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362938 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292939 MockRead("You are not authorized to view this page\r\n"),
2940
2941 // Wrong password.
2942 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292943 MockRead("WWW-Authenticate: NTLM\r\n"),
2944 MockRead("Connection: close\r\n"),
2945 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362946 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292947 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422948 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292949 };
2950
2951 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222952 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292953 // request we should be issuing -- the final header line contains a Type
2954 // 1 message.
2955 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2956 "Host: 172.22.68.17\r\n"
2957 "Connection: keep-alive\r\n"
2958 "Authorization: NTLM "
2959 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2960
2961 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2962 // (the credentials for the origin server). The second request continues
2963 // on the same connection.
2964 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2965 "Host: 172.22.68.17\r\n"
2966 "Connection: keep-alive\r\n"
2967 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2968 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2969 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2970 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2971 "+4MUm7c=\r\n\r\n"),
2972 };
2973
2974 MockRead data_reads3[] = {
2975 // The origin server responds with a Type 2 message.
2976 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2977 MockRead("WWW-Authenticate: NTLM "
2978 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2979 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2980 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2981 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2982 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2983 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2984 "BtAAAAAAA=\r\n"),
2985 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362986 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292987 MockRead("You are not authorized to view this page\r\n"),
2988
2989 // Lastly we get the desired content.
2990 MockRead("HTTP/1.1 200 OK\r\n"),
2991 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2992 MockRead("Content-Length: 13\r\n\r\n"),
2993 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422994 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292995 };
2996
[email protected]31a2bfe2010-02-09 08:03:392997 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2998 data_writes1, arraysize(data_writes1));
2999 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3000 data_writes2, arraysize(data_writes2));
3001 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3002 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593003 session_deps.socket_factory.AddSocketDataProvider(&data1);
3004 session_deps.socket_factory.AddSocketDataProvider(&data2);
3005 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293006
3007 TestCompletionCallback callback1;
3008
[email protected]0b0bf032010-09-21 18:08:503009 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3010
[email protected]5a1d7ca2010-04-28 20:12:273011 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423012 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293013
3014 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423015 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293016
[email protected]0757e7702009-03-27 04:00:223017 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293018
[email protected]1c773ea12009-04-28 19:58:423019 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293020 EXPECT_FALSE(response == NULL);
3021
3022 // The password prompt info should have been set in response->auth_challenge.
3023 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3024
[email protected]71e4573a2009-05-21 22:03:003025 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293026 EXPECT_EQ(L"", response->auth_challenge->realm);
3027 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3028
[email protected]10af5fe72011-01-31 16:17:253029 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293030
[email protected]0757e7702009-03-27 04:00:223031 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253032 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423033 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293034
[email protected]10af5fe72011-01-31 16:17:253035 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423036 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293037
[email protected]0757e7702009-03-27 04:00:223038 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:253039 TestCompletionCallback callback3;
3040 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423041 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253042 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423043 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223044 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3045
3046 response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:253047 ASSERT_TRUE(response != NULL);
[email protected]0757e7702009-03-27 04:00:223048
3049 // The password prompt info should have been set in response->auth_challenge.
3050 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3051
[email protected]71e4573a2009-05-21 22:03:003052 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223053 EXPECT_EQ(L"", response->auth_challenge->realm);
3054 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3055
[email protected]10af5fe72011-01-31 16:17:253056 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223057
3058 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253059 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3060 EXPECT_EQ(ERR_IO_PENDING, rv);
3061
3062 rv = callback4.WaitForResult();
3063 EXPECT_EQ(OK, rv);
3064
3065 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3066
3067 TestCompletionCallback callback5;
3068
3069 // One more roundtrip
3070 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423071 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223072
3073 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423074 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223075
[email protected]385a4672009-03-11 22:21:293076 response = trans->GetResponseInfo();
3077 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3078 EXPECT_EQ(13, response->headers->GetContentLength());
3079}
[email protected]ea9dc9a2009-09-05 00:43:323080#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293081
[email protected]4ddaf2502008-10-23 18:26:193082// Test reading a server response which has only headers, and no body.
3083// After some maximum number of bytes is consumed, the transaction should
3084// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3085TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423086 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193087 request.method = "GET";
3088 request.url = GURL("http://www.google.com/");
3089 request.load_flags = 0;
3090
[email protected]cb9bf6ca2011-01-28 13:15:273091 SessionDependencies session_deps;
3092 scoped_ptr<HttpTransaction> trans(
3093 new HttpNetworkTransaction(CreateSession(&session_deps)));
3094
[email protected]b75b7b2f2009-10-06 00:54:533095 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433096 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533097 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193098
3099 MockRead data_reads[] = {
3100 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433101 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193102 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423103 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193104 };
[email protected]31a2bfe2010-02-09 08:03:393105 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593106 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193107
3108 TestCompletionCallback callback;
3109
[email protected]5a1d7ca2010-04-28 20:12:273110 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423111 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193112
3113 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423114 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193115
[email protected]1c773ea12009-04-28 19:58:423116 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193117 EXPECT_TRUE(response == NULL);
3118}
[email protected]f4e426b2008-11-05 00:24:493119
3120// Make sure that we don't try to reuse a TCPClientSocket when failing to
3121// establish tunnel.
3122// http://code.google.com/p/chromium/issues/detail?id=3772
3123TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273124 HttpRequestInfo request;
3125 request.method = "GET";
3126 request.url = GURL("https://www.google.com/");
3127 request.load_flags = 0;
3128
[email protected]f4e426b2008-11-05 00:24:493129 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003130 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013131
[email protected]228ff742009-06-05 01:19:593132 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493133
[email protected]5695b8c2009-09-30 21:36:433134 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493135
[email protected]f4e426b2008-11-05 00:24:493136 // Since we have proxy, should try to establish tunnel.
3137 MockWrite data_writes1[] = {
3138 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453139 "Host: www.google.com\r\n"
3140 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493141 };
3142
[email protected]77848d12008-11-14 00:00:223143 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493144 // connection. Usually a proxy would return 501 (not implemented),
3145 // or 200 (tunnel established).
3146 MockRead data_reads1[] = {
3147 MockRead("HTTP/1.1 404 Not Found\r\n"),
3148 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423149 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493150 };
3151
[email protected]31a2bfe2010-02-09 08:03:393152 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3153 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593154 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493155
3156 TestCompletionCallback callback1;
3157
[email protected]5a1d7ca2010-04-28 20:12:273158 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423159 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493160
3161 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423162 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493163
[email protected]1c773ea12009-04-28 19:58:423164 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083165 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493166
[email protected]b4404c02009-04-10 16:38:523167 // Empty the current queue. This is necessary because idle sockets are
3168 // added to the connection pool asynchronously with a PostTask.
3169 MessageLoop::current()->RunAllPending();
3170
[email protected]f4e426b2008-11-05 00:24:493171 // We now check to make sure the TCPClientSocket was not added back to
3172 // the pool.
[email protected]a937a06d2009-08-19 21:19:243173 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493174 trans.reset();
[email protected]b4404c02009-04-10 16:38:523175 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493176 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:243177 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493178}
[email protected]372d34a2008-11-05 21:30:513179
[email protected]1b157c02009-04-21 01:55:403180// Make sure that we recycle a socket after reading all of the response body.
3181TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423182 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403183 request.method = "GET";
3184 request.url = GURL("http://www.google.com/");
3185 request.load_flags = 0;
3186
[email protected]cb9bf6ca2011-01-28 13:15:273187 SessionDependencies session_deps;
3188 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3189
3190 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3191
[email protected]1b157c02009-04-21 01:55:403192 MockRead data_reads[] = {
3193 // A part of the response body is received with the response headers.
3194 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3195 // The rest of the response body is received in two parts.
3196 MockRead("lo"),
3197 MockRead(" world"),
3198 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423199 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403200 };
3201
[email protected]31a2bfe2010-02-09 08:03:393202 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593203 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403204
3205 TestCompletionCallback callback;
3206
[email protected]5a1d7ca2010-04-28 20:12:273207 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423208 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403209
3210 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423211 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403212
[email protected]1c773ea12009-04-28 19:58:423213 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403214 EXPECT_TRUE(response != NULL);
3215
3216 EXPECT_TRUE(response->headers != NULL);
3217 std::string status_line = response->headers->GetStatusLine();
3218 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3219
[email protected]a937a06d2009-08-19 21:19:243220 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403221
3222 std::string response_data;
3223 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403225 EXPECT_EQ("hello world", response_data);
3226
3227 // Empty the current queue. This is necessary because idle sockets are
3228 // added to the connection pool asynchronously with a PostTask.
3229 MessageLoop::current()->RunAllPending();
3230
3231 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243232 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403233}
3234
[email protected]76a505b2010-08-25 06:23:003235// Make sure that we recycle a SSL socket after reading all of the response
3236// body.
3237TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3238 SessionDependencies session_deps;
3239 HttpRequestInfo request;
3240 request.method = "GET";
3241 request.url = GURL("https://www.google.com/");
3242 request.load_flags = 0;
3243
3244 MockWrite data_writes[] = {
3245 MockWrite("GET / HTTP/1.1\r\n"
3246 "Host: www.google.com\r\n"
3247 "Connection: keep-alive\r\n\r\n"),
3248 };
3249
3250 MockRead data_reads[] = {
3251 MockRead("HTTP/1.1 200 OK\r\n"),
3252 MockRead("Content-Length: 11\r\n\r\n"),
3253 MockRead("hello world"),
3254 MockRead(false, OK),
3255 };
3256
3257 SSLSocketDataProvider ssl(true, OK);
3258 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3259
3260 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3261 data_writes, arraysize(data_writes));
3262 session_deps.socket_factory.AddSocketDataProvider(&data);
3263
3264 TestCompletionCallback callback;
3265
3266 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3267 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3268
3269 int rv = trans->Start(&request, &callback, BoundNetLog());
3270
3271 EXPECT_EQ(ERR_IO_PENDING, rv);
3272 EXPECT_EQ(OK, callback.WaitForResult());
3273
3274 const HttpResponseInfo* response = trans->GetResponseInfo();
3275 ASSERT_TRUE(response != NULL);
3276 ASSERT_TRUE(response->headers != NULL);
3277 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3278
3279 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3280
3281 std::string response_data;
3282 rv = ReadTransaction(trans.get(), &response_data);
3283 EXPECT_EQ(OK, rv);
3284 EXPECT_EQ("hello world", response_data);
3285
3286 // Empty the current queue. This is necessary because idle sockets are
3287 // added to the connection pool asynchronously with a PostTask.
3288 MessageLoop::current()->RunAllPending();
3289
3290 // We now check to make sure the socket was added back to the pool.
3291 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3292}
3293
3294// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3295// from the pool and make sure that we recover okay.
3296TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3297 SessionDependencies session_deps;
3298 HttpRequestInfo request;
3299 request.method = "GET";
3300 request.url = GURL("https://www.google.com/");
3301 request.load_flags = 0;
3302
3303 MockWrite data_writes[] = {
3304 MockWrite("GET / HTTP/1.1\r\n"
3305 "Host: www.google.com\r\n"
3306 "Connection: keep-alive\r\n\r\n"),
3307 MockWrite("GET / HTTP/1.1\r\n"
3308 "Host: www.google.com\r\n"
3309 "Connection: keep-alive\r\n\r\n"),
3310 };
3311
3312 MockRead data_reads[] = {
3313 MockRead("HTTP/1.1 200 OK\r\n"),
3314 MockRead("Content-Length: 11\r\n\r\n"),
3315 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3316 MockRead("hello world"),
3317 MockRead(true, 0, 0) // EOF
3318 };
3319
3320 SSLSocketDataProvider ssl(true, OK);
3321 SSLSocketDataProvider ssl2(true, OK);
3322 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3323 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3324
3325 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3326 data_writes, arraysize(data_writes));
3327 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3328 data_writes, arraysize(data_writes));
3329 session_deps.socket_factory.AddSocketDataProvider(&data);
3330 session_deps.socket_factory.AddSocketDataProvider(&data2);
3331
3332 TestCompletionCallback callback;
3333
3334 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3335 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3336
3337 int rv = trans->Start(&request, &callback, BoundNetLog());
3338
3339 EXPECT_EQ(ERR_IO_PENDING, rv);
3340 EXPECT_EQ(OK, callback.WaitForResult());
3341
3342 const HttpResponseInfo* response = trans->GetResponseInfo();
3343 ASSERT_TRUE(response != NULL);
3344 ASSERT_TRUE(response->headers != NULL);
3345 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3346
3347 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3348
3349 std::string response_data;
3350 rv = ReadTransaction(trans.get(), &response_data);
3351 EXPECT_EQ(OK, rv);
3352 EXPECT_EQ("hello world", response_data);
3353
3354 // Empty the current queue. This is necessary because idle sockets are
3355 // added to the connection pool asynchronously with a PostTask.
3356 MessageLoop::current()->RunAllPending();
3357
3358 // We now check to make sure the socket was added back to the pool.
3359 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3360
3361 // Now start the second transaction, which should reuse the previous socket.
3362
3363 trans.reset(new HttpNetworkTransaction(session));
3364
3365 rv = trans->Start(&request, &callback, BoundNetLog());
3366
3367 EXPECT_EQ(ERR_IO_PENDING, rv);
3368 EXPECT_EQ(OK, callback.WaitForResult());
3369
3370 response = trans->GetResponseInfo();
3371 ASSERT_TRUE(response != NULL);
3372 ASSERT_TRUE(response->headers != NULL);
3373 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3374
3375 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3376
3377 rv = ReadTransaction(trans.get(), &response_data);
3378 EXPECT_EQ(OK, rv);
3379 EXPECT_EQ("hello world", response_data);
3380
3381 // Empty the current queue. This is necessary because idle sockets are
3382 // added to the connection pool asynchronously with a PostTask.
3383 MessageLoop::current()->RunAllPending();
3384
3385 // We now check to make sure the socket was added back to the pool.
3386 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3387}
3388
[email protected]b4404c02009-04-10 16:38:523389// Make sure that we recycle a socket after a zero-length response.
3390// http://crbug.com/9880
3391TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423392 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523393 request.method = "GET";
3394 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3395 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3396 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3397 "rt=prt.2642,ol.2649,xjs.2951");
3398 request.load_flags = 0;
3399
[email protected]cb9bf6ca2011-01-28 13:15:273400 SessionDependencies session_deps;
3401 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3402
3403 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3404
[email protected]b4404c02009-04-10 16:38:523405 MockRead data_reads[] = {
3406 MockRead("HTTP/1.1 204 No Content\r\n"
3407 "Content-Length: 0\r\n"
3408 "Content-Type: text/html\r\n\r\n"),
3409 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423410 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523411 };
3412
[email protected]31a2bfe2010-02-09 08:03:393413 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593414 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523415
3416 TestCompletionCallback callback;
3417
[email protected]5a1d7ca2010-04-28 20:12:273418 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423419 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523420
3421 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423422 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523423
[email protected]1c773ea12009-04-28 19:58:423424 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523425 EXPECT_TRUE(response != NULL);
3426
3427 EXPECT_TRUE(response->headers != NULL);
3428 std::string status_line = response->headers->GetStatusLine();
3429 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3430
[email protected]a937a06d2009-08-19 21:19:243431 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523432
3433 std::string response_data;
3434 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423435 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523436 EXPECT_EQ("", response_data);
3437
3438 // Empty the current queue. This is necessary because idle sockets are
3439 // added to the connection pool asynchronously with a PostTask.
3440 MessageLoop::current()->RunAllPending();
3441
3442 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243443 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523444}
3445
[email protected]372d34a2008-11-05 21:30:513446TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423447 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513448 // Transaction 1: a GET request that succeeds. The socket is recycled
3449 // after use.
3450 request[0].method = "GET";
3451 request[0].url = GURL("http://www.google.com/");
3452 request[0].load_flags = 0;
3453 // Transaction 2: a POST request. Reuses the socket kept alive from
3454 // transaction 1. The first attempts fails when writing the POST data.
3455 // This causes the transaction to retry with a new socket. The second
3456 // attempt succeeds.
3457 request[1].method = "POST";
3458 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423459 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513460 request[1].upload_data->AppendBytes("foo", 3);
3461 request[1].load_flags = 0;
3462
[email protected]228ff742009-06-05 01:19:593463 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273464 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513465
3466 // The first socket is used for transaction 1 and the first attempt of
3467 // transaction 2.
3468
3469 // The response of transaction 1.
3470 MockRead data_reads1[] = {
3471 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3472 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423473 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513474 };
3475 // The mock write results of transaction 1 and the first attempt of
3476 // transaction 2.
3477 MockWrite data_writes1[] = {
3478 MockWrite(false, 64), // GET
3479 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423480 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513481 };
[email protected]31a2bfe2010-02-09 08:03:393482 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3483 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513484
3485 // The second socket is used for the second attempt of transaction 2.
3486
3487 // The response of transaction 2.
3488 MockRead data_reads2[] = {
3489 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3490 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423491 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513492 };
3493 // The mock write results of the second attempt of transaction 2.
3494 MockWrite data_writes2[] = {
3495 MockWrite(false, 93), // POST
3496 MockWrite(false, 3), // POST data
3497 };
[email protected]31a2bfe2010-02-09 08:03:393498 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3499 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513500
[email protected]5ecc992a42009-11-11 01:41:593501 session_deps.socket_factory.AddSocketDataProvider(&data1);
3502 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513503
3504 const char* kExpectedResponseData[] = {
3505 "hello world", "welcome"
3506 };
3507
3508 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423509 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433510 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513511
3512 TestCompletionCallback callback;
3513
[email protected]5a1d7ca2010-04-28 20:12:273514 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423515 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513516
3517 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423518 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513519
[email protected]1c773ea12009-04-28 19:58:423520 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513521 EXPECT_TRUE(response != NULL);
3522
3523 EXPECT_TRUE(response->headers != NULL);
3524 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3525
3526 std::string response_data;
3527 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423528 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513529 EXPECT_EQ(kExpectedResponseData[i], response_data);
3530 }
3531}
[email protected]f9ee6b52008-11-08 06:46:233532
3533// Test the request-challenge-retry sequence for basic auth when there is
3534// an identity in the URL. The request should be sent as normal, but when
3535// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323536TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423537 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233538 request.method = "GET";
3539 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293540 request.url = GURL("http://foo:b@[email protected]/");
3541
[email protected]cb9bf6ca2011-01-28 13:15:273542 SessionDependencies session_deps;
3543 scoped_ptr<HttpTransaction> trans(
3544 new HttpNetworkTransaction(CreateSession(&session_deps)));
3545
[email protected]a97cca42009-08-14 01:00:293546 // The password contains an escaped character -- for this test to pass it
3547 // will need to be unescaped by HttpNetworkTransaction.
3548 EXPECT_EQ("b%40r", request.url.password());
3549
[email protected]ea9dc9a2009-09-05 00:43:323550 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233551
3552 MockWrite data_writes1[] = {
3553 MockWrite("GET / HTTP/1.1\r\n"
3554 "Host: www.google.com\r\n"
3555 "Connection: keep-alive\r\n\r\n"),
3556 };
3557
3558 MockRead data_reads1[] = {
3559 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3560 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3561 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423562 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233563 };
3564
3565 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323566 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233567 MockWrite data_writes2[] = {
3568 MockWrite("GET / HTTP/1.1\r\n"
3569 "Host: www.google.com\r\n"
3570 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293571 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233572 };
3573
3574 MockRead data_reads2[] = {
3575 MockRead("HTTP/1.0 200 OK\r\n"),
3576 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423577 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233578 };
3579
[email protected]31a2bfe2010-02-09 08:03:393580 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3581 data_writes1, arraysize(data_writes1));
3582 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3583 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593584 session_deps.socket_factory.AddSocketDataProvider(&data1);
3585 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233586
3587 TestCompletionCallback callback1;
3588
[email protected]5a1d7ca2010-04-28 20:12:273589 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423590 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233591
3592 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423593 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233594
[email protected]0757e7702009-03-27 04:00:223595 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3596 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443597 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423598 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223599 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423600 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223601 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3602
[email protected]1c773ea12009-04-28 19:58:423603 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233604 EXPECT_FALSE(response == NULL);
3605
3606 // There is no challenge info, since the identity in URL worked.
3607 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3608
3609 EXPECT_EQ(100, response->headers->GetContentLength());
3610
3611 // Empty the current queue.
3612 MessageLoop::current()->RunAllPending();
3613}
3614
[email protected]ea9dc9a2009-09-05 00:43:323615// Test the request-challenge-retry sequence for basic auth when there is
3616// an incorrect identity in the URL. The identity from the URL should be used
3617// only once.
3618TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323619 HttpRequestInfo request;
3620 request.method = "GET";
3621 // Note: the URL has a username:password in it. The password "baz" is
3622 // wrong (should be "bar").
3623 request.url = GURL("http://foo:[email protected]/");
3624
3625 request.load_flags = LOAD_NORMAL;
3626
[email protected]cb9bf6ca2011-01-28 13:15:273627 SessionDependencies session_deps;
3628 scoped_ptr<HttpTransaction> trans(
3629 new HttpNetworkTransaction(CreateSession(&session_deps)));
3630
[email protected]ea9dc9a2009-09-05 00:43:323631 MockWrite data_writes1[] = {
3632 MockWrite("GET / HTTP/1.1\r\n"
3633 "Host: www.google.com\r\n"
3634 "Connection: keep-alive\r\n\r\n"),
3635 };
3636
3637 MockRead data_reads1[] = {
3638 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3639 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3640 MockRead("Content-Length: 10\r\n\r\n"),
3641 MockRead(false, ERR_FAILED),
3642 };
3643
3644 // After the challenge above, the transaction will be restarted using the
3645 // identity from the url (foo, baz) to answer the challenge.
3646 MockWrite data_writes2[] = {
3647 MockWrite("GET / HTTP/1.1\r\n"
3648 "Host: www.google.com\r\n"
3649 "Connection: keep-alive\r\n"
3650 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3651 };
3652
3653 MockRead data_reads2[] = {
3654 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3655 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3656 MockRead("Content-Length: 10\r\n\r\n"),
3657 MockRead(false, ERR_FAILED),
3658 };
3659
3660 // After the challenge above, the transaction will be restarted using the
3661 // identity supplied by the user (foo, bar) to answer the challenge.
3662 MockWrite data_writes3[] = {
3663 MockWrite("GET / HTTP/1.1\r\n"
3664 "Host: www.google.com\r\n"
3665 "Connection: keep-alive\r\n"
3666 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3667 };
3668
3669 MockRead data_reads3[] = {
3670 MockRead("HTTP/1.0 200 OK\r\n"),
3671 MockRead("Content-Length: 100\r\n\r\n"),
3672 MockRead(false, OK),
3673 };
3674
[email protected]31a2bfe2010-02-09 08:03:393675 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3676 data_writes1, arraysize(data_writes1));
3677 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3678 data_writes2, arraysize(data_writes2));
3679 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3680 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593681 session_deps.socket_factory.AddSocketDataProvider(&data1);
3682 session_deps.socket_factory.AddSocketDataProvider(&data2);
3683 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323684
3685 TestCompletionCallback callback1;
3686
[email protected]5a1d7ca2010-04-28 20:12:273687 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323688 EXPECT_EQ(ERR_IO_PENDING, rv);
3689
3690 rv = callback1.WaitForResult();
3691 EXPECT_EQ(OK, rv);
3692
3693 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3694 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443695 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323696 EXPECT_EQ(ERR_IO_PENDING, rv);
3697 rv = callback2.WaitForResult();
3698 EXPECT_EQ(OK, rv);
3699 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3700
3701 const HttpResponseInfo* response = trans->GetResponseInfo();
3702 EXPECT_FALSE(response == NULL);
3703 // The password prompt info should have been set in response->auth_challenge.
3704 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3705
3706 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3707 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3708 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3709
3710 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443711 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323712 EXPECT_EQ(ERR_IO_PENDING, rv);
3713 rv = callback3.WaitForResult();
3714 EXPECT_EQ(OK, rv);
3715 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3716
3717 response = trans->GetResponseInfo();
3718 EXPECT_FALSE(response == NULL);
3719
3720 // There is no challenge info, since the identity worked.
3721 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3722
3723 EXPECT_EQ(100, response->headers->GetContentLength());
3724
3725 // Empty the current queue.
3726 MessageLoop::current()->RunAllPending();
3727}
3728
[email protected]f9ee6b52008-11-08 06:46:233729// Test that previously tried username/passwords for a realm get re-used.
3730TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593731 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273732 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233733
3734 // Transaction 1: authenticate (foo, bar) on MyRealm1
3735 {
[email protected]1c773ea12009-04-28 19:58:423736 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233737 request.method = "GET";
3738 request.url = GURL("http://www.google.com/x/y/z");
3739 request.load_flags = 0;
3740
[email protected]cb9bf6ca2011-01-28 13:15:273741 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3742
[email protected]f9ee6b52008-11-08 06:46:233743 MockWrite data_writes1[] = {
3744 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3745 "Host: www.google.com\r\n"
3746 "Connection: keep-alive\r\n\r\n"),
3747 };
3748
3749 MockRead data_reads1[] = {
3750 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3751 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3752 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423753 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233754 };
3755
3756 // Resend with authorization (username=foo, password=bar)
3757 MockWrite data_writes2[] = {
3758 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3759 "Host: www.google.com\r\n"
3760 "Connection: keep-alive\r\n"
3761 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3762 };
3763
3764 // Sever accepts the authorization.
3765 MockRead data_reads2[] = {
3766 MockRead("HTTP/1.0 200 OK\r\n"),
3767 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423768 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233769 };
3770
[email protected]31a2bfe2010-02-09 08:03:393771 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3772 data_writes1, arraysize(data_writes1));
3773 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3774 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593775 session_deps.socket_factory.AddSocketDataProvider(&data1);
3776 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233777
3778 TestCompletionCallback callback1;
3779
[email protected]5a1d7ca2010-04-28 20:12:273780 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423781 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233782
3783 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423784 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233785
[email protected]1c773ea12009-04-28 19:58:423786 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233787 EXPECT_FALSE(response == NULL);
3788
3789 // The password prompt info should have been set in
3790 // response->auth_challenge.
3791 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3792
[email protected]71e4573a2009-05-21 22:03:003793 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233794 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3795 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3796
3797 TestCompletionCallback callback2;
3798
[email protected]13c8a092010-07-29 06:15:443799 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233801
3802 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423803 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233804
3805 response = trans->GetResponseInfo();
3806 EXPECT_FALSE(response == NULL);
3807 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3808 EXPECT_EQ(100, response->headers->GetContentLength());
3809 }
3810
3811 // ------------------------------------------------------------------------
3812
3813 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3814 {
[email protected]1c773ea12009-04-28 19:58:423815 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233816 request.method = "GET";
3817 // Note that Transaction 1 was at /x/y/z, so this is in the same
3818 // protection space as MyRealm1.
3819 request.url = GURL("http://www.google.com/x/y/a/b");
3820 request.load_flags = 0;
3821
[email protected]cb9bf6ca2011-01-28 13:15:273822 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3823
[email protected]f9ee6b52008-11-08 06:46:233824 MockWrite data_writes1[] = {
3825 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3826 "Host: www.google.com\r\n"
3827 "Connection: keep-alive\r\n"
3828 // Send preemptive authorization for MyRealm1
3829 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3830 };
3831
3832 // The server didn't like the preemptive authorization, and
3833 // challenges us for a different realm (MyRealm2).
3834 MockRead data_reads1[] = {
3835 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3836 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3837 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423838 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233839 };
3840
3841 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3842 MockWrite data_writes2[] = {
3843 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3844 "Host: www.google.com\r\n"
3845 "Connection: keep-alive\r\n"
3846 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3847 };
3848
3849 // Sever accepts the authorization.
3850 MockRead data_reads2[] = {
3851 MockRead("HTTP/1.0 200 OK\r\n"),
3852 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423853 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233854 };
3855
[email protected]31a2bfe2010-02-09 08:03:393856 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3857 data_writes1, arraysize(data_writes1));
3858 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3859 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593860 session_deps.socket_factory.AddSocketDataProvider(&data1);
3861 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233862
3863 TestCompletionCallback callback1;
3864
[email protected]5a1d7ca2010-04-28 20:12:273865 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423866 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233867
3868 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423869 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233870
[email protected]1c773ea12009-04-28 19:58:423871 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233872 EXPECT_FALSE(response == NULL);
3873
3874 // The password prompt info should have been set in
3875 // response->auth_challenge.
3876 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3877
[email protected]71e4573a2009-05-21 22:03:003878 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233879 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3880 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3881
3882 TestCompletionCallback callback2;
3883
[email protected]13c8a092010-07-29 06:15:443884 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233886
3887 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423888 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233889
3890 response = trans->GetResponseInfo();
3891 EXPECT_FALSE(response == NULL);
3892 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3893 EXPECT_EQ(100, response->headers->GetContentLength());
3894 }
3895
3896 // ------------------------------------------------------------------------
3897
3898 // Transaction 3: Resend a request in MyRealm's protection space --
3899 // succeed with preemptive authorization.
3900 {
[email protected]1c773ea12009-04-28 19:58:423901 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233902 request.method = "GET";
3903 request.url = GURL("http://www.google.com/x/y/z2");
3904 request.load_flags = 0;
3905
[email protected]cb9bf6ca2011-01-28 13:15:273906 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3907
[email protected]f9ee6b52008-11-08 06:46:233908 MockWrite data_writes1[] = {
3909 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3910 "Host: www.google.com\r\n"
3911 "Connection: keep-alive\r\n"
3912 // The authorization for MyRealm1 gets sent preemptively
3913 // (since the url is in the same protection space)
3914 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3915 };
3916
3917 // Sever accepts the preemptive authorization
3918 MockRead data_reads1[] = {
3919 MockRead("HTTP/1.0 200 OK\r\n"),
3920 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423921 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233922 };
3923
[email protected]31a2bfe2010-02-09 08:03:393924 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3925 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593926 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233927
3928 TestCompletionCallback callback1;
3929
[email protected]5a1d7ca2010-04-28 20:12:273930 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423931 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233932
3933 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423934 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233935
[email protected]1c773ea12009-04-28 19:58:423936 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233937 EXPECT_FALSE(response == NULL);
3938
3939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3940 EXPECT_EQ(100, response->headers->GetContentLength());
3941 }
3942
3943 // ------------------------------------------------------------------------
3944
3945 // Transaction 4: request another URL in MyRealm (however the
3946 // url is not known to belong to the protection space, so no pre-auth).
3947 {
[email protected]1c773ea12009-04-28 19:58:423948 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233949 request.method = "GET";
3950 request.url = GURL("http://www.google.com/x/1");
3951 request.load_flags = 0;
3952
[email protected]cb9bf6ca2011-01-28 13:15:273953 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3954
[email protected]f9ee6b52008-11-08 06:46:233955 MockWrite data_writes1[] = {
3956 MockWrite("GET /x/1 HTTP/1.1\r\n"
3957 "Host: www.google.com\r\n"
3958 "Connection: keep-alive\r\n\r\n"),
3959 };
3960
3961 MockRead data_reads1[] = {
3962 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3963 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3964 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423965 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233966 };
3967
3968 // Resend with authorization from MyRealm's cache.
3969 MockWrite data_writes2[] = {
3970 MockWrite("GET /x/1 HTTP/1.1\r\n"
3971 "Host: www.google.com\r\n"
3972 "Connection: keep-alive\r\n"
3973 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3974 };
3975
3976 // Sever accepts the authorization.
3977 MockRead data_reads2[] = {
3978 MockRead("HTTP/1.0 200 OK\r\n"),
3979 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423980 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233981 };
3982
[email protected]31a2bfe2010-02-09 08:03:393983 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3984 data_writes1, arraysize(data_writes1));
3985 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3986 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593987 session_deps.socket_factory.AddSocketDataProvider(&data1);
3988 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233989
3990 TestCompletionCallback callback1;
3991
[email protected]5a1d7ca2010-04-28 20:12:273992 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233994
3995 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423996 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233997
[email protected]0757e7702009-03-27 04:00:223998 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3999 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444000 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424001 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224002 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424003 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224004 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4005
[email protected]1c773ea12009-04-28 19:58:424006 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234007 EXPECT_FALSE(response == NULL);
4008 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4009 EXPECT_EQ(100, response->headers->GetContentLength());
4010 }
4011
4012 // ------------------------------------------------------------------------
4013
4014 // Transaction 5: request a URL in MyRealm, but the server rejects the
4015 // cached identity. Should invalidate and re-prompt.
4016 {
[email protected]1c773ea12009-04-28 19:58:424017 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234018 request.method = "GET";
4019 request.url = GURL("http://www.google.com/p/q/t");
4020 request.load_flags = 0;
4021
[email protected]cb9bf6ca2011-01-28 13:15:274022 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4023
[email protected]f9ee6b52008-11-08 06:46:234024 MockWrite data_writes1[] = {
4025 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4026 "Host: www.google.com\r\n"
4027 "Connection: keep-alive\r\n\r\n"),
4028 };
4029
4030 MockRead data_reads1[] = {
4031 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4032 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4033 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424034 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234035 };
4036
4037 // Resend with authorization from cache for MyRealm.
4038 MockWrite data_writes2[] = {
4039 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4040 "Host: www.google.com\r\n"
4041 "Connection: keep-alive\r\n"
4042 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4043 };
4044
4045 // Sever rejects the authorization.
4046 MockRead data_reads2[] = {
4047 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4049 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424050 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234051 };
4052
4053 // At this point we should prompt for new credentials for MyRealm.
4054 // Restart with username=foo3, password=foo4.
4055 MockWrite data_writes3[] = {
4056 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4057 "Host: www.google.com\r\n"
4058 "Connection: keep-alive\r\n"
4059 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4060 };
4061
4062 // Sever accepts the authorization.
4063 MockRead data_reads3[] = {
4064 MockRead("HTTP/1.0 200 OK\r\n"),
4065 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424066 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234067 };
4068
[email protected]31a2bfe2010-02-09 08:03:394069 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4070 data_writes1, arraysize(data_writes1));
4071 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4072 data_writes2, arraysize(data_writes2));
4073 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4074 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594075 session_deps.socket_factory.AddSocketDataProvider(&data1);
4076 session_deps.socket_factory.AddSocketDataProvider(&data2);
4077 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234078
4079 TestCompletionCallback callback1;
4080
[email protected]5a1d7ca2010-04-28 20:12:274081 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424082 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234083
4084 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424085 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234086
[email protected]0757e7702009-03-27 04:00:224087 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4088 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444089 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424090 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224091 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424092 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224093 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4094
[email protected]1c773ea12009-04-28 19:58:424095 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234096 EXPECT_FALSE(response == NULL);
4097
4098 // The password prompt info should have been set in
4099 // response->auth_challenge.
4100 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4101
[email protected]71e4573a2009-05-21 22:03:004102 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234103 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4104 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4105
[email protected]0757e7702009-03-27 04:00:224106 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234107
[email protected]13c8a092010-07-29 06:15:444108 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424109 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234110
[email protected]0757e7702009-03-27 04:00:224111 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424112 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234113
4114 response = trans->GetResponseInfo();
4115 EXPECT_FALSE(response == NULL);
4116 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4117 EXPECT_EQ(100, response->headers->GetContentLength());
4118 }
4119}
[email protected]89ceba9a2009-03-21 03:46:064120
[email protected]3c32c5f2010-05-18 15:18:124121// Tests that nonce count increments when multiple auth attempts
4122// are started with the same nonce.
4123TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4124 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444125 HttpAuthHandlerDigest::Factory* digest_factory =
4126 new HttpAuthHandlerDigest::Factory();
4127 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4128 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4129 digest_factory->set_nonce_generator(nonce_generator);
4130 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274131 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124132
4133 // Transaction 1: authenticate (foo, bar) on MyRealm1
4134 {
[email protected]3c32c5f2010-05-18 15:18:124135 HttpRequestInfo request;
4136 request.method = "GET";
4137 request.url = GURL("http://www.google.com/x/y/z");
4138 request.load_flags = 0;
4139
[email protected]cb9bf6ca2011-01-28 13:15:274140 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4141
[email protected]3c32c5f2010-05-18 15:18:124142 MockWrite data_writes1[] = {
4143 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4144 "Host: www.google.com\r\n"
4145 "Connection: keep-alive\r\n\r\n"),
4146 };
4147
4148 MockRead data_reads1[] = {
4149 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4150 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4151 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4152 MockRead(false, OK),
4153 };
4154
4155 // Resend with authorization (username=foo, password=bar)
4156 MockWrite data_writes2[] = {
4157 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4158 "Host: www.google.com\r\n"
4159 "Connection: keep-alive\r\n"
4160 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4161 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4162 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4163 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4164 };
4165
4166 // Sever accepts the authorization.
4167 MockRead data_reads2[] = {
4168 MockRead("HTTP/1.0 200 OK\r\n"),
4169 MockRead(false, OK),
4170 };
4171
4172 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4173 data_writes1, arraysize(data_writes1));
4174 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4175 data_writes2, arraysize(data_writes2));
4176 session_deps.socket_factory.AddSocketDataProvider(&data1);
4177 session_deps.socket_factory.AddSocketDataProvider(&data2);
4178
4179 TestCompletionCallback callback1;
4180
4181 int rv = trans->Start(&request, &callback1, BoundNetLog());
4182 EXPECT_EQ(ERR_IO_PENDING, rv);
4183
4184 rv = callback1.WaitForResult();
4185 EXPECT_EQ(OK, rv);
4186
4187 const HttpResponseInfo* response = trans->GetResponseInfo();
4188 ASSERT_FALSE(response == NULL);
4189
4190 // The password prompt info should have been set in
4191 // response->auth_challenge.
4192 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4193
4194 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4195 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4196 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4197
4198 TestCompletionCallback callback2;
4199
[email protected]13c8a092010-07-29 06:15:444200 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124201 EXPECT_EQ(ERR_IO_PENDING, rv);
4202
4203 rv = callback2.WaitForResult();
4204 EXPECT_EQ(OK, rv);
4205
4206 response = trans->GetResponseInfo();
4207 ASSERT_FALSE(response == NULL);
4208 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4209 }
4210
4211 // ------------------------------------------------------------------------
4212
4213 // Transaction 2: Request another resource in digestive's protection space.
4214 // This will preemptively add an Authorization header which should have an
4215 // "nc" value of 2 (as compared to 1 in the first use.
4216 {
[email protected]3c32c5f2010-05-18 15:18:124217 HttpRequestInfo request;
4218 request.method = "GET";
4219 // Note that Transaction 1 was at /x/y/z, so this is in the same
4220 // protection space as digest.
4221 request.url = GURL("http://www.google.com/x/y/a/b");
4222 request.load_flags = 0;
4223
[email protected]cb9bf6ca2011-01-28 13:15:274224 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4225
[email protected]3c32c5f2010-05-18 15:18:124226 MockWrite data_writes1[] = {
4227 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4228 "Host: www.google.com\r\n"
4229 "Connection: keep-alive\r\n"
4230 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4231 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4232 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4233 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4234 };
4235
4236 // Sever accepts the authorization.
4237 MockRead data_reads1[] = {
4238 MockRead("HTTP/1.0 200 OK\r\n"),
4239 MockRead("Content-Length: 100\r\n\r\n"),
4240 MockRead(false, OK),
4241 };
4242
4243 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4244 data_writes1, arraysize(data_writes1));
4245 session_deps.socket_factory.AddSocketDataProvider(&data1);
4246
4247 TestCompletionCallback callback1;
4248
4249 int rv = trans->Start(&request, &callback1, BoundNetLog());
4250 EXPECT_EQ(ERR_IO_PENDING, rv);
4251
4252 rv = callback1.WaitForResult();
4253 EXPECT_EQ(OK, rv);
4254
4255 const HttpResponseInfo* response = trans->GetResponseInfo();
4256 ASSERT_FALSE(response == NULL);
4257 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4258 }
4259}
4260
[email protected]89ceba9a2009-03-21 03:46:064261// Test the ResetStateForRestart() private method.
4262TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4263 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594264 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404265 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434266 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064267
4268 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064269 trans->read_buf_ = new IOBuffer(15);
4270 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204271 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064272
4273 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144274 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574275 response->auth_challenge = new AuthChallengeInfo();
4276 response->ssl_info.cert_status = -15;
4277 response->response_time = base::Time::Now();
4278 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064279
4280 { // Setup state for response_.vary_data
4281 HttpRequestInfo request;
4282 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4283 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274284 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434285 request.extra_headers.SetHeader("Foo", "1");
4286 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574287 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064288 }
4289
4290 // Cause the above state to be reset.
4291 trans->ResetStateForRestart();
4292
4293 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074294 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064295 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204296 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574297 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4298 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044299 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574300 EXPECT_EQ(0, response->ssl_info.cert_status);
4301 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064302}
4303
[email protected]bacff652009-03-31 17:50:334304// Test HTTPS connections to a site with a bad certificate
4305TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334306 HttpRequestInfo request;
4307 request.method = "GET";
4308 request.url = GURL("https://www.google.com/");
4309 request.load_flags = 0;
4310
[email protected]cb9bf6ca2011-01-28 13:15:274311 SessionDependencies session_deps;
4312 scoped_ptr<HttpTransaction> trans(
4313 new HttpNetworkTransaction(CreateSession(&session_deps)));
4314
[email protected]bacff652009-03-31 17:50:334315 MockWrite data_writes[] = {
4316 MockWrite("GET / HTTP/1.1\r\n"
4317 "Host: www.google.com\r\n"
4318 "Connection: keep-alive\r\n\r\n"),
4319 };
4320
4321 MockRead data_reads[] = {
4322 MockRead("HTTP/1.0 200 OK\r\n"),
4323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4324 MockRead("Content-Length: 100\r\n\r\n"),
4325 MockRead(false, OK),
4326 };
4327
[email protected]5ecc992a42009-11-11 01:41:594328 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394329 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4330 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594331 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4332 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334333
[email protected]5ecc992a42009-11-11 01:41:594334 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4335 session_deps.socket_factory.AddSocketDataProvider(&data);
4336 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4337 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334338
4339 TestCompletionCallback callback;
4340
[email protected]5a1d7ca2010-04-28 20:12:274341 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334342 EXPECT_EQ(ERR_IO_PENDING, rv);
4343
4344 rv = callback.WaitForResult();
4345 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4346
4347 rv = trans->RestartIgnoringLastError(&callback);
4348 EXPECT_EQ(ERR_IO_PENDING, rv);
4349
4350 rv = callback.WaitForResult();
4351 EXPECT_EQ(OK, rv);
4352
4353 const HttpResponseInfo* response = trans->GetResponseInfo();
4354
4355 EXPECT_FALSE(response == NULL);
4356 EXPECT_EQ(100, response->headers->GetContentLength());
4357}
4358
4359// Test HTTPS connections to a site with a bad certificate, going through a
4360// proxy
4361TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004362 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334363
4364 HttpRequestInfo request;
4365 request.method = "GET";
4366 request.url = GURL("https://www.google.com/");
4367 request.load_flags = 0;
4368
4369 MockWrite proxy_writes[] = {
4370 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454371 "Host: www.google.com\r\n"
4372 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334373 };
4374
4375 MockRead proxy_reads[] = {
4376 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424377 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334378 };
4379
4380 MockWrite data_writes[] = {
4381 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454382 "Host: www.google.com\r\n"
4383 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334384 MockWrite("GET / HTTP/1.1\r\n"
4385 "Host: www.google.com\r\n"
4386 "Connection: keep-alive\r\n\r\n"),
4387 };
4388
4389 MockRead data_reads[] = {
4390 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4391 MockRead("HTTP/1.0 200 OK\r\n"),
4392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4393 MockRead("Content-Length: 100\r\n\r\n"),
4394 MockRead(false, OK),
4395 };
4396
[email protected]31a2bfe2010-02-09 08:03:394397 StaticSocketDataProvider ssl_bad_certificate(
4398 proxy_reads, arraysize(proxy_reads),
4399 proxy_writes, arraysize(proxy_writes));
4400 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4401 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594402 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4403 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334404
[email protected]5ecc992a42009-11-11 01:41:594405 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4406 session_deps.socket_factory.AddSocketDataProvider(&data);
4407 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4408 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334409
4410 TestCompletionCallback callback;
4411
4412 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594413 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334414
[email protected]d207a5f2009-06-04 05:28:404415 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434416 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334417
[email protected]5a1d7ca2010-04-28 20:12:274418 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334419 EXPECT_EQ(ERR_IO_PENDING, rv);
4420
4421 rv = callback.WaitForResult();
4422 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4423
4424 rv = trans->RestartIgnoringLastError(&callback);
4425 EXPECT_EQ(ERR_IO_PENDING, rv);
4426
4427 rv = callback.WaitForResult();
4428 EXPECT_EQ(OK, rv);
4429
4430 const HttpResponseInfo* response = trans->GetResponseInfo();
4431
4432 EXPECT_FALSE(response == NULL);
4433 EXPECT_EQ(100, response->headers->GetContentLength());
4434 }
4435}
4436
[email protected]2df19bb2010-08-25 20:13:464437
4438// Test HTTPS connections to a site, going through an HTTPS proxy
4439TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004440 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464441
4442 HttpRequestInfo request;
4443 request.method = "GET";
4444 request.url = GURL("https://www.google.com/");
4445 request.load_flags = 0;
4446
4447 MockWrite data_writes[] = {
4448 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4449 "Host: www.google.com\r\n"
4450 "Proxy-Connection: keep-alive\r\n\r\n"),
4451 MockWrite("GET / HTTP/1.1\r\n"
4452 "Host: www.google.com\r\n"
4453 "Connection: keep-alive\r\n\r\n"),
4454 };
4455
4456 MockRead data_reads[] = {
4457 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4458 MockRead("HTTP/1.1 200 OK\r\n"),
4459 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4460 MockRead("Content-Length: 100\r\n\r\n"),
4461 MockRead(false, OK),
4462 };
4463
4464 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4465 data_writes, arraysize(data_writes));
4466 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4467 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4468
4469 session_deps.socket_factory.AddSocketDataProvider(&data);
4470 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4471 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4472
4473 TestCompletionCallback callback;
4474
4475 scoped_ptr<HttpTransaction> trans(
4476 new HttpNetworkTransaction(CreateSession(&session_deps)));
4477
4478 int rv = trans->Start(&request, &callback, BoundNetLog());
4479 EXPECT_EQ(ERR_IO_PENDING, rv);
4480
4481 rv = callback.WaitForResult();
4482 EXPECT_EQ(OK, rv);
4483 const HttpResponseInfo* response = trans->GetResponseInfo();
4484
4485 ASSERT_FALSE(response == NULL);
4486
4487 EXPECT_TRUE(response->headers->IsKeepAlive());
4488 EXPECT_EQ(200, response->headers->response_code());
4489 EXPECT_EQ(100, response->headers->GetContentLength());
4490 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4491}
4492
[email protected]511f6f52010-12-17 03:58:294493// Test an HTTPS Proxy's ability to redirect a CONNECT request
4494TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4495 SessionDependencies session_deps(
4496 ProxyService::CreateFixed("https://proxy:70"));
4497
4498 HttpRequestInfo request;
4499 request.method = "GET";
4500 request.url = GURL("https://www.google.com/");
4501 request.load_flags = 0;
4502
4503 MockWrite data_writes[] = {
4504 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4505 "Host: www.google.com\r\n"
4506 "Proxy-Connection: keep-alive\r\n\r\n"),
4507 };
4508
4509 MockRead data_reads[] = {
4510 MockRead("HTTP/1.1 302 Redirect\r\n"),
4511 MockRead("Location: http://login.example.com/\r\n"),
4512 MockRead("Content-Length: 0\r\n\r\n"),
4513 MockRead(false, OK),
4514 };
4515
4516 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4517 data_writes, arraysize(data_writes));
4518 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4519
4520 session_deps.socket_factory.AddSocketDataProvider(&data);
4521 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4522
4523 TestCompletionCallback callback;
4524
4525 scoped_ptr<HttpTransaction> trans(
4526 new HttpNetworkTransaction(CreateSession(&session_deps)));
4527
4528 int rv = trans->Start(&request, &callback, BoundNetLog());
4529 EXPECT_EQ(ERR_IO_PENDING, rv);
4530
4531 rv = callback.WaitForResult();
4532 EXPECT_EQ(OK, rv);
4533 const HttpResponseInfo* response = trans->GetResponseInfo();
4534
4535 ASSERT_FALSE(response == NULL);
4536
4537 EXPECT_EQ(302, response->headers->response_code());
4538 std::string url;
4539 EXPECT_TRUE(response->headers->IsRedirect(&url));
4540 EXPECT_EQ("http://login.example.com/", url);
4541}
4542
4543// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4544TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4545 SessionDependencies session_deps(
4546 ProxyService::CreateFixed("https://proxy:70"));
4547
4548 HttpRequestInfo request;
4549 request.method = "GET";
4550 request.url = GURL("https://www.google.com/");
4551 request.load_flags = 0;
4552
4553 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4554 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4555 MockWrite data_writes[] = {
4556 CreateMockWrite(*conn.get(), 0, false),
4557 };
4558
4559 static const char* const kExtraHeaders[] = {
4560 "location",
4561 "http://login.example.com/",
4562 };
4563 scoped_ptr<spdy::SpdyFrame> resp(
4564 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4565 arraysize(kExtraHeaders)/2, 1));
4566 MockRead data_reads[] = {
4567 CreateMockRead(*resp.get(), 1, false),
4568 MockRead(true, 0, 2), // EOF
4569 };
4570
4571 scoped_refptr<DelayedSocketData> data(
4572 new DelayedSocketData(
4573 1, // wait for one write to finish before reading.
4574 data_reads, arraysize(data_reads),
4575 data_writes, arraysize(data_writes)));
4576 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4577 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4578 proxy_ssl.next_proto = "spdy/2";
4579 proxy_ssl.was_npn_negotiated = true;
4580
4581 session_deps.socket_factory.AddSocketDataProvider(data.get());
4582 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4583
4584 TestCompletionCallback callback;
4585
4586 scoped_ptr<HttpTransaction> trans(
4587 new HttpNetworkTransaction(CreateSession(&session_deps)));
4588
4589 int rv = trans->Start(&request, &callback, BoundNetLog());
4590 EXPECT_EQ(ERR_IO_PENDING, rv);
4591
4592 rv = callback.WaitForResult();
4593 EXPECT_EQ(OK, rv);
4594 const HttpResponseInfo* response = trans->GetResponseInfo();
4595
4596 ASSERT_FALSE(response == NULL);
4597
4598 EXPECT_EQ(302, response->headers->response_code());
4599 std::string url;
4600 EXPECT_TRUE(response->headers->IsRedirect(&url));
4601 EXPECT_EQ("http://login.example.com/", url);
4602}
4603
4604// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4605TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4606 SessionDependencies session_deps(
4607 ProxyService::CreateFixed("https://proxy:70"));
4608
4609 HttpRequestInfo request;
4610 request.method = "GET";
4611 request.url = GURL("https://www.google.com/");
4612 request.load_flags = 0;
4613
4614 MockWrite data_writes[] = {
4615 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4616 "Host: www.google.com\r\n"
4617 "Proxy-Connection: keep-alive\r\n\r\n"),
4618 };
4619
4620 MockRead data_reads[] = {
4621 MockRead("HTTP/1.1 404 Not Found\r\n"),
4622 MockRead("Content-Length: 23\r\n\r\n"),
4623 MockRead("The host does not exist"),
4624 MockRead(false, OK),
4625 };
4626
4627 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4628 data_writes, arraysize(data_writes));
4629 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4630
4631 session_deps.socket_factory.AddSocketDataProvider(&data);
4632 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4633
4634 TestCompletionCallback callback;
4635
4636 scoped_ptr<HttpTransaction> trans(
4637 new HttpNetworkTransaction(CreateSession(&session_deps)));
4638
4639 int rv = trans->Start(&request, &callback, BoundNetLog());
4640 EXPECT_EQ(ERR_IO_PENDING, rv);
4641
4642 rv = callback.WaitForResult();
4643 EXPECT_EQ(OK, rv);
4644 const HttpResponseInfo* response = trans->GetResponseInfo();
4645
4646 ASSERT_FALSE(response == NULL);
4647
4648 EXPECT_EQ(404, response->headers->response_code());
4649 EXPECT_EQ(23, response->headers->GetContentLength());
4650 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4651 EXPECT_FALSE(response->ssl_info.is_valid());
4652
4653 std::string response_data;
4654 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4655 EXPECT_EQ("The host does not exist", response_data);
4656}
4657
4658// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4659// request
4660TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4661 SessionDependencies session_deps(
4662 ProxyService::CreateFixed("https://proxy:70"));
4663
4664 HttpRequestInfo request;
4665 request.method = "GET";
4666 request.url = GURL("https://www.google.com/");
4667 request.load_flags = 0;
4668
4669 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4670 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4671 MockWrite data_writes[] = {
4672 CreateMockWrite(*conn.get(), 0, false),
4673 };
4674
4675 static const char* const kExtraHeaders[] = {
4676 "location",
4677 "http://login.example.com/",
4678 };
4679 scoped_ptr<spdy::SpdyFrame> resp(
4680 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4681 arraysize(kExtraHeaders)/2, 1));
4682 scoped_ptr<spdy::SpdyFrame> body(
4683 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4684 MockRead data_reads[] = {
4685 CreateMockRead(*resp.get(), 1, false),
4686 CreateMockRead(*body.get(), 2, false),
4687 MockRead(true, 0, 3), // EOF
4688 };
4689
4690 scoped_refptr<DelayedSocketData> data(
4691 new DelayedSocketData(
4692 1, // wait for one write to finish before reading.
4693 data_reads, arraysize(data_reads),
4694 data_writes, arraysize(data_writes)));
4695 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4696 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4697 proxy_ssl.next_proto = "spdy/2";
4698 proxy_ssl.was_npn_negotiated = true;
4699
4700 session_deps.socket_factory.AddSocketDataProvider(data.get());
4701 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4702
4703 TestCompletionCallback callback;
4704
4705 scoped_ptr<HttpTransaction> trans(
4706 new HttpNetworkTransaction(CreateSession(&session_deps)));
4707
4708 int rv = trans->Start(&request, &callback, BoundNetLog());
4709 EXPECT_EQ(ERR_IO_PENDING, rv);
4710
4711 rv = callback.WaitForResult();
4712 EXPECT_EQ(OK, rv);
4713 const HttpResponseInfo* response = trans->GetResponseInfo();
4714
4715 ASSERT_FALSE(response == NULL);
4716
4717 EXPECT_EQ(404, response->headers->response_code());
4718 EXPECT_FALSE(response->ssl_info.is_valid());
4719
4720 std::string response_data;
4721 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4722 EXPECT_EQ("The host does not exist", response_data);
4723}
4724
[email protected]2df19bb2010-08-25 20:13:464725// Test HTTPS connections to a site with a bad certificate, going through an
4726// HTTPS proxy
4727TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004728 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464729
4730 HttpRequestInfo request;
4731 request.method = "GET";
4732 request.url = GURL("https://www.google.com/");
4733 request.load_flags = 0;
4734
4735 // Attempt to fetch the URL from a server with a bad cert
4736 MockWrite bad_cert_writes[] = {
4737 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4738 "Host: www.google.com\r\n"
4739 "Proxy-Connection: keep-alive\r\n\r\n"),
4740 };
4741
4742 MockRead bad_cert_reads[] = {
4743 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4744 MockRead(false, OK)
4745 };
4746
4747 // Attempt to fetch the URL with a good cert
4748 MockWrite good_data_writes[] = {
4749 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4750 "Host: www.google.com\r\n"
4751 "Proxy-Connection: keep-alive\r\n\r\n"),
4752 MockWrite("GET / HTTP/1.1\r\n"
4753 "Host: www.google.com\r\n"
4754 "Connection: keep-alive\r\n\r\n"),
4755 };
4756
4757 MockRead good_cert_reads[] = {
4758 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4759 MockRead("HTTP/1.0 200 OK\r\n"),
4760 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4761 MockRead("Content-Length: 100\r\n\r\n"),
4762 MockRead(false, OK),
4763 };
4764
4765 StaticSocketDataProvider ssl_bad_certificate(
4766 bad_cert_reads, arraysize(bad_cert_reads),
4767 bad_cert_writes, arraysize(bad_cert_writes));
4768 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4769 good_data_writes, arraysize(good_data_writes));
4770 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4771 SSLSocketDataProvider ssl(true, OK);
4772
4773 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4774 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4775 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4776 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4777
4778 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4779 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4780 session_deps.socket_factory.AddSocketDataProvider(&data);
4781 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4782
4783 TestCompletionCallback callback;
4784
4785 scoped_ptr<HttpTransaction> trans(
4786 new HttpNetworkTransaction(CreateSession(&session_deps)));
4787
4788 int rv = trans->Start(&request, &callback, BoundNetLog());
4789 EXPECT_EQ(ERR_IO_PENDING, rv);
4790
4791 rv = callback.WaitForResult();
4792 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4793
4794 rv = trans->RestartIgnoringLastError(&callback);
4795 EXPECT_EQ(ERR_IO_PENDING, rv);
4796
4797 rv = callback.WaitForResult();
4798 EXPECT_EQ(OK, rv);
4799
4800 const HttpResponseInfo* response = trans->GetResponseInfo();
4801
4802 EXPECT_FALSE(response == NULL);
4803 EXPECT_EQ(100, response->headers->GetContentLength());
4804}
4805
[email protected]1c773ea12009-04-28 19:58:424806TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424807 HttpRequestInfo request;
4808 request.method = "GET";
4809 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434810 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4811 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424812
[email protected]cb9bf6ca2011-01-28 13:15:274813 SessionDependencies session_deps;
4814 scoped_ptr<HttpTransaction> trans(
4815 new HttpNetworkTransaction(CreateSession(&session_deps)));
4816
[email protected]1c773ea12009-04-28 19:58:424817 MockWrite data_writes[] = {
4818 MockWrite("GET / HTTP/1.1\r\n"
4819 "Host: www.google.com\r\n"
4820 "Connection: keep-alive\r\n"
4821 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4822 };
4823
4824 // Lastly, the server responds with the actual content.
4825 MockRead data_reads[] = {
4826 MockRead("HTTP/1.0 200 OK\r\n"),
4827 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4828 MockRead("Content-Length: 100\r\n\r\n"),
4829 MockRead(false, OK),
4830 };
4831
[email protected]31a2bfe2010-02-09 08:03:394832 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4833 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594834 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424835
4836 TestCompletionCallback callback;
4837
[email protected]5a1d7ca2010-04-28 20:12:274838 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424839 EXPECT_EQ(ERR_IO_PENDING, rv);
4840
4841 rv = callback.WaitForResult();
4842 EXPECT_EQ(OK, rv);
4843}
4844
[email protected]da81f132010-08-18 23:39:294845TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294846 HttpRequestInfo request;
4847 request.method = "GET";
4848 request.url = GURL("https://www.google.com/");
4849 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4850 "Chromium Ultra Awesome X Edition");
4851
[email protected]cb9bf6ca2011-01-28 13:15:274852 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4853 scoped_ptr<HttpTransaction> trans(
4854 new HttpNetworkTransaction(CreateSession(&session_deps)));
4855
[email protected]da81f132010-08-18 23:39:294856 MockWrite data_writes[] = {
4857 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4858 "Host: www.google.com\r\n"
4859 "Proxy-Connection: keep-alive\r\n"
4860 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4861 };
4862 MockRead data_reads[] = {
4863 // Return an error, so the transaction stops here (this test isn't
4864 // interested in the rest).
4865 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4866 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4867 MockRead("Proxy-Connection: close\r\n\r\n"),
4868 };
4869
4870 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4871 data_writes, arraysize(data_writes));
4872 session_deps.socket_factory.AddSocketDataProvider(&data);
4873
4874 TestCompletionCallback callback;
4875
4876 int rv = trans->Start(&request, &callback, BoundNetLog());
4877 EXPECT_EQ(ERR_IO_PENDING, rv);
4878
4879 rv = callback.WaitForResult();
4880 EXPECT_EQ(OK, rv);
4881}
4882
[email protected]1c773ea12009-04-28 19:58:424883TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424884 HttpRequestInfo request;
4885 request.method = "GET";
4886 request.url = GURL("http://www.google.com/");
4887 request.load_flags = 0;
4888 request.referrer = GURL("http://the.previous.site.com/");
4889
[email protected]cb9bf6ca2011-01-28 13:15:274890 SessionDependencies session_deps;
4891 scoped_ptr<HttpTransaction> trans(
4892 new HttpNetworkTransaction(CreateSession(&session_deps)));
4893
[email protected]1c773ea12009-04-28 19:58:424894 MockWrite data_writes[] = {
4895 MockWrite("GET / HTTP/1.1\r\n"
4896 "Host: www.google.com\r\n"
4897 "Connection: keep-alive\r\n"
4898 "Referer: http://the.previous.site.com/\r\n\r\n"),
4899 };
4900
4901 // Lastly, the server responds with the actual content.
4902 MockRead data_reads[] = {
4903 MockRead("HTTP/1.0 200 OK\r\n"),
4904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4905 MockRead("Content-Length: 100\r\n\r\n"),
4906 MockRead(false, OK),
4907 };
4908
[email protected]31a2bfe2010-02-09 08:03:394909 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4910 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594911 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424912
4913 TestCompletionCallback callback;
4914
[email protected]5a1d7ca2010-04-28 20:12:274915 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424916 EXPECT_EQ(ERR_IO_PENDING, rv);
4917
4918 rv = callback.WaitForResult();
4919 EXPECT_EQ(OK, rv);
4920}
4921
4922TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424923 HttpRequestInfo request;
4924 request.method = "POST";
4925 request.url = GURL("http://www.google.com/");
4926
[email protected]cb9bf6ca2011-01-28 13:15:274927 SessionDependencies session_deps;
4928 scoped_ptr<HttpTransaction> trans(
4929 new HttpNetworkTransaction(CreateSession(&session_deps)));
4930
[email protected]1c773ea12009-04-28 19:58:424931 MockWrite data_writes[] = {
4932 MockWrite("POST / HTTP/1.1\r\n"
4933 "Host: www.google.com\r\n"
4934 "Connection: keep-alive\r\n"
4935 "Content-Length: 0\r\n\r\n"),
4936 };
4937
4938 // Lastly, the server responds with the actual content.
4939 MockRead data_reads[] = {
4940 MockRead("HTTP/1.0 200 OK\r\n"),
4941 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4942 MockRead("Content-Length: 100\r\n\r\n"),
4943 MockRead(false, OK),
4944 };
4945
[email protected]31a2bfe2010-02-09 08:03:394946 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4947 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594948 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424949
4950 TestCompletionCallback callback;
4951
[email protected]5a1d7ca2010-04-28 20:12:274952 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424953 EXPECT_EQ(ERR_IO_PENDING, rv);
4954
4955 rv = callback.WaitForResult();
4956 EXPECT_EQ(OK, rv);
4957}
4958
4959TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424960 HttpRequestInfo request;
4961 request.method = "PUT";
4962 request.url = GURL("http://www.google.com/");
4963
[email protected]cb9bf6ca2011-01-28 13:15:274964 SessionDependencies session_deps;
4965 scoped_ptr<HttpTransaction> trans(
4966 new HttpNetworkTransaction(CreateSession(&session_deps)));
4967
[email protected]1c773ea12009-04-28 19:58:424968 MockWrite data_writes[] = {
4969 MockWrite("PUT / HTTP/1.1\r\n"
4970 "Host: www.google.com\r\n"
4971 "Connection: keep-alive\r\n"
4972 "Content-Length: 0\r\n\r\n"),
4973 };
4974
4975 // Lastly, the server responds with the actual content.
4976 MockRead data_reads[] = {
4977 MockRead("HTTP/1.0 200 OK\r\n"),
4978 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4979 MockRead("Content-Length: 100\r\n\r\n"),
4980 MockRead(false, OK),
4981 };
4982
[email protected]31a2bfe2010-02-09 08:03:394983 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4984 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594985 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424986
4987 TestCompletionCallback callback;
4988
[email protected]5a1d7ca2010-04-28 20:12:274989 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424990 EXPECT_EQ(ERR_IO_PENDING, rv);
4991
4992 rv = callback.WaitForResult();
4993 EXPECT_EQ(OK, rv);
4994}
4995
4996TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424997 HttpRequestInfo request;
4998 request.method = "HEAD";
4999 request.url = GURL("http://www.google.com/");
5000
[email protected]cb9bf6ca2011-01-28 13:15:275001 SessionDependencies session_deps;
5002 scoped_ptr<HttpTransaction> trans(
5003 new HttpNetworkTransaction(CreateSession(&session_deps)));
5004
[email protected]1c773ea12009-04-28 19:58:425005 MockWrite data_writes[] = {
5006 MockWrite("HEAD / HTTP/1.1\r\n"
5007 "Host: www.google.com\r\n"
5008 "Connection: keep-alive\r\n"
5009 "Content-Length: 0\r\n\r\n"),
5010 };
5011
5012 // Lastly, the server responds with the actual content.
5013 MockRead data_reads[] = {
5014 MockRead("HTTP/1.0 200 OK\r\n"),
5015 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5016 MockRead("Content-Length: 100\r\n\r\n"),
5017 MockRead(false, OK),
5018 };
5019
[email protected]31a2bfe2010-02-09 08:03:395020 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5021 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595022 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425023
5024 TestCompletionCallback callback;
5025
[email protected]5a1d7ca2010-04-28 20:12:275026 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425027 EXPECT_EQ(ERR_IO_PENDING, rv);
5028
5029 rv = callback.WaitForResult();
5030 EXPECT_EQ(OK, rv);
5031}
5032
5033TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425034 HttpRequestInfo request;
5035 request.method = "GET";
5036 request.url = GURL("http://www.google.com/");
5037 request.load_flags = LOAD_BYPASS_CACHE;
5038
[email protected]cb9bf6ca2011-01-28 13:15:275039 SessionDependencies session_deps;
5040 scoped_ptr<HttpTransaction> trans(
5041 new HttpNetworkTransaction(CreateSession(&session_deps)));
5042
[email protected]1c773ea12009-04-28 19:58:425043 MockWrite data_writes[] = {
5044 MockWrite("GET / HTTP/1.1\r\n"
5045 "Host: www.google.com\r\n"
5046 "Connection: keep-alive\r\n"
5047 "Pragma: no-cache\r\n"
5048 "Cache-Control: no-cache\r\n\r\n"),
5049 };
5050
5051 // Lastly, the server responds with the actual content.
5052 MockRead data_reads[] = {
5053 MockRead("HTTP/1.0 200 OK\r\n"),
5054 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5055 MockRead("Content-Length: 100\r\n\r\n"),
5056 MockRead(false, OK),
5057 };
5058
[email protected]31a2bfe2010-02-09 08:03:395059 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5060 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595061 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425062
5063 TestCompletionCallback callback;
5064
[email protected]5a1d7ca2010-04-28 20:12:275065 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425066 EXPECT_EQ(ERR_IO_PENDING, rv);
5067
5068 rv = callback.WaitForResult();
5069 EXPECT_EQ(OK, rv);
5070}
5071
5072TEST_F(HttpNetworkTransactionTest,
5073 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425074 HttpRequestInfo request;
5075 request.method = "GET";
5076 request.url = GURL("http://www.google.com/");
5077 request.load_flags = LOAD_VALIDATE_CACHE;
5078
[email protected]cb9bf6ca2011-01-28 13:15:275079 SessionDependencies session_deps;
5080 scoped_ptr<HttpTransaction> trans(
5081 new HttpNetworkTransaction(CreateSession(&session_deps)));
5082
[email protected]1c773ea12009-04-28 19:58:425083 MockWrite data_writes[] = {
5084 MockWrite("GET / HTTP/1.1\r\n"
5085 "Host: www.google.com\r\n"
5086 "Connection: keep-alive\r\n"
5087 "Cache-Control: max-age=0\r\n\r\n"),
5088 };
5089
5090 // Lastly, the server responds with the actual content.
5091 MockRead data_reads[] = {
5092 MockRead("HTTP/1.0 200 OK\r\n"),
5093 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5094 MockRead("Content-Length: 100\r\n\r\n"),
5095 MockRead(false, OK),
5096 };
5097
[email protected]31a2bfe2010-02-09 08:03:395098 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5099 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595100 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425101
5102 TestCompletionCallback callback;
5103
[email protected]5a1d7ca2010-04-28 20:12:275104 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425105 EXPECT_EQ(ERR_IO_PENDING, rv);
5106
5107 rv = callback.WaitForResult();
5108 EXPECT_EQ(OK, rv);
5109}
5110
5111TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425112 HttpRequestInfo request;
5113 request.method = "GET";
5114 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435115 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425116
[email protected]cb9bf6ca2011-01-28 13:15:275117 SessionDependencies session_deps;
5118 scoped_ptr<HttpTransaction> trans(
5119 new HttpNetworkTransaction(CreateSession(&session_deps)));
5120
[email protected]1c773ea12009-04-28 19:58:425121 MockWrite data_writes[] = {
5122 MockWrite("GET / HTTP/1.1\r\n"
5123 "Host: www.google.com\r\n"
5124 "Connection: keep-alive\r\n"
5125 "FooHeader: Bar\r\n\r\n"),
5126 };
5127
5128 // Lastly, the server responds with the actual content.
5129 MockRead data_reads[] = {
5130 MockRead("HTTP/1.0 200 OK\r\n"),
5131 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5132 MockRead("Content-Length: 100\r\n\r\n"),
5133 MockRead(false, OK),
5134 };
5135
[email protected]31a2bfe2010-02-09 08:03:395136 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5137 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595138 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425139
5140 TestCompletionCallback callback;
5141
[email protected]5a1d7ca2010-04-28 20:12:275142 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425143 EXPECT_EQ(ERR_IO_PENDING, rv);
5144
5145 rv = callback.WaitForResult();
5146 EXPECT_EQ(OK, rv);
5147}
5148
[email protected]270c6412010-03-29 22:02:475149TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475150 HttpRequestInfo request;
5151 request.method = "GET";
5152 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435153 request.extra_headers.SetHeader("referer", "www.foo.com");
5154 request.extra_headers.SetHeader("hEllo", "Kitty");
5155 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475156
[email protected]cb9bf6ca2011-01-28 13:15:275157 SessionDependencies session_deps;
5158 scoped_ptr<HttpTransaction> trans(
5159 new HttpNetworkTransaction(CreateSession(&session_deps)));
5160
[email protected]270c6412010-03-29 22:02:475161 MockWrite data_writes[] = {
5162 MockWrite("GET / HTTP/1.1\r\n"
5163 "Host: www.google.com\r\n"
5164 "Connection: keep-alive\r\n"
5165 "hEllo: Kitty\r\n"
5166 "FoO: bar\r\n\r\n"),
5167 };
5168
5169 // Lastly, the server responds with the actual content.
5170 MockRead data_reads[] = {
5171 MockRead("HTTP/1.0 200 OK\r\n"),
5172 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5173 MockRead("Content-Length: 100\r\n\r\n"),
5174 MockRead(false, OK),
5175 };
5176
5177 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5178 data_writes, arraysize(data_writes));
5179 session_deps.socket_factory.AddSocketDataProvider(&data);
5180
5181 TestCompletionCallback callback;
5182
[email protected]5a1d7ca2010-04-28 20:12:275183 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475184 EXPECT_EQ(ERR_IO_PENDING, rv);
5185
5186 rv = callback.WaitForResult();
5187 EXPECT_EQ(OK, rv);
5188}
5189
[email protected]3cd17242009-06-23 02:59:025190TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275191 HttpRequestInfo request;
5192 request.method = "GET";
5193 request.url = GURL("http://www.google.com/");
5194 request.load_flags = 0;
5195
[email protected]80d6524d2009-08-18 03:58:095196 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005197 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025198
5199 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435200 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025201
[email protected]3cd17242009-06-23 02:59:025202 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5203 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5204
5205 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355206 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025207 MockWrite("GET / HTTP/1.1\r\n"
5208 "Host: www.google.com\r\n"
5209 "Connection: keep-alive\r\n\r\n")
5210 };
5211
5212 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595213 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025214 MockRead("HTTP/1.0 200 OK\r\n"),
5215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5216 MockRead("Payload"),
5217 MockRead(false, OK)
5218 };
5219
[email protected]31a2bfe2010-02-09 08:03:395220 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5221 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595222 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025223
5224 TestCompletionCallback callback;
5225
[email protected]5a1d7ca2010-04-28 20:12:275226 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025227 EXPECT_EQ(ERR_IO_PENDING, rv);
5228
5229 rv = callback.WaitForResult();
5230 EXPECT_EQ(OK, rv);
5231
5232 const HttpResponseInfo* response = trans->GetResponseInfo();
5233 EXPECT_FALSE(response == NULL);
5234
5235 std::string response_text;
5236 rv = ReadTransaction(trans.get(), &response_text);
5237 EXPECT_EQ(OK, rv);
5238 EXPECT_EQ("Payload", response_text);
5239}
5240
5241TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275242 HttpRequestInfo request;
5243 request.method = "GET";
5244 request.url = GURL("https://www.google.com/");
5245 request.load_flags = 0;
5246
[email protected]80d6524d2009-08-18 03:58:095247 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005248 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025249
5250 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435251 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025252
[email protected]3cd17242009-06-23 02:59:025253 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5254 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5255
5256 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355257 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5258 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025259 MockWrite("GET / HTTP/1.1\r\n"
5260 "Host: www.google.com\r\n"
5261 "Connection: keep-alive\r\n\r\n")
5262 };
5263
5264 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355265 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5266 arraysize(read_buffer)),
5267 MockRead("HTTP/1.0 200 OK\r\n"),
5268 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5269 MockRead("Payload"),
5270 MockRead(false, OK)
5271 };
5272
[email protected]31a2bfe2010-02-09 08:03:395273 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5274 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595275 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355276
[email protected]5ecc992a42009-11-11 01:41:595277 SSLSocketDataProvider ssl(true, OK);
5278 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355279
5280 TestCompletionCallback callback;
5281
[email protected]5a1d7ca2010-04-28 20:12:275282 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355283 EXPECT_EQ(ERR_IO_PENDING, rv);
5284
5285 rv = callback.WaitForResult();
5286 EXPECT_EQ(OK, rv);
5287
5288 const HttpResponseInfo* response = trans->GetResponseInfo();
5289 EXPECT_FALSE(response == NULL);
5290
5291 std::string response_text;
5292 rv = ReadTransaction(trans.get(), &response_text);
5293 EXPECT_EQ(OK, rv);
5294 EXPECT_EQ("Payload", response_text);
5295}
5296
5297TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275298 HttpRequestInfo request;
5299 request.method = "GET";
5300 request.url = GURL("http://www.google.com/");
5301 request.load_flags = 0;
5302
[email protected]80d6524d2009-08-18 03:58:095303 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005304 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355305
5306 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435307 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355308
[email protected]e0c27be2009-07-15 13:09:355309 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5310 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375311 const char kSOCKS5OkRequest[] = {
5312 0x05, // Version
5313 0x01, // Command (CONNECT)
5314 0x00, // Reserved.
5315 0x03, // Address type (DOMAINNAME).
5316 0x0E, // Length of domain (14)
5317 // Domain string:
5318 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5319 0x00, 0x50, // 16-bit port (80)
5320 };
[email protected]e0c27be2009-07-15 13:09:355321 const char kSOCKS5OkResponse[] =
5322 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5323
5324 MockWrite data_writes[] = {
5325 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5326 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5327 MockWrite("GET / HTTP/1.1\r\n"
5328 "Host: www.google.com\r\n"
5329 "Connection: keep-alive\r\n\r\n")
5330 };
5331
5332 MockRead data_reads[] = {
5333 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5334 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5335 MockRead("HTTP/1.0 200 OK\r\n"),
5336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5337 MockRead("Payload"),
5338 MockRead(false, OK)
5339 };
5340
[email protected]31a2bfe2010-02-09 08:03:395341 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5342 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595343 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355344
5345 TestCompletionCallback callback;
5346
[email protected]5a1d7ca2010-04-28 20:12:275347 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355348 EXPECT_EQ(ERR_IO_PENDING, rv);
5349
5350 rv = callback.WaitForResult();
5351 EXPECT_EQ(OK, rv);
5352
5353 const HttpResponseInfo* response = trans->GetResponseInfo();
5354 EXPECT_FALSE(response == NULL);
5355
5356 std::string response_text;
5357 rv = ReadTransaction(trans.get(), &response_text);
5358 EXPECT_EQ(OK, rv);
5359 EXPECT_EQ("Payload", response_text);
5360}
5361
5362TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275363 HttpRequestInfo request;
5364 request.method = "GET";
5365 request.url = GURL("https://www.google.com/");
5366 request.load_flags = 0;
5367
[email protected]80d6524d2009-08-18 03:58:095368 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005369 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355370
5371 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435372 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355373
[email protected]e0c27be2009-07-15 13:09:355374 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5375 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375376 const unsigned char kSOCKS5OkRequest[] = {
5377 0x05, // Version
5378 0x01, // Command (CONNECT)
5379 0x00, // Reserved.
5380 0x03, // Address type (DOMAINNAME).
5381 0x0E, // Length of domain (14)
5382 // Domain string:
5383 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5384 0x01, 0xBB, // 16-bit port (443)
5385 };
5386
[email protected]e0c27be2009-07-15 13:09:355387 const char kSOCKS5OkResponse[] =
5388 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5389
5390 MockWrite data_writes[] = {
5391 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5392 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5393 arraysize(kSOCKS5OkRequest)),
5394 MockWrite("GET / HTTP/1.1\r\n"
5395 "Host: www.google.com\r\n"
5396 "Connection: keep-alive\r\n\r\n")
5397 };
5398
5399 MockRead data_reads[] = {
5400 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5401 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025402 MockRead("HTTP/1.0 200 OK\r\n"),
5403 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5404 MockRead("Payload"),
5405 MockRead(false, OK)
5406 };
5407
[email protected]31a2bfe2010-02-09 08:03:395408 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5409 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595410 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025411
[email protected]5ecc992a42009-11-11 01:41:595412 SSLSocketDataProvider ssl(true, OK);
5413 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025414
5415 TestCompletionCallback callback;
5416
[email protected]5a1d7ca2010-04-28 20:12:275417 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025418 EXPECT_EQ(ERR_IO_PENDING, rv);
5419
5420 rv = callback.WaitForResult();
5421 EXPECT_EQ(OK, rv);
5422
5423 const HttpResponseInfo* response = trans->GetResponseInfo();
5424 EXPECT_FALSE(response == NULL);
5425
5426 std::string response_text;
5427 rv = ReadTransaction(trans.get(), &response_text);
5428 EXPECT_EQ(OK, rv);
5429 EXPECT_EQ("Payload", response_text);
5430}
5431
[email protected]04e5be32009-06-26 20:00:315432// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065433
5434struct GroupNameTest {
5435 std::string proxy_server;
5436 std::string url;
5437 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185438 bool ssl;
[email protected]2d731a32010-04-29 01:04:065439};
5440
5441scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5442 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:005443 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:065444 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5445
5446 HttpAlternateProtocols* alternate_protocols =
5447 session->mutable_alternate_protocols();
5448 alternate_protocols->SetAlternateProtocolFor(
5449 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355450 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065451
5452 return session;
5453}
5454
5455int GroupNameTransactionHelper(
5456 const std::string& url,
5457 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065458 HttpRequestInfo request;
5459 request.method = "GET";
5460 request.url = GURL(url);
5461 request.load_flags = 0;
5462
[email protected]cb9bf6ca2011-01-28 13:15:275463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5464
[email protected]2d731a32010-04-29 01:04:065465 TestCompletionCallback callback;
5466
5467 // We do not complete this request, the dtor will clean the transaction up.
5468 return trans->Start(&request, &callback, BoundNetLog());
5469}
5470
5471TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5472 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315473 {
[email protected]2d731a32010-04-29 01:04:065474 "", // unused
[email protected]04e5be32009-06-26 20:00:315475 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545476 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185477 false,
[email protected]2ff8b312010-04-26 22:20:545478 },
5479 {
[email protected]2d731a32010-04-29 01:04:065480 "", // unused
[email protected]2ff8b312010-04-26 22:20:545481 "http://[2001:1418:13:1::25]/direct",
5482 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185483 false,
[email protected]04e5be32009-06-26 20:00:315484 },
[email protected]04e5be32009-06-26 20:00:315485
5486 // SSL Tests
5487 {
[email protected]2d731a32010-04-29 01:04:065488 "", // unused
[email protected]04e5be32009-06-26 20:00:315489 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025490 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185491 true,
[email protected]04e5be32009-06-26 20:00:315492 },
5493 {
[email protected]2d731a32010-04-29 01:04:065494 "", // unused
5495 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025496 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185497 true,
[email protected]04e5be32009-06-26 20:00:315498 },
5499 {
[email protected]2d731a32010-04-29 01:04:065500 "", // unused
[email protected]2ff8b312010-04-26 22:20:545501 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025502 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185503 true,
[email protected]2ff8b312010-04-26 22:20:545504 },
[email protected]2d731a32010-04-29 01:04:065505 };
[email protected]2ff8b312010-04-26 22:20:545506
[email protected]8e6441ca2010-08-19 05:56:385507 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065508
5509 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5510 scoped_refptr<HttpNetworkSession> session(
5511 SetupSessionForGroupNameTests(tests[i].proxy_server));
5512
5513 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135514 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345515 new CaptureGroupNameTCPSocketPool(NULL, NULL);
[email protected]2d731a32010-04-29 01:04:065516 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135517 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345518 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185519 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065520
5521 EXPECT_EQ(ERR_IO_PENDING,
5522 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185523 if (tests[i].ssl)
5524 EXPECT_EQ(tests[i].expected_group_name,
5525 ssl_conn_pool->last_group_name_received());
5526 else
5527 EXPECT_EQ(tests[i].expected_group_name,
5528 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065529 }
5530
[email protected]8e6441ca2010-08-19 05:56:385531 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065532}
5533
5534TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5535 const GroupNameTest tests[] = {
5536 {
5537 "http_proxy",
5538 "http://www.google.com/http_proxy_normal",
5539 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185540 false,
[email protected]2d731a32010-04-29 01:04:065541 },
5542
5543 // SSL Tests
5544 {
5545 "http_proxy",
5546 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025547 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185548 true,
[email protected]2d731a32010-04-29 01:04:065549 },
[email protected]af3490e2010-10-16 21:02:295550
[email protected]9faeded92010-04-29 20:03:055551 {
5552 "http_proxy",
5553 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025554 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185555 true,
[email protected]9faeded92010-04-29 20:03:055556 },
[email protected]2d731a32010-04-29 01:04:065557 };
5558
[email protected]8e6441ca2010-08-19 05:56:385559 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065560
5561 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5562 scoped_refptr<HttpNetworkSession> session(
5563 SetupSessionForGroupNameTests(tests[i].proxy_server));
5564
5565 HttpNetworkSessionPeer peer(session);
5566
[email protected]e60e47a2010-07-14 03:37:185567 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135568 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345569 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185570 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135571 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345572 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185573 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065574
5575 EXPECT_EQ(ERR_IO_PENDING,
5576 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185577 if (tests[i].ssl)
5578 EXPECT_EQ(tests[i].expected_group_name,
5579 ssl_conn_pool->last_group_name_received());
5580 else
5581 EXPECT_EQ(tests[i].expected_group_name,
5582 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065583 }
5584
[email protected]8e6441ca2010-08-19 05:56:385585 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065586}
5587
5588TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5589 const GroupNameTest tests[] = {
5590 {
5591 "socks4://socks_proxy:1080",
5592 "http://www.google.com/socks4_direct",
5593 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185594 false,
[email protected]2d731a32010-04-29 01:04:065595 },
5596 {
5597 "socks5://socks_proxy:1080",
5598 "http://www.google.com/socks5_direct",
5599 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185600 false,
[email protected]2d731a32010-04-29 01:04:065601 },
5602
5603 // SSL Tests
5604 {
5605 "socks4://socks_proxy:1080",
5606 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025607 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185608 true,
[email protected]2d731a32010-04-29 01:04:065609 },
5610 {
5611 "socks5://socks_proxy:1080",
5612 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025613 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185614 true,
[email protected]2d731a32010-04-29 01:04:065615 },
[email protected]af3490e2010-10-16 21:02:295616
[email protected]9faeded92010-04-29 20:03:055617 {
5618 "socks4://socks_proxy:1080",
5619 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025620 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185621 true,
[email protected]9faeded92010-04-29 20:03:055622 },
[email protected]04e5be32009-06-26 20:00:315623 };
5624
[email protected]8e6441ca2010-08-19 05:56:385625 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545626
[email protected]04e5be32009-06-26 20:00:315627 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065628 scoped_refptr<HttpNetworkSession> session(
5629 SetupSessionForGroupNameTests(tests[i].proxy_server));
5630 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315631
[email protected]e60e47a2010-07-14 03:37:185632 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135633 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345634 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185635 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135636 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345637 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185638 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315639
[email protected]5695b8c2009-09-30 21:36:435640 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315641
[email protected]2d731a32010-04-29 01:04:065642 EXPECT_EQ(ERR_IO_PENDING,
5643 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185644 if (tests[i].ssl)
5645 EXPECT_EQ(tests[i].expected_group_name,
5646 ssl_conn_pool->last_group_name_received());
5647 else
5648 EXPECT_EQ(tests[i].expected_group_name,
5649 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315650 }
[email protected]2ff8b312010-04-26 22:20:545651
[email protected]8e6441ca2010-08-19 05:56:385652 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315653}
5654
[email protected]9172a982009-06-06 00:30:255655TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275656 HttpRequestInfo request;
5657 request.method = "GET";
5658 request.url = GURL("http://www.google.com/");
5659
[email protected]5c6a17e2009-06-10 00:54:545660 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005661 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325662
[email protected]69719062010-01-05 20:09:215663 // This simulates failure resolving all hostnames; that means we will fail
5664 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325665 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5666
[email protected]9172a982009-06-06 00:30:255667 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435668 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255669
[email protected]9172a982009-06-06 00:30:255670 TestCompletionCallback callback;
5671
[email protected]5a1d7ca2010-04-28 20:12:275672 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255673 EXPECT_EQ(ERR_IO_PENDING, rv);
5674
[email protected]9172a982009-06-06 00:30:255675 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015676 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255677}
5678
[email protected]f3e6c1e2009-06-15 20:52:125679// Host resolution observer used by
5680// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5681// resovle requests are issued with a referrer of |expected_referrer|.
5682class ResolutionReferrerObserver : public HostResolver::Observer {
5683 public:
5684 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5685 : expected_referrer_(expected_referrer),
5686 called_start_with_referrer_(false),
5687 called_finish_with_referrer_(false) {
5688 }
5689
5690 virtual void OnStartResolution(int id,
5691 const HostResolver::RequestInfo& info) {
5692 if (info.referrer() == expected_referrer_)
5693 called_start_with_referrer_ = true;
5694 }
5695
5696 virtual void OnFinishResolutionWithStatus(
5697 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5698 if (info.referrer() == expected_referrer_)
5699 called_finish_with_referrer_ = true;
5700 }
5701
[email protected]eb255d32009-06-17 02:11:035702 virtual void OnCancelResolution(int id,
5703 const HostResolver::RequestInfo& info ) {
5704 FAIL() << "Should not be cancelling any requests!";
5705 }
5706
[email protected]f3e6c1e2009-06-15 20:52:125707 bool did_complete_with_expected_referrer() const {
5708 return called_start_with_referrer_ && called_finish_with_referrer_;
5709 }
5710
5711 private:
5712 GURL expected_referrer_;
5713 bool called_start_with_referrer_;
5714 bool called_finish_with_referrer_;
5715
5716 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5717};
5718
5719// Make sure that when HostResolver::Resolve() is invoked, it passes through
5720// the "referrer". This is depended on by the DNS prefetch observer.
5721TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5722 GURL referrer = GURL("http://expected-referrer/");
5723 EXPECT_TRUE(referrer.is_valid());
5724 ResolutionReferrerObserver resolution_observer(referrer);
5725
[email protected]cb9bf6ca2011-01-28 13:15:275726 // Issue a request, containing an HTTP referrer.
5727 HttpRequestInfo request;
5728 request.method = "GET";
5729 request.referrer = referrer;
5730 request.url = GURL("http://www.google.com/");
5731
[email protected]f3e6c1e2009-06-15 20:52:125732 SessionDependencies session_deps;
5733 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435734 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125735
5736 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145737 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125738
5739 // Connect up a mock socket which will fail when reading.
5740 MockRead data_reads[] = {
5741 MockRead(false, ERR_FAILED),
5742 };
[email protected]31a2bfe2010-02-09 08:03:395743 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595744 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125745
[email protected]f3e6c1e2009-06-15 20:52:125746 // Run the request until it fails reading from the socket.
5747 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275748 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125749 EXPECT_EQ(ERR_IO_PENDING, rv);
5750 rv = callback.WaitForResult();
5751 EXPECT_EQ(ERR_FAILED, rv);
5752
5753 // Check that the host resolution observer saw |referrer|.
5754 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5755}
5756
[email protected]685af592010-05-11 19:31:245757// Base test to make sure that when the load flags for a request specify to
5758// bypass the cache, the DNS cache is not used.
5759void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275760 // Issue a request, asking to bypass the cache(s).
5761 HttpRequestInfo request;
5762 request.method = "GET";
5763 request.load_flags = load_flags;
5764 request.url = GURL("http://www.google.com/");
5765
[email protected]3b9cca42009-06-16 01:08:285766 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325767
[email protected]a2c2fb92009-07-18 07:31:045768 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545769 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325770
[email protected]3b9cca42009-06-16 01:08:285771 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435772 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285773
5774 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5775 // a synchronous lookup.)
5776 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145777 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105778 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275779 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285780 EXPECT_EQ(OK, rv);
5781
5782 // Verify that it was added to host cache, by doing a subsequent async lookup
5783 // and confirming it completes synchronously.
5784 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465785 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105786 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275787 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325788 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285789
5790 // Inject a failure the next time that "www.google.com" is resolved. This way
5791 // we can tell if the next lookup hit the cache, or the "network".
5792 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325793 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285794
5795 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5796 // first read -- this won't be reached as the host resolution will fail first.
5797 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395798 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595799 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285800
[email protected]3b9cca42009-06-16 01:08:285801 // Run the request.
5802 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275803 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285804 ASSERT_EQ(ERR_IO_PENDING, rv);
5805 rv = callback.WaitForResult();
5806
5807 // If we bypassed the cache, we would have gotten a failure while resolving
5808 // "www.google.com".
5809 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5810}
5811
[email protected]685af592010-05-11 19:31:245812// There are multiple load flags that should trigger the host cache bypass.
5813// Test each in isolation:
5814TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5815 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5816}
5817
5818TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5819 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5820}
5821
5822TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5823 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5824}
5825
[email protected]0877e3d2009-10-17 22:29:575826// Make sure we can handle an error when writing the request.
5827TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5828 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575830
5831 HttpRequestInfo request;
5832 request.method = "GET";
5833 request.url = GURL("http://www.foo.com/");
5834 request.load_flags = 0;
5835
5836 MockWrite write_failure[] = {
5837 MockWrite(true, ERR_CONNECTION_RESET),
5838 };
[email protected]31a2bfe2010-02-09 08:03:395839 StaticSocketDataProvider data(NULL, 0,
5840 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595841 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575842
5843 TestCompletionCallback callback;
5844
5845 scoped_ptr<HttpTransaction> trans(
5846 new HttpNetworkTransaction(CreateSession(&session_deps)));
5847
[email protected]5a1d7ca2010-04-28 20:12:275848 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575849 EXPECT_EQ(ERR_IO_PENDING, rv);
5850
5851 rv = callback.WaitForResult();
5852 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5853}
5854
5855// Check that a connection closed after the start of the headers finishes ok.
5856TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5857 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275858 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575859
5860 HttpRequestInfo request;
5861 request.method = "GET";
5862 request.url = GURL("http://www.foo.com/");
5863 request.load_flags = 0;
5864
5865 MockRead data_reads[] = {
5866 MockRead("HTTP/1."),
5867 MockRead(false, OK),
5868 };
5869
[email protected]31a2bfe2010-02-09 08:03:395870 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595871 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575872
5873 TestCompletionCallback callback;
5874
5875 scoped_ptr<HttpTransaction> trans(
5876 new HttpNetworkTransaction(CreateSession(&session_deps)));
5877
[email protected]5a1d7ca2010-04-28 20:12:275878 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575879 EXPECT_EQ(ERR_IO_PENDING, rv);
5880
5881 rv = callback.WaitForResult();
5882 EXPECT_EQ(OK, rv);
5883
5884 const HttpResponseInfo* response = trans->GetResponseInfo();
5885 EXPECT_TRUE(response != NULL);
5886
5887 EXPECT_TRUE(response->headers != NULL);
5888 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5889
5890 std::string response_data;
5891 rv = ReadTransaction(trans.get(), &response_data);
5892 EXPECT_EQ(OK, rv);
5893 EXPECT_EQ("", response_data);
5894}
5895
5896// Make sure that a dropped connection while draining the body for auth
5897// restart does the right thing.
5898TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5899 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275900 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575901
5902 HttpRequestInfo request;
5903 request.method = "GET";
5904 request.url = GURL("http://www.google.com/");
5905 request.load_flags = 0;
5906
5907 MockWrite data_writes1[] = {
5908 MockWrite("GET / HTTP/1.1\r\n"
5909 "Host: www.google.com\r\n"
5910 "Connection: keep-alive\r\n\r\n"),
5911 };
5912
5913 MockRead data_reads1[] = {
5914 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5915 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5916 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5917 MockRead("Content-Length: 14\r\n\r\n"),
5918 MockRead("Unauth"),
5919 MockRead(true, ERR_CONNECTION_RESET),
5920 };
5921
[email protected]31a2bfe2010-02-09 08:03:395922 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5923 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595924 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575925
5926 // After calling trans->RestartWithAuth(), this is the request we should
5927 // be issuing -- the final header line contains the credentials.
5928 MockWrite data_writes2[] = {
5929 MockWrite("GET / HTTP/1.1\r\n"
5930 "Host: www.google.com\r\n"
5931 "Connection: keep-alive\r\n"
5932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5933 };
5934
5935 // Lastly, the server responds with the actual content.
5936 MockRead data_reads2[] = {
5937 MockRead("HTTP/1.1 200 OK\r\n"),
5938 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5939 MockRead("Content-Length: 100\r\n\r\n"),
5940 MockRead(false, OK),
5941 };
5942
[email protected]31a2bfe2010-02-09 08:03:395943 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5944 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595945 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575946
5947 TestCompletionCallback callback1;
5948
[email protected]0b0bf032010-09-21 18:08:505949 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5950
[email protected]5a1d7ca2010-04-28 20:12:275951 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575952 EXPECT_EQ(ERR_IO_PENDING, rv);
5953
5954 rv = callback1.WaitForResult();
5955 EXPECT_EQ(OK, rv);
5956
5957 const HttpResponseInfo* response = trans->GetResponseInfo();
5958 EXPECT_FALSE(response == NULL);
5959
5960 // The password prompt info should have been set in response->auth_challenge.
5961 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5962
5963 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5964 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5965 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5966
5967 TestCompletionCallback callback2;
5968
[email protected]13c8a092010-07-29 06:15:445969 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575970 EXPECT_EQ(ERR_IO_PENDING, rv);
5971
5972 rv = callback2.WaitForResult();
5973 EXPECT_EQ(OK, rv);
5974
5975 response = trans->GetResponseInfo();
5976 EXPECT_FALSE(response == NULL);
5977 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5978 EXPECT_EQ(100, response->headers->GetContentLength());
5979}
5980
5981// Test HTTPS connections going through a proxy that sends extra data.
5982TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005983 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575984
5985 HttpRequestInfo request;
5986 request.method = "GET";
5987 request.url = GURL("https://www.google.com/");
5988 request.load_flags = 0;
5989
5990 MockRead proxy_reads[] = {
5991 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5992 MockRead(false, OK)
5993 };
5994
[email protected]31a2bfe2010-02-09 08:03:395995 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595996 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575997
[email protected]5ecc992a42009-11-11 01:41:595998 session_deps.socket_factory.AddSocketDataProvider(&data);
5999 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576000
6001 TestCompletionCallback callback;
6002
6003 session_deps.socket_factory.ResetNextMockIndexes();
6004
6005 scoped_ptr<HttpTransaction> trans(
6006 new HttpNetworkTransaction(CreateSession(&session_deps)));
6007
[email protected]5a1d7ca2010-04-28 20:12:276008 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576009 EXPECT_EQ(ERR_IO_PENDING, rv);
6010
6011 rv = callback.WaitForResult();
6012 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6013}
6014
[email protected]e22e1362009-11-23 21:31:126015TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466016 HttpRequestInfo request;
6017 request.method = "GET";
6018 request.url = GURL("http://www.google.com/");
6019 request.load_flags = 0;
6020
[email protected]cb9bf6ca2011-01-28 13:15:276021 SessionDependencies session_deps;
6022 scoped_ptr<HttpTransaction> trans(
6023 new HttpNetworkTransaction(CreateSession(&session_deps)));
6024
[email protected]e22e1362009-11-23 21:31:126025 MockRead data_reads[] = {
6026 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6027 MockRead(false, OK),
6028 };
[email protected]9492e4a2010-02-24 00:58:466029
6030 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6031 session_deps.socket_factory.AddSocketDataProvider(&data);
6032
6033 TestCompletionCallback callback;
6034
[email protected]5a1d7ca2010-04-28 20:12:276035 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466036 EXPECT_EQ(ERR_IO_PENDING, rv);
6037
6038 EXPECT_EQ(OK, callback.WaitForResult());
6039
6040 const HttpResponseInfo* response = trans->GetResponseInfo();
6041 EXPECT_TRUE(response != NULL);
6042
6043 EXPECT_TRUE(response->headers != NULL);
6044 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6045
6046 std::string response_data;
6047 rv = ReadTransaction(trans.get(), &response_data);
6048 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126049}
6050
[email protected]95d88ffe2010-02-04 21:25:336051TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336052 HttpRequestInfo request;
6053 request.method = "POST";
6054 request.url = GURL("http://www.google.com/upload");
6055 request.upload_data = new UploadData;
6056 request.load_flags = 0;
6057
[email protected]cb9bf6ca2011-01-28 13:15:276058 SessionDependencies session_deps;
6059 scoped_ptr<HttpTransaction> trans(
6060 new HttpNetworkTransaction(CreateSession(&session_deps)));
6061
[email protected]95d88ffe2010-02-04 21:25:336062 FilePath temp_file_path;
6063 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6064 const uint64 kFakeSize = 100000; // file is actually blank
6065
6066 std::vector<UploadData::Element> elements;
6067 UploadData::Element element;
6068 element.SetToFilePath(temp_file_path);
6069 element.SetContentLength(kFakeSize);
6070 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536071 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336072 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6073
6074 MockRead data_reads[] = {
6075 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6076 MockRead("hello world"),
6077 MockRead(false, OK),
6078 };
[email protected]31a2bfe2010-02-09 08:03:396079 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336080 session_deps.socket_factory.AddSocketDataProvider(&data);
6081
6082 TestCompletionCallback callback;
6083
[email protected]5a1d7ca2010-04-28 20:12:276084 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336085 EXPECT_EQ(ERR_IO_PENDING, rv);
6086
6087 rv = callback.WaitForResult();
6088 EXPECT_EQ(OK, rv);
6089
6090 const HttpResponseInfo* response = trans->GetResponseInfo();
6091 EXPECT_TRUE(response != NULL);
6092
6093 EXPECT_TRUE(response->headers != NULL);
6094 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6095
6096 std::string response_data;
6097 rv = ReadTransaction(trans.get(), &response_data);
6098 EXPECT_EQ(OK, rv);
6099 EXPECT_EQ("hello world", response_data);
6100
6101 file_util::Delete(temp_file_path, false);
6102}
6103
[email protected]6624b4622010-03-29 19:58:366104TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276105 HttpRequestInfo request;
6106 request.method = "POST";
6107 request.url = GURL("http://www.google.com/upload");
6108 request.upload_data = new UploadData;
6109 request.load_flags = 0;
6110
[email protected]6624b4622010-03-29 19:58:366111 // If we try to upload an unreadable file, the network stack should report
6112 // the file size as zero and upload zero bytes for that file.
6113 SessionDependencies session_deps;
6114 scoped_ptr<HttpTransaction> trans(
6115 new HttpNetworkTransaction(CreateSession(&session_deps)));
6116
6117 FilePath temp_file;
6118 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6119 std::string temp_file_content("Unreadable file.");
6120 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6121 temp_file_content.length()));
6122 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6123
[email protected]6624b4622010-03-29 19:58:366124 std::vector<UploadData::Element> elements;
6125 UploadData::Element element;
6126 element.SetToFilePath(temp_file);
6127 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536128 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366129
6130 MockRead data_reads[] = {
6131 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6132 MockRead(false, OK),
6133 };
6134 MockWrite data_writes[] = {
6135 MockWrite("POST /upload HTTP/1.1\r\n"
6136 "Host: www.google.com\r\n"
6137 "Connection: keep-alive\r\n"
6138 "Content-Length: 0\r\n\r\n"),
6139 MockWrite(false, OK),
6140 };
6141 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6142 arraysize(data_writes));
6143 session_deps.socket_factory.AddSocketDataProvider(&data);
6144
6145 TestCompletionCallback callback;
6146
[email protected]5a1d7ca2010-04-28 20:12:276147 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366148 EXPECT_EQ(ERR_IO_PENDING, rv);
6149
6150 rv = callback.WaitForResult();
6151 EXPECT_EQ(OK, rv);
6152
6153 const HttpResponseInfo* response = trans->GetResponseInfo();
6154 EXPECT_TRUE(response != NULL);
6155 EXPECT_TRUE(response->headers != NULL);
6156 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6157
6158 file_util::Delete(temp_file, false);
6159}
6160
6161TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276162 HttpRequestInfo request;
6163 request.method = "POST";
6164 request.url = GURL("http://www.google.com/upload");
6165 request.upload_data = new UploadData;
6166 request.load_flags = 0;
6167
[email protected]6624b4622010-03-29 19:58:366168 SessionDependencies session_deps;
6169 scoped_ptr<HttpTransaction> trans(
6170 new HttpNetworkTransaction(CreateSession(&session_deps)));
6171
6172 FilePath temp_file;
6173 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6174 std::string temp_file_contents("Unreadable file.");
6175 std::string unreadable_contents(temp_file_contents.length(), '\0');
6176 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6177 temp_file_contents.length()));
6178
[email protected]6624b4622010-03-29 19:58:366179 std::vector<UploadData::Element> elements;
6180 UploadData::Element element;
6181 element.SetToFilePath(temp_file);
6182 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536183 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366184
6185 MockRead data_reads[] = {
6186 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6187 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6188 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6189
6190 MockRead("HTTP/1.1 200 OK\r\n"),
6191 MockRead("Content-Length: 0\r\n\r\n"),
6192 MockRead(false, OK),
6193 };
6194 MockWrite data_writes[] = {
6195 MockWrite("POST /upload HTTP/1.1\r\n"
6196 "Host: www.google.com\r\n"
6197 "Connection: keep-alive\r\n"
6198 "Content-Length: 16\r\n\r\n"),
6199 MockWrite(false, temp_file_contents.c_str()),
6200
6201 MockWrite("POST /upload HTTP/1.1\r\n"
6202 "Host: www.google.com\r\n"
6203 "Connection: keep-alive\r\n"
6204 "Content-Length: 16\r\n"
6205 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6206 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6207 MockWrite(false, OK),
6208 };
6209 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6210 arraysize(data_writes));
6211 session_deps.socket_factory.AddSocketDataProvider(&data);
6212
6213 TestCompletionCallback callback1;
6214
[email protected]5a1d7ca2010-04-28 20:12:276215 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366216 EXPECT_EQ(ERR_IO_PENDING, rv);
6217
6218 rv = callback1.WaitForResult();
6219 EXPECT_EQ(OK, rv);
6220
6221 const HttpResponseInfo* response = trans->GetResponseInfo();
6222 EXPECT_TRUE(response != NULL);
6223 EXPECT_TRUE(response->headers != NULL);
6224 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6225
6226 // The password prompt info should have been set in response->auth_challenge.
6227 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6228 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6229 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6230 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6231
6232 // Now make the file unreadable and try again.
6233 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6234
6235 TestCompletionCallback callback2;
6236
[email protected]13c8a092010-07-29 06:15:446237 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366238 EXPECT_EQ(ERR_IO_PENDING, rv);
6239
6240 rv = callback2.WaitForResult();
6241 EXPECT_EQ(OK, rv);
6242
6243 response = trans->GetResponseInfo();
6244 EXPECT_TRUE(response != NULL);
6245 EXPECT_TRUE(response->headers != NULL);
6246 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6247 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6248
6249 file_util::Delete(temp_file, false);
6250}
6251
[email protected]aeefc9e82010-02-19 16:18:276252// Tests that changes to Auth realms are treated like auth rejections.
6253TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6254 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276255
6256 HttpRequestInfo request;
6257 request.method = "GET";
6258 request.url = GURL("http://www.google.com/");
6259 request.load_flags = 0;
6260
6261 // First transaction will request a resource and receive a Basic challenge
6262 // with realm="first_realm".
6263 MockWrite data_writes1[] = {
6264 MockWrite("GET / HTTP/1.1\r\n"
6265 "Host: www.google.com\r\n"
6266 "Connection: keep-alive\r\n"
6267 "\r\n"),
6268 };
6269 MockRead data_reads1[] = {
6270 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6271 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6272 "\r\n"),
6273 };
6274
6275 // After calling trans->RestartWithAuth(), provide an Authentication header
6276 // for first_realm. The server will reject and provide a challenge with
6277 // second_realm.
6278 MockWrite data_writes2[] = {
6279 MockWrite("GET / HTTP/1.1\r\n"
6280 "Host: www.google.com\r\n"
6281 "Connection: keep-alive\r\n"
6282 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6283 "\r\n"),
6284 };
6285 MockRead data_reads2[] = {
6286 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6287 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6288 "\r\n"),
6289 };
6290
6291 // This again fails, and goes back to first_realm. Make sure that the
6292 // entry is removed from cache.
6293 MockWrite data_writes3[] = {
6294 MockWrite("GET / HTTP/1.1\r\n"
6295 "Host: www.google.com\r\n"
6296 "Connection: keep-alive\r\n"
6297 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6298 "\r\n"),
6299 };
6300 MockRead data_reads3[] = {
6301 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6302 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6303 "\r\n"),
6304 };
6305
6306 // Try one last time (with the correct password) and get the resource.
6307 MockWrite data_writes4[] = {
6308 MockWrite("GET / HTTP/1.1\r\n"
6309 "Host: www.google.com\r\n"
6310 "Connection: keep-alive\r\n"
6311 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6312 "\r\n"),
6313 };
6314 MockRead data_reads4[] = {
6315 MockRead("HTTP/1.1 200 OK\r\n"
6316 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506317 "Content-Length: 5\r\n"
6318 "\r\n"
6319 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276320 };
6321
6322 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6323 data_writes1, arraysize(data_writes1));
6324 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6325 data_writes2, arraysize(data_writes2));
6326 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6327 data_writes3, arraysize(data_writes3));
6328 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6329 data_writes4, arraysize(data_writes4));
6330 session_deps.socket_factory.AddSocketDataProvider(&data1);
6331 session_deps.socket_factory.AddSocketDataProvider(&data2);
6332 session_deps.socket_factory.AddSocketDataProvider(&data3);
6333 session_deps.socket_factory.AddSocketDataProvider(&data4);
6334
6335 TestCompletionCallback callback1;
6336
[email protected]0b0bf032010-09-21 18:08:506337 scoped_ptr<HttpTransaction> trans(
6338 new HttpNetworkTransaction(CreateSession(&session_deps)));
6339
[email protected]aeefc9e82010-02-19 16:18:276340 // Issue the first request with Authorize headers. There should be a
6341 // password prompt for first_realm waiting to be filled in after the
6342 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276343 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276344 EXPECT_EQ(ERR_IO_PENDING, rv);
6345 rv = callback1.WaitForResult();
6346 EXPECT_EQ(OK, rv);
6347 const HttpResponseInfo* response = trans->GetResponseInfo();
6348 ASSERT_FALSE(response == NULL);
6349 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6350 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6351 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6352 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6353
6354 // Issue the second request with an incorrect password. There should be a
6355 // password prompt for second_realm waiting to be filled in after the
6356 // transaction completes.
6357 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446358 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276359 EXPECT_EQ(ERR_IO_PENDING, rv);
6360 rv = callback2.WaitForResult();
6361 EXPECT_EQ(OK, rv);
6362 response = trans->GetResponseInfo();
6363 ASSERT_FALSE(response == NULL);
6364 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6365 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6366 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6367 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6368
6369 // Issue the third request with another incorrect password. There should be
6370 // a password prompt for first_realm waiting to be filled in. If the password
6371 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6372 // first_realm was not correctly removed.
6373 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446374 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276375 EXPECT_EQ(ERR_IO_PENDING, rv);
6376 rv = callback3.WaitForResult();
6377 EXPECT_EQ(OK, rv);
6378 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 fourth request with the correct password and username.
6386 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446387 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276388 EXPECT_EQ(ERR_IO_PENDING, rv);
6389 rv = callback4.WaitForResult();
6390 EXPECT_EQ(OK, rv);
6391 response = trans->GetResponseInfo();
6392 ASSERT_FALSE(response == NULL);
6393 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6394}
6395
[email protected]564b4912010-03-09 16:30:426396TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386397 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6398 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426399
[email protected]564b4912010-03-09 16:30:426400 SessionDependencies session_deps;
6401
6402 MockRead data_reads[] = {
6403 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356404 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426405 MockRead("hello world"),
6406 MockRead(false, OK),
6407 };
6408
6409 HttpRequestInfo request;
6410 request.method = "GET";
6411 request.url = GURL("http://www.google.com/");
6412 request.load_flags = 0;
6413
6414 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6415
6416 session_deps.socket_factory.AddSocketDataProvider(&data);
6417
6418 TestCompletionCallback callback;
6419
6420 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6421 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6422
[email protected]5a1d7ca2010-04-28 20:12:276423 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426424 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536425
[email protected]2fbaecf22010-07-22 22:20:356426 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426427 const HttpAlternateProtocols& alternate_protocols =
6428 session->alternate_protocols();
6429 EXPECT_FALSE(
6430 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6431
6432 EXPECT_EQ(OK, callback.WaitForResult());
6433
6434 const HttpResponseInfo* response = trans->GetResponseInfo();
6435 ASSERT_TRUE(response != NULL);
6436 ASSERT_TRUE(response->headers != NULL);
6437 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536438 EXPECT_FALSE(response->was_fetched_via_spdy);
6439 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576440 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:426441
6442 std::string response_data;
6443 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6444 EXPECT_EQ("hello world", response_data);
6445
6446 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6447 const HttpAlternateProtocols::PortProtocolPair alternate =
6448 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6449 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6450 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356451 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426452 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426453
[email protected]8e6441ca2010-08-19 05:56:386454 HttpStreamFactory::set_use_alternate_protocols(false);
6455 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426456}
6457
6458TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386459 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426460 SessionDependencies session_deps;
6461
6462 HttpRequestInfo request;
6463 request.method = "GET";
6464 request.url = GURL("http://www.google.com/");
6465 request.load_flags = 0;
6466
6467 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6468 StaticSocketDataProvider first_data;
6469 first_data.set_connect_data(mock_connect);
6470 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6471
6472 MockRead data_reads[] = {
6473 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6474 MockRead("hello world"),
6475 MockRead(true, OK),
6476 };
6477 StaticSocketDataProvider second_data(
6478 data_reads, arraysize(data_reads), NULL, 0);
6479 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6480
6481 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6482 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6483 // http://crbug.com/37454.
6484 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6485
6486 TestCompletionCallback callback;
6487
6488 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6489
[email protected]2fbaecf22010-07-22 22:20:356490 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426491 HttpAlternateProtocols* alternate_protocols =
6492 session->mutable_alternate_protocols();
6493 alternate_protocols->SetAlternateProtocolFor(
6494 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356495 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426496
6497 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6498
[email protected]5a1d7ca2010-04-28 20:12:276499 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426500 EXPECT_EQ(ERR_IO_PENDING, rv);
6501 EXPECT_EQ(OK, callback.WaitForResult());
6502
6503 const HttpResponseInfo* response = trans->GetResponseInfo();
6504 ASSERT_TRUE(response != NULL);
6505 ASSERT_TRUE(response->headers != NULL);
6506 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6507
6508 std::string response_data;
6509 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6510 EXPECT_EQ("hello world", response_data);
6511
6512 ASSERT_TRUE(
6513 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6514 const HttpAlternateProtocols::PortProtocolPair alternate =
6515 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6516 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386517 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426518}
6519
6520// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6521// says that it does SPDY, but it just does the TLS handshake, but the NPN
6522// response does not indicate SPDY, so we just do standard HTTPS over the port.
6523// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6524// on the original port.
[email protected]a2cb8122010-03-10 17:22:426525// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6526// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536527//
[email protected]a2cb8122010-03-10 17:22:426528// HttpRequestInfo request;
6529// request.method = "GET";
6530// request.url = GURL("http://www.google.com/");
6531// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536532//
[email protected]a2cb8122010-03-10 17:22:426533// MockRead data_reads[] = {
6534// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6535// MockRead("hello world"),
6536// MockRead(true, OK),
6537// };
6538// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6539// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536540//
[email protected]a2cb8122010-03-10 17:22:426541// SSLSocketDataProvider ssl(true, OK);
6542// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536543//
[email protected]a2cb8122010-03-10 17:22:426544// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536545//
[email protected]a2cb8122010-03-10 17:22:426546// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536547//
[email protected]a2cb8122010-03-10 17:22:426548// HostPortPair http_host_port_pair;
6549// http_host_port_pair.host = "www.google.com";
6550// http_host_port_pair.port = 80;
6551// HttpAlternateProtocols* alternate_protocols =
6552// session->mutable_alternate_protocols();
6553// alternate_protocols->SetAlternateProtocolFor(
6554// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066555// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536556//
[email protected]a2cb8122010-03-10 17:22:426557// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536558//
[email protected]5a1d7ca2010-04-28 20:12:276559// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426560// EXPECT_EQ(ERR_IO_PENDING, rv);
6561// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536562//
[email protected]a2cb8122010-03-10 17:22:426563// const HttpResponseInfo* response = trans->GetResponseInfo();
6564// ASSERT_TRUE(response != NULL);
6565// ASSERT_TRUE(response->headers != NULL);
6566// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536567//
[email protected]a2cb8122010-03-10 17:22:426568// std::string response_data;
6569// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6570// EXPECT_EQ("hello world", response_data);
6571// }
6572
6573TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386574 HttpStreamFactory::set_use_alternate_protocols(true);
6575 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426576 SessionDependencies session_deps;
6577
6578 HttpRequestInfo request;
6579 request.method = "GET";
6580 request.url = GURL("http://www.google.com/");
6581 request.load_flags = 0;
6582
[email protected]a2cb8122010-03-10 17:22:426583 StaticSocketDataProvider first_tcp_connect;
6584 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6585
6586 SSLSocketDataProvider ssl(true, OK);
6587 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6588
[email protected]564b4912010-03-09 16:30:426589 MockRead data_reads[] = {
6590 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6591 MockRead("hello world"),
6592 MockRead(true, OK),
6593 };
[email protected]a2cb8122010-03-10 17:22:426594 StaticSocketDataProvider fallback_data(
6595 data_reads, arraysize(data_reads), NULL, 0);
6596 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426597
6598 TestCompletionCallback callback;
6599
6600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6601
[email protected]2fbaecf22010-07-22 22:20:356602 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426603 HttpAlternateProtocols* alternate_protocols =
6604 session->mutable_alternate_protocols();
6605 alternate_protocols->SetAlternateProtocolFor(
6606 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356607 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426608
6609 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6610
[email protected]5a1d7ca2010-04-28 20:12:276611 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426612 EXPECT_EQ(ERR_IO_PENDING, rv);
6613 EXPECT_EQ(OK, callback.WaitForResult());
6614
6615 const HttpResponseInfo* response = trans->GetResponseInfo();
6616 ASSERT_TRUE(response != NULL);
6617 ASSERT_TRUE(response->headers != NULL);
6618 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6619
6620 std::string response_data;
6621 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6622 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386623 HttpStreamFactory::set_next_protos("");
6624 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546625}
6626
6627TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386628 HttpStreamFactory::set_use_alternate_protocols(true);
6629 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546630 SessionDependencies session_deps;
6631
6632 HttpRequestInfo request;
6633 request.method = "GET";
6634 request.url = GURL("http://www.google.com/");
6635 request.load_flags = 0;
6636
6637 MockRead data_reads[] = {
6638 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356639 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546640 MockRead("hello world"),
6641 MockRead(true, OK),
6642 };
6643
6644 StaticSocketDataProvider first_transaction(
6645 data_reads, arraysize(data_reads), NULL, 0);
6646 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6647
6648 SSLSocketDataProvider ssl(true, OK);
6649 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356650 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536651 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546652 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6653
[email protected]2bd93022010-07-17 00:58:446654 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136655 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546656
[email protected]2bd93022010-07-17 00:58:446657 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6658 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546659 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136660 CreateMockRead(*resp),
6661 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546662 MockRead(true, 0, 0),
6663 };
6664
6665 scoped_refptr<DelayedSocketData> spdy_data(
6666 new DelayedSocketData(
6667 1, // wait for one write to finish before reading.
6668 spdy_reads, arraysize(spdy_reads),
6669 spdy_writes, arraysize(spdy_writes)));
6670 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6671
6672 TestCompletionCallback callback;
6673
6674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6675 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6676
[email protected]5a1d7ca2010-04-28 20:12:276677 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546678 EXPECT_EQ(ERR_IO_PENDING, rv);
6679 EXPECT_EQ(OK, callback.WaitForResult());
6680
6681 const HttpResponseInfo* response = trans->GetResponseInfo();
6682 ASSERT_TRUE(response != NULL);
6683 ASSERT_TRUE(response->headers != NULL);
6684 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6685
6686 std::string response_data;
6687 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6688 EXPECT_EQ("hello world", response_data);
6689
6690 trans.reset(new HttpNetworkTransaction(session));
6691
[email protected]5a1d7ca2010-04-28 20:12:276692 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546693 EXPECT_EQ(ERR_IO_PENDING, rv);
6694 EXPECT_EQ(OK, callback.WaitForResult());
6695
6696 response = trans->GetResponseInfo();
6697 ASSERT_TRUE(response != NULL);
6698 ASSERT_TRUE(response->headers != NULL);
6699 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536700 EXPECT_TRUE(response->was_fetched_via_spdy);
6701 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576702 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546703
6704 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6705 EXPECT_EQ("hello!", response_data);
6706
[email protected]8e6441ca2010-08-19 05:56:386707 HttpStreamFactory::set_next_protos("");
6708 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546709}
6710
[email protected]631f1322010-04-30 17:59:116711class CapturingProxyResolver : public ProxyResolver {
6712 public:
6713 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6714 virtual ~CapturingProxyResolver() {}
6715
6716 virtual int GetProxyForURL(const GURL& url,
6717 ProxyInfo* results,
6718 CompletionCallback* callback,
6719 RequestHandle* request,
6720 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406721 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6722 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426723 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116724 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426725 return OK;
[email protected]631f1322010-04-30 17:59:116726 }
6727
6728 virtual void CancelRequest(RequestHandle request) {
6729 NOTREACHED();
6730 }
6731
[email protected]1e605472010-12-16 21:41:406732 virtual void CancelSetPacScript() {
6733 NOTREACHED();
6734 }
6735
[email protected]24476402010-07-20 20:55:176736 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116737 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426738 return OK;
[email protected]631f1322010-04-30 17:59:116739 }
6740
[email protected]24476402010-07-20 20:55:176741 const std::vector<GURL>& resolved() const { return resolved_; }
6742
6743 private:
[email protected]631f1322010-04-30 17:59:116744 std::vector<GURL> resolved_;
6745
6746 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6747};
6748
[email protected]631f1322010-04-30 17:59:116749TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386750 HttpStreamFactory::set_use_alternate_protocols(true);
6751 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116752
6753 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426754 proxy_config.set_auto_detect(true);
6755 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116756
[email protected]631f1322010-04-30 17:59:116757 CapturingProxyResolver* capturing_proxy_resolver =
6758 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386759 SessionDependencies session_deps(new ProxyService(
6760 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6761 NULL));
[email protected]631f1322010-04-30 17:59:116762
6763 HttpRequestInfo request;
6764 request.method = "GET";
6765 request.url = GURL("http://www.google.com/");
6766 request.load_flags = 0;
6767
6768 MockRead data_reads[] = {
6769 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356770 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116771 MockRead("hello world"),
6772 MockRead(true, OK),
6773 };
6774
6775 StaticSocketDataProvider first_transaction(
6776 data_reads, arraysize(data_reads), NULL, 0);
6777 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6778
6779 SSLSocketDataProvider ssl(true, OK);
6780 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356781 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536782 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116783 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6784
[email protected]2bd93022010-07-17 00:58:446785 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116786 MockWrite spdy_writes[] = {
6787 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6788 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426789 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136790 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116791 };
6792
[email protected]d911f1b2010-05-05 22:39:426793 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6794
[email protected]2bd93022010-07-17 00:58:446795 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6796 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116797 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426798 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136799 CreateMockRead(*resp.get(), 4), // 2, 4
6800 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426801 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116802 };
6803
[email protected]d911f1b2010-05-05 22:39:426804 scoped_refptr<OrderedSocketData> spdy_data(
6805 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116806 spdy_reads, arraysize(spdy_reads),
6807 spdy_writes, arraysize(spdy_writes)));
6808 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6809
6810 TestCompletionCallback callback;
6811
6812 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6813 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6814
6815 int rv = trans->Start(&request, &callback, BoundNetLog());
6816 EXPECT_EQ(ERR_IO_PENDING, rv);
6817 EXPECT_EQ(OK, callback.WaitForResult());
6818
6819 const HttpResponseInfo* response = trans->GetResponseInfo();
6820 ASSERT_TRUE(response != NULL);
6821 ASSERT_TRUE(response->headers != NULL);
6822 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536823 EXPECT_FALSE(response->was_fetched_via_spdy);
6824 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116825
6826 std::string response_data;
6827 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6828 EXPECT_EQ("hello world", response_data);
6829
6830 trans.reset(new HttpNetworkTransaction(session));
6831
6832 rv = trans->Start(&request, &callback, BoundNetLog());
6833 EXPECT_EQ(ERR_IO_PENDING, rv);
6834 EXPECT_EQ(OK, callback.WaitForResult());
6835
6836 response = trans->GetResponseInfo();
6837 ASSERT_TRUE(response != NULL);
6838 ASSERT_TRUE(response->headers != NULL);
6839 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536840 EXPECT_TRUE(response->was_fetched_via_spdy);
6841 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116842
6843 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6844 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426845 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6846 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116847 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426848 EXPECT_EQ("https://www.google.com/",
6849 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116850
[email protected]8e6441ca2010-08-19 05:56:386851 HttpStreamFactory::set_next_protos("");
6852 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116853}
[email protected]631f1322010-04-30 17:59:116854
[email protected]2ff8b312010-04-26 22:20:546855TEST_F(HttpNetworkTransactionTest,
6856 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386857 HttpStreamFactory::set_use_alternate_protocols(true);
6858 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546859 SessionDependencies session_deps;
6860
6861 HttpRequestInfo request;
6862 request.method = "GET";
6863 request.url = GURL("http://www.google.com/");
6864 request.load_flags = 0;
6865
6866 MockRead data_reads[] = {
6867 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356868 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546869 MockRead("hello world"),
6870 MockRead(true, OK),
6871 };
6872
6873 StaticSocketDataProvider first_transaction(
6874 data_reads, arraysize(data_reads), NULL, 0);
6875 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6876
6877 SSLSocketDataProvider ssl(true, OK);
6878 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356879 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536880 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546881 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536882 // Make sure we use ssl for spdy here.
6883 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546884
[email protected]2bd93022010-07-17 00:58:446885 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136886 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546887
[email protected]2bd93022010-07-17 00:58:446888 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6889 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546890 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136891 CreateMockRead(*resp),
6892 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546893 MockRead(true, 0, 0),
6894 };
6895
6896 scoped_refptr<DelayedSocketData> spdy_data(
6897 new DelayedSocketData(
6898 1, // wait for one write to finish before reading.
6899 spdy_reads, arraysize(spdy_reads),
6900 spdy_writes, arraysize(spdy_writes)));
6901 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6902
6903 TestCompletionCallback callback;
6904
6905 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6906
6907 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6908
[email protected]5a1d7ca2010-04-28 20:12:276909 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546910 EXPECT_EQ(ERR_IO_PENDING, rv);
6911 EXPECT_EQ(OK, callback.WaitForResult());
6912
6913 const HttpResponseInfo* response = trans->GetResponseInfo();
6914 ASSERT_TRUE(response != NULL);
6915 ASSERT_TRUE(response->headers != NULL);
6916 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6917
6918 std::string response_data;
6919 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6920 EXPECT_EQ("hello world", response_data);
6921
6922 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386923 HostPortPair host_port_pair("www.google.com", 443);
6924 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546925 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:316926 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276927 scoped_refptr<TCPSocketParams> tcp_params(
6928 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386929
6930 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6931 EXPECT_EQ(ERR_IO_PENDING,
6932 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6933 &callback, session->tcp_socket_pool(),
6934 BoundNetLog()));
6935 EXPECT_EQ(OK, callback.WaitForResult());
6936
6937 SSLConfig ssl_config;
6938 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:346939 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
6940 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
6941 connection.release(), HostPortPair("" , 443), ssl_config,
6942 NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL));
6943 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:386944 EXPECT_EQ(OK, callback.WaitForResult());
6945
[email protected]9e1bdd32011-02-03 21:48:346946 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:386947 true, OK));
6948
[email protected]2ff8b312010-04-26 22:20:546949 trans.reset(new HttpNetworkTransaction(session));
6950
[email protected]5a1d7ca2010-04-28 20:12:276951 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546952 EXPECT_EQ(ERR_IO_PENDING, rv);
6953 EXPECT_EQ(OK, callback.WaitForResult());
6954
6955 response = trans->GetResponseInfo();
6956 ASSERT_TRUE(response != NULL);
6957 ASSERT_TRUE(response->headers != NULL);
6958 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536959 EXPECT_TRUE(response->was_fetched_via_spdy);
6960 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576961 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546962
6963 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6964 EXPECT_EQ("hello!", response_data);
6965
[email protected]8e6441ca2010-08-19 05:56:386966 HttpStreamFactory::set_next_protos("");
6967 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426968}
6969
[email protected]044de0642010-06-17 10:42:156970// GenerateAuthToken is a mighty big test.
6971// It tests all permutation of GenerateAuthToken behavior:
6972// - Synchronous and Asynchronous completion.
6973// - OK or error on completion.
6974// - Direct connection, non-authenticating proxy, and authenticating proxy.
6975// - HTTP or HTTPS backend (to include proxy tunneling).
6976// - Non-authenticating and authenticating backend.
6977//
6978// In all, there are 44 reasonable permuations (for example, if there are
6979// problems generating an auth token for an authenticating proxy, we don't
6980// need to test all permutations of the backend server).
6981//
6982// The test proceeds by going over each of the configuration cases, and
6983// potentially running up to three rounds in each of the tests. The TestConfig
6984// specifies both the configuration for the test as well as the expectations
6985// for the results.
6986TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506987 static const char kServer[] = "http://www.example.com";
6988 static const char kSecureServer[] = "https://www.example.com";
6989 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156990 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6991
6992 enum AuthTiming {
6993 AUTH_NONE,
6994 AUTH_SYNC,
6995 AUTH_ASYNC,
6996 };
6997
6998 const MockWrite kGet(
6999 "GET / HTTP/1.1\r\n"
7000 "Host: www.example.com\r\n"
7001 "Connection: keep-alive\r\n\r\n");
7002 const MockWrite kGetProxy(
7003 "GET http://www.example.com/ HTTP/1.1\r\n"
7004 "Host: www.example.com\r\n"
7005 "Proxy-Connection: keep-alive\r\n\r\n");
7006 const MockWrite kGetAuth(
7007 "GET / HTTP/1.1\r\n"
7008 "Host: www.example.com\r\n"
7009 "Connection: keep-alive\r\n"
7010 "Authorization: auth_token\r\n\r\n");
7011 const MockWrite kGetProxyAuth(
7012 "GET http://www.example.com/ HTTP/1.1\r\n"
7013 "Host: www.example.com\r\n"
7014 "Proxy-Connection: keep-alive\r\n"
7015 "Proxy-Authorization: auth_token\r\n\r\n");
7016 const MockWrite kGetAuthThroughProxy(
7017 "GET http://www.example.com/ HTTP/1.1\r\n"
7018 "Host: www.example.com\r\n"
7019 "Proxy-Connection: keep-alive\r\n"
7020 "Authorization: auth_token\r\n\r\n");
7021 const MockWrite kGetAuthWithProxyAuth(
7022 "GET http://www.example.com/ HTTP/1.1\r\n"
7023 "Host: www.example.com\r\n"
7024 "Proxy-Connection: keep-alive\r\n"
7025 "Proxy-Authorization: auth_token\r\n"
7026 "Authorization: auth_token\r\n\r\n");
7027 const MockWrite kConnect(
7028 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7029 "Host: www.example.com\r\n"
7030 "Proxy-Connection: keep-alive\r\n\r\n");
7031 const MockWrite kConnectProxyAuth(
7032 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7033 "Host: www.example.com\r\n"
7034 "Proxy-Connection: keep-alive\r\n"
7035 "Proxy-Authorization: auth_token\r\n\r\n");
7036
7037 const MockRead kSuccess(
7038 "HTTP/1.1 200 OK\r\n"
7039 "Content-Type: text/html; charset=iso-8859-1\r\n"
7040 "Content-Length: 3\r\n\r\n"
7041 "Yes");
7042 const MockRead kFailure(
7043 "Should not be called.");
7044 const MockRead kServerChallenge(
7045 "HTTP/1.1 401 Unauthorized\r\n"
7046 "WWW-Authenticate: Mock realm=server\r\n"
7047 "Content-Type: text/html; charset=iso-8859-1\r\n"
7048 "Content-Length: 14\r\n\r\n"
7049 "Unauthorized\r\n");
7050 const MockRead kProxyChallenge(
7051 "HTTP/1.1 407 Unauthorized\r\n"
7052 "Proxy-Authenticate: Mock realm=proxy\r\n"
7053 "Proxy-Connection: close\r\n"
7054 "Content-Type: text/html; charset=iso-8859-1\r\n"
7055 "Content-Length: 14\r\n\r\n"
7056 "Unauthorized\r\n");
7057 const MockRead kProxyConnected(
7058 "HTTP/1.1 200 Connection Established\r\n\r\n");
7059
7060 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7061 // no constructors, but the C++ compiler on Windows warns about
7062 // unspecified data in compound literals. So, moved to using constructors,
7063 // and TestRound's created with the default constructor should not be used.
7064 struct TestRound {
7065 TestRound()
7066 : expected_rv(ERR_UNEXPECTED),
7067 extra_write(NULL),
7068 extra_read(NULL) {
7069 }
7070 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7071 int expected_rv_arg)
7072 : write(write_arg),
7073 read(read_arg),
7074 expected_rv(expected_rv_arg),
7075 extra_write(NULL),
7076 extra_read(NULL) {
7077 }
7078 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7079 int expected_rv_arg, const MockWrite* extra_write_arg,
7080 const MockWrite* extra_read_arg)
7081 : write(write_arg),
7082 read(read_arg),
7083 expected_rv(expected_rv_arg),
7084 extra_write(extra_write_arg),
7085 extra_read(extra_read_arg) {
7086 }
7087 MockWrite write;
7088 MockRead read;
7089 int expected_rv;
7090 const MockWrite* extra_write;
7091 const MockRead* extra_read;
7092 };
7093
7094 static const int kNoSSL = 500;
7095
7096 struct TestConfig {
7097 const char* proxy_url;
7098 AuthTiming proxy_auth_timing;
7099 int proxy_auth_rv;
7100 const char* server_url;
7101 AuthTiming server_auth_timing;
7102 int server_auth_rv;
7103 int num_auth_rounds;
7104 int first_ssl_round;
7105 TestRound rounds[3];
7106 } test_configs[] = {
7107 // Non-authenticating HTTP server with a direct connection.
7108 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7109 { TestRound(kGet, kSuccess, OK)}},
7110 // Authenticating HTTP server with a direct connection.
7111 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7112 { TestRound(kGet, kServerChallenge, OK),
7113 TestRound(kGetAuth, kSuccess, OK)}},
7114 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7115 { TestRound(kGet, kServerChallenge, OK),
7116 TestRound(kGetAuth, kFailure, kAuthErr)}},
7117 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7118 { TestRound(kGet, kServerChallenge, OK),
7119 TestRound(kGetAuth, kSuccess, OK)}},
7120 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7121 { TestRound(kGet, kServerChallenge, OK),
7122 TestRound(kGetAuth, kFailure, kAuthErr)}},
7123 // Non-authenticating HTTP server through a non-authenticating proxy.
7124 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7125 { TestRound(kGetProxy, kSuccess, OK)}},
7126 // Authenticating HTTP server through a non-authenticating proxy.
7127 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7128 { TestRound(kGetProxy, kServerChallenge, OK),
7129 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7130 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7131 { TestRound(kGetProxy, kServerChallenge, OK),
7132 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7133 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7134 { TestRound(kGetProxy, kServerChallenge, OK),
7135 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7136 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7137 { TestRound(kGetProxy, kServerChallenge, OK),
7138 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7139 // Non-authenticating HTTP server through an authenticating proxy.
7140 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7141 { TestRound(kGetProxy, kProxyChallenge, OK),
7142 TestRound(kGetProxyAuth, kSuccess, OK)}},
7143 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7144 { TestRound(kGetProxy, kProxyChallenge, OK),
7145 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7146 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7147 { TestRound(kGetProxy, kProxyChallenge, OK),
7148 TestRound(kGetProxyAuth, kSuccess, OK)}},
7149 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7150 { TestRound(kGetProxy, kProxyChallenge, OK),
7151 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7152 // Authenticating HTTP server through an authenticating proxy.
7153 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7154 { TestRound(kGetProxy, kProxyChallenge, OK),
7155 TestRound(kGetProxyAuth, kServerChallenge, OK),
7156 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7157 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7158 { TestRound(kGetProxy, kProxyChallenge, OK),
7159 TestRound(kGetProxyAuth, kServerChallenge, OK),
7160 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7161 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7162 { TestRound(kGetProxy, kProxyChallenge, OK),
7163 TestRound(kGetProxyAuth, kServerChallenge, OK),
7164 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7165 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7166 { TestRound(kGetProxy, kProxyChallenge, OK),
7167 TestRound(kGetProxyAuth, kServerChallenge, OK),
7168 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7169 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7170 { TestRound(kGetProxy, kProxyChallenge, OK),
7171 TestRound(kGetProxyAuth, kServerChallenge, OK),
7172 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7173 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7174 { TestRound(kGetProxy, kProxyChallenge, OK),
7175 TestRound(kGetProxyAuth, kServerChallenge, OK),
7176 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7177 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7178 { TestRound(kGetProxy, kProxyChallenge, OK),
7179 TestRound(kGetProxyAuth, kServerChallenge, OK),
7180 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7181 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7182 { TestRound(kGetProxy, kProxyChallenge, OK),
7183 TestRound(kGetProxyAuth, kServerChallenge, OK),
7184 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7185 // Non-authenticating HTTPS server with a direct connection.
7186 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7187 { TestRound(kGet, kSuccess, OK)}},
7188 // Authenticating HTTPS server with a direct connection.
7189 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7190 { TestRound(kGet, kServerChallenge, OK),
7191 TestRound(kGetAuth, kSuccess, OK)}},
7192 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7193 { TestRound(kGet, kServerChallenge, OK),
7194 TestRound(kGetAuth, kFailure, kAuthErr)}},
7195 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7196 { TestRound(kGet, kServerChallenge, OK),
7197 TestRound(kGetAuth, kSuccess, OK)}},
7198 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7199 { TestRound(kGet, kServerChallenge, OK),
7200 TestRound(kGetAuth, kFailure, kAuthErr)}},
7201 // Non-authenticating HTTPS server with a non-authenticating proxy.
7202 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7203 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7204 // Authenticating HTTPS server through a non-authenticating proxy.
7205 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7206 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7207 TestRound(kGetAuth, kSuccess, OK)}},
7208 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7209 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7210 TestRound(kGetAuth, kFailure, kAuthErr)}},
7211 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7212 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7213 TestRound(kGetAuth, kSuccess, OK)}},
7214 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7215 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7216 TestRound(kGetAuth, kFailure, kAuthErr)}},
7217 // Non-Authenticating HTTPS server through an authenticating proxy.
7218 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7219 { TestRound(kConnect, kProxyChallenge, OK),
7220 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7221 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7222 { TestRound(kConnect, kProxyChallenge, OK),
7223 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7224 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7225 { TestRound(kConnect, kProxyChallenge, OK),
7226 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7227 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7228 { TestRound(kConnect, kProxyChallenge, OK),
7229 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7230 // Authenticating HTTPS server through an authenticating proxy.
7231 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7232 { TestRound(kConnect, kProxyChallenge, OK),
7233 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7234 &kGet, &kServerChallenge),
7235 TestRound(kGetAuth, kSuccess, OK)}},
7236 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7237 { TestRound(kConnect, kProxyChallenge, OK),
7238 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7239 &kGet, &kServerChallenge),
7240 TestRound(kGetAuth, kFailure, kAuthErr)}},
7241 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7242 { TestRound(kConnect, kProxyChallenge, OK),
7243 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7244 &kGet, &kServerChallenge),
7245 TestRound(kGetAuth, kSuccess, OK)}},
7246 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7247 { TestRound(kConnect, kProxyChallenge, OK),
7248 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7249 &kGet, &kServerChallenge),
7250 TestRound(kGetAuth, kFailure, kAuthErr)}},
7251 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7252 { TestRound(kConnect, kProxyChallenge, OK),
7253 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7254 &kGet, &kServerChallenge),
7255 TestRound(kGetAuth, kSuccess, OK)}},
7256 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7257 { TestRound(kConnect, kProxyChallenge, OK),
7258 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7259 &kGet, &kServerChallenge),
7260 TestRound(kGetAuth, kFailure, kAuthErr)}},
7261 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7262 { TestRound(kConnect, kProxyChallenge, OK),
7263 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7264 &kGet, &kServerChallenge),
7265 TestRound(kGetAuth, kSuccess, OK)}},
7266 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7267 { TestRound(kConnect, kProxyChallenge, OK),
7268 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7269 &kGet, &kServerChallenge),
7270 TestRound(kGetAuth, kFailure, kAuthErr)}},
7271 };
7272
7273 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007274 HttpAuthHandlerMock::Factory* auth_factory(
7275 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157276 session_deps.http_auth_handler_factory.reset(auth_factory);
7277
7278 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7279 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267280
7281 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157282 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007283 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157284 std::string auth_challenge = "Mock realm=proxy";
7285 GURL origin(test_config.proxy_url);
7286 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7287 auth_challenge.end());
7288 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7289 origin, BoundNetLog());
7290 auth_handler->SetGenerateExpectation(
7291 test_config.proxy_auth_timing == AUTH_ASYNC,
7292 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157293 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7294 }
7295 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007296 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157297 std::string auth_challenge = "Mock realm=server";
7298 GURL origin(test_config.server_url);
7299 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7300 auth_challenge.end());
7301 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7302 origin, BoundNetLog());
7303 auth_handler->SetGenerateExpectation(
7304 test_config.server_auth_timing == AUTH_ASYNC,
7305 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157306 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7307 }
7308 if (test_config.proxy_url) {
7309 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:007310 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:157311 } else {
[email protected]ebeefff32010-09-15 05:10:027312 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:157313 }
7314
7315 HttpRequestInfo request;
7316 request.method = "GET";
7317 request.url = GURL(test_config.server_url);
7318 request.load_flags = 0;
7319
[email protected]0b0bf032010-09-21 18:08:507320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7321 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157322
7323 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7324 const TestRound& read_write_round = test_config.rounds[round];
7325
7326 // Set up expected reads and writes.
7327 MockRead reads[2];
7328 reads[0] = read_write_round.read;
7329 size_t length_reads = 1;
7330 if (read_write_round.extra_read) {
7331 reads[1] = *read_write_round.extra_read;
7332 length_reads = 2;
7333 }
7334
7335 MockWrite writes[2];
7336 writes[0] = read_write_round.write;
7337 size_t length_writes = 1;
7338 if (read_write_round.extra_write) {
7339 writes[1] = *read_write_round.extra_write;
7340 length_writes = 2;
7341 }
7342 StaticSocketDataProvider data_provider(
7343 reads, length_reads, writes, length_writes);
7344 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7345
7346 // Add an SSL sequence if necessary.
7347 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7348 if (round >= test_config.first_ssl_round)
7349 session_deps.socket_factory.AddSSLSocketDataProvider(
7350 &ssl_socket_data_provider);
7351
7352 // Start or restart the transaction.
7353 TestCompletionCallback callback;
7354 int rv;
7355 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507356 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157357 } else {
[email protected]0b0bf032010-09-21 18:08:507358 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157359 }
7360 if (rv == ERR_IO_PENDING)
7361 rv = callback.WaitForResult();
7362
7363 // Compare results with expected data.
7364 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507365 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157366 if (read_write_round.expected_rv == OK) {
7367 EXPECT_FALSE(response == NULL);
7368 } else {
7369 EXPECT_TRUE(response == NULL);
7370 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7371 continue;
7372 }
7373 if (round + 1 < test_config.num_auth_rounds) {
7374 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7375 } else {
7376 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7377 }
7378 }
[email protected]e5ae96a2010-04-14 20:12:457379 }
7380}
7381
[email protected]c871bce92010-07-15 21:51:147382TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7383 // Do multi-round authentication and make sure it works correctly.
7384 SessionDependencies session_deps;
7385 HttpAuthHandlerMock::Factory* auth_factory(
7386 new HttpAuthHandlerMock::Factory());
7387 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:027388 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:147389 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7390 session_deps.host_resolver->set_synchronous_mode(true);
7391
7392 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7393 auth_handler->set_connection_based(true);
7394 std::string auth_challenge = "Mock realm=server";
7395 GURL origin("http://www.example.com");
7396 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7397 auth_challenge.end());
7398 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7399 origin, BoundNetLog());
7400 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7401
[email protected]c871bce92010-07-15 21:51:147402 int rv = OK;
7403 const HttpResponseInfo* response = NULL;
7404 HttpRequestInfo request;
7405 request.method = "GET";
7406 request.url = origin;
7407 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277408
7409 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107410
7411 // Use a TCP Socket Pool with only one connection per group. This is used
7412 // to validate that the TCP socket is not released to the pool between
7413 // each round of multi-round authentication.
7414 HttpNetworkSessionPeer session_peer(session);
7415 ClientSocketPoolHistograms tcp_pool_histograms("SmallTCP");
7416 TCPClientSocketPool* tcp_pool = new TCPClientSocketPool(
7417 50, // Max sockets for pool
7418 1, // Max sockets per group
7419 &tcp_pool_histograms,
7420 session_deps.host_resolver.get(),
7421 &session_deps.socket_factory,
7422 session_deps.net_log);
7423 session_peer.SetTCPSocketPool(tcp_pool);
7424
[email protected]cb9bf6ca2011-01-28 13:15:277425 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147426 TestCompletionCallback callback;
7427
7428 const MockWrite kGet(
7429 "GET / HTTP/1.1\r\n"
7430 "Host: www.example.com\r\n"
7431 "Connection: keep-alive\r\n\r\n");
7432 const MockWrite kGetAuth(
7433 "GET / HTTP/1.1\r\n"
7434 "Host: www.example.com\r\n"
7435 "Connection: keep-alive\r\n"
7436 "Authorization: auth_token\r\n\r\n");
7437
7438 const MockRead kServerChallenge(
7439 "HTTP/1.1 401 Unauthorized\r\n"
7440 "WWW-Authenticate: Mock realm=server\r\n"
7441 "Content-Type: text/html; charset=iso-8859-1\r\n"
7442 "Content-Length: 14\r\n\r\n"
7443 "Unauthorized\r\n");
7444 const MockRead kSuccess(
7445 "HTTP/1.1 200 OK\r\n"
7446 "Content-Type: text/html; charset=iso-8859-1\r\n"
7447 "Content-Length: 3\r\n\r\n"
7448 "Yes");
7449
7450 MockWrite writes[] = {
7451 // First round
7452 kGet,
7453 // Second round
7454 kGetAuth,
7455 // Third round
7456 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307457 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107458 kGetAuth,
7459 // Competing request
7460 kGet,
[email protected]c871bce92010-07-15 21:51:147461 };
7462 MockRead reads[] = {
7463 // First round
7464 kServerChallenge,
7465 // Second round
7466 kServerChallenge,
7467 // Third round
[email protected]eca50e122010-09-11 14:03:307468 kServerChallenge,
7469 // Fourth round
[email protected]c871bce92010-07-15 21:51:147470 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107471 // Competing response
7472 kSuccess,
[email protected]c871bce92010-07-15 21:51:147473 };
7474 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7475 writes, arraysize(writes));
7476 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7477
[email protected]7ef4cbbb2011-02-06 11:19:107478 const char* const kSocketGroup = "www.example.com:80";
7479
7480 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147481 auth_handler->SetGenerateExpectation(false, OK);
7482 rv = trans->Start(&request, &callback, BoundNetLog());
7483 if (rv == ERR_IO_PENDING)
7484 rv = callback.WaitForResult();
7485 EXPECT_EQ(OK, rv);
7486 response = trans->GetResponseInfo();
7487 ASSERT_FALSE(response == NULL);
7488 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]7ef4cbbb2011-02-06 11:19:107489 EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147490
[email protected]7ef4cbbb2011-02-06 11:19:107491 // In between rounds, another request comes in for the same domain.
7492 // It should not be able to grab the TCP socket that trans has already
7493 // claimed.
7494 scoped_ptr<HttpTransaction> trans_compete(
7495 new HttpNetworkTransaction(session));
7496 TestCompletionCallback callback_compete;
7497 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7498 EXPECT_EQ(ERR_IO_PENDING, rv);
7499 // callback_compete.WaitForResult at this point would stall forever,
7500 // since the HttpNetworkTransaction does not release the request back to
7501 // the pool until after authentication completes.
7502
7503 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147504 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447505 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147506 if (rv == ERR_IO_PENDING)
7507 rv = callback.WaitForResult();
7508 EXPECT_EQ(OK, rv);
7509 response = trans->GetResponseInfo();
7510 ASSERT_FALSE(response == NULL);
7511 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]7ef4cbbb2011-02-06 11:19:107512 EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147513
[email protected]7ef4cbbb2011-02-06 11:19:107514 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147515 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447516 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147517 if (rv == ERR_IO_PENDING)
7518 rv = callback.WaitForResult();
7519 EXPECT_EQ(OK, rv);
7520 response = trans->GetResponseInfo();
7521 ASSERT_FALSE(response == NULL);
7522 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]7ef4cbbb2011-02-06 11:19:107523 EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307524
[email protected]7ef4cbbb2011-02-06 11:19:107525 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307526 auth_handler->SetGenerateExpectation(false, OK);
7527 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7528 if (rv == ERR_IO_PENDING)
7529 rv = callback.WaitForResult();
7530 EXPECT_EQ(OK, rv);
7531 response = trans->GetResponseInfo();
7532 ASSERT_FALSE(response == NULL);
7533 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]7ef4cbbb2011-02-06 11:19:107534 EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
7535
7536 // Read the body since the fourth round was successful. This will also
7537 // release the socket back to the pool.
7538 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7539 rv = trans->Read(io_buf, io_buf->size(), &callback);
7540 if (rv == ERR_IO_PENDING)
7541 rv = callback.WaitForResult();
7542 EXPECT_EQ(3, rv);
7543 rv = trans->Read(io_buf, io_buf->size(), &callback);
7544 EXPECT_EQ(0, rv);
7545 // There are still 0 idle sockets, since the trans_compete transaction
7546 // will be handed it immediately after trans releases it to the group.
7547 EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
7548
7549 // The competing request can now finish. Wait for the headers and then
7550 // read the body.
7551 rv = callback_compete.WaitForResult();
7552 EXPECT_EQ(OK, rv);
7553 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7554 if (rv == ERR_IO_PENDING)
7555 rv = callback.WaitForResult();
7556 EXPECT_EQ(3, rv);
7557 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7558 EXPECT_EQ(0, rv);
7559
7560 // Finally, the socket is released to the group.
7561 EXPECT_EQ(1, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147562}
7563
[email protected]aeaca1f2010-04-20 22:05:217564class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7565 public:
[email protected]06650c52010-06-03 00:49:177566 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217567 : fail_all_(fail_all) {
7568 }
7569
7570 virtual MockRead GetNextRead() {
7571 if (fail_all_)
7572 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7573
7574 return MockRead(false /* async */,
7575 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7576 }
7577
7578 virtual MockWriteResult OnWrite(const std::string& data) {
7579 return MockWriteResult(false /* async */, data.size());
7580 }
7581
7582 void Reset() {
7583 }
7584
7585 private:
7586 const bool fail_all_;
7587};
7588
7589// Test that we restart a connection when we see a decompression failure from
7590// the peer during the handshake. (In the real world we'll restart with SSLv3
7591// and we won't offer DEFLATE in that case.)
7592TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7593 HttpRequestInfo request;
7594 request.method = "GET";
7595 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7596 request.load_flags = 0;
7597
7598 SessionDependencies session_deps;
7599 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7600 false /* fail all reads */);
7601 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7602 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117603 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217604 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7605 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7606 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7607 session_deps.socket_factory.AddSSLSocketDataProvider(
7608 &ssl_socket_data_provider1);
7609 session_deps.socket_factory.AddSSLSocketDataProvider(
7610 &ssl_socket_data_provider2);
7611
[email protected]e60e47a2010-07-14 03:37:187612 // Work around http://crbug.com/37454
7613 StaticSocketDataProvider bug37454_connection;
7614 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7615 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7616
[email protected]aeaca1f2010-04-20 22:05:217617 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7618 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7619 TestCompletionCallback callback;
7620
[email protected]5a1d7ca2010-04-28 20:12:277621 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217622 EXPECT_EQ(ERR_IO_PENDING, rv);
7623 EXPECT_EQ(OK, callback.WaitForResult());
7624
7625 const HttpResponseInfo* response = trans->GetResponseInfo();
7626 ASSERT_TRUE(response != NULL);
7627 ASSERT_TRUE(response->headers != NULL);
7628 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7629
7630 std::string response_data;
7631 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7632 EXPECT_EQ("ok.", response_data);
7633}
7634
7635// Test that we restart a connection if we get a decompression failure from the
7636// peer while reading the first bytes from the connection. This occurs when the
7637// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7638// in the handshake.
7639TEST_F(HttpNetworkTransactionTest,
7640 RestartAfterTLSDecompressionFailureWithFalseStart) {
7641 HttpRequestInfo request;
7642 request.method = "GET";
7643 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7644 request.load_flags = 0;
7645
7646 SessionDependencies session_deps;
7647 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7648 true /* fail all reads */);
7649 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7650 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7651 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7652 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7653 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7654 session_deps.socket_factory.AddSSLSocketDataProvider(
7655 &ssl_socket_data_provider1);
7656 session_deps.socket_factory.AddSSLSocketDataProvider(
7657 &ssl_socket_data_provider2);
7658
7659 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7660 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7661 TestCompletionCallback callback;
7662
[email protected]5a1d7ca2010-04-28 20:12:277663 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217664 EXPECT_EQ(ERR_IO_PENDING, rv);
7665 EXPECT_EQ(OK, callback.WaitForResult());
7666
7667 const HttpResponseInfo* response = trans->GetResponseInfo();
7668 ASSERT_TRUE(response != NULL);
7669 ASSERT_TRUE(response->headers != NULL);
7670 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7671
7672 std::string response_data;
7673 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7674 EXPECT_EQ("ok.", response_data);
7675}
7676
[email protected]65041fa2010-05-21 06:56:537677// This tests the case that a request is issued via http instead of spdy after
7678// npn is negotiated.
7679TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387680 HttpStreamFactory::set_use_alternate_protocols(true);
7681 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537682 SessionDependencies session_deps;
7683 HttpRequestInfo request;
7684 request.method = "GET";
7685 request.url = GURL("https://www.google.com/");
7686 request.load_flags = 0;
7687
7688 MockWrite data_writes[] = {
7689 MockWrite("GET / HTTP/1.1\r\n"
7690 "Host: www.google.com\r\n"
7691 "Connection: keep-alive\r\n\r\n"),
7692 };
7693
7694 MockRead data_reads[] = {
7695 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357696 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537697 MockRead("hello world"),
7698 MockRead(false, OK),
7699 };
7700
7701 SSLSocketDataProvider ssl(true, OK);
7702 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7703 ssl.next_proto = "http/1.1";
7704
7705 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7706
7707 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7708 data_writes, arraysize(data_writes));
7709 session_deps.socket_factory.AddSocketDataProvider(&data);
7710
7711 TestCompletionCallback callback;
7712
7713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7715
7716 int rv = trans->Start(&request, &callback, BoundNetLog());
7717
7718 EXPECT_EQ(ERR_IO_PENDING, rv);
7719 EXPECT_EQ(OK, callback.WaitForResult());
7720
7721 const HttpResponseInfo* response = trans->GetResponseInfo();
7722 ASSERT_TRUE(response != NULL);
7723 ASSERT_TRUE(response->headers != NULL);
7724 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7725
7726 std::string response_data;
7727 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7728 EXPECT_EQ("hello world", response_data);
7729
7730 EXPECT_FALSE(response->was_fetched_via_spdy);
7731 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577732 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537733
[email protected]8e6441ca2010-08-19 05:56:387734 HttpStreamFactory::set_next_protos("");
7735 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537736}
[email protected]26ef6582010-06-24 02:30:477737
7738TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7739 // Simulate the SSL handshake completing with an NPN negotiation
7740 // followed by an immediate server closing of the socket.
7741 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387742 HttpStreamFactory::set_use_alternate_protocols(true);
7743 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477744 SessionDependencies session_deps;
7745
7746 HttpRequestInfo request;
7747 request.method = "GET";
7748 request.url = GURL("https://www.google.com/");
7749 request.load_flags = 0;
7750
7751 SSLSocketDataProvider ssl(true, OK);
7752 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357753 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477754 ssl.was_npn_negotiated = true;
7755 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7756
[email protected]2bd93022010-07-17 00:58:447757 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137758 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477759
7760 MockRead spdy_reads[] = {
7761 MockRead(false, 0, 0) // Not async - return 0 immediately.
7762 };
7763
7764 scoped_refptr<DelayedSocketData> spdy_data(
7765 new DelayedSocketData(
7766 0, // don't wait in this case, immediate hangup.
7767 spdy_reads, arraysize(spdy_reads),
7768 spdy_writes, arraysize(spdy_writes)));
7769 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7770
7771 TestCompletionCallback callback;
7772
7773 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7774 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7775
7776 int rv = trans->Start(&request, &callback, BoundNetLog());
7777 EXPECT_EQ(ERR_IO_PENDING, rv);
7778 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7779
[email protected]8e6441ca2010-08-19 05:56:387780 HttpStreamFactory::set_next_protos("");
7781 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477782}
[email protected]65d34382010-07-01 18:12:267783
[email protected]f45c1ee2010-08-03 00:54:307784TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7785 // This test ensures that the URL passed into the proxy is upgraded
7786 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387787 HttpStreamFactory::set_use_alternate_protocols(true);
7788 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307789 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7790
[email protected]81cdfcd2010-10-16 00:49:007791 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307792 HttpAuthHandlerMock::Factory* auth_factory =
7793 new HttpAuthHandlerMock::Factory();
7794 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7795 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7796 auth_factory->set_do_init_from_challenge(true);
7797 session_deps.http_auth_handler_factory.reset(auth_factory);
7798
7799 HttpRequestInfo request;
7800 request.method = "GET";
7801 request.url = GURL("http://www.google.com");
7802 request.load_flags = 0;
7803
7804 // First round goes unauthenticated through the proxy.
7805 MockWrite data_writes_1[] = {
7806 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7807 "Host: www.google.com\r\n"
7808 "Proxy-Connection: keep-alive\r\n"
7809 "\r\n"),
7810 };
7811 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597812 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307813 MockRead("HTTP/1.1 200 OK\r\n"
7814 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7815 "Proxy-Connection: close\r\n"
7816 "\r\n"),
7817 };
7818 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7819 data_writes_1, arraysize(data_writes_1));
7820
7821 // Second round tries to tunnel to www.google.com due to the
7822 // Alternate-Protocol announcement in the first round. It fails due
7823 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597824 // After the failure, a tunnel is established to www.google.com using
7825 // Proxy-Authorization headers. There is then a SPDY request round.
7826 //
7827 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7828 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7829 // does a Disconnect and Connect on the same socket, rather than trying
7830 // to obtain a new one.
7831 //
7832 // NOTE: Originally, the proxy response to the second CONNECT request
7833 // simply returned another 407 so the unit test could skip the SSL connection
7834 // establishment and SPDY framing issues. Alas, the
7835 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307836 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597837
[email protected]f45c1ee2010-08-03 00:54:307838 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7839 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7840 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7841
[email protected]394816e92010-08-03 07:38:597842 MockWrite data_writes_2[] = {
7843 // First connection attempt without Proxy-Authorization.
7844 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7845 "Host: www.google.com\r\n"
7846 "Proxy-Connection: keep-alive\r\n"
7847 "\r\n"),
7848
7849 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307850 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7851 "Host: www.google.com\r\n"
7852 "Proxy-Connection: keep-alive\r\n"
7853 "Proxy-Authorization: auth_token\r\n"
7854 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307855
[email protected]394816e92010-08-03 07:38:597856 // SPDY request
7857 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307858 };
[email protected]394816e92010-08-03 07:38:597859 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7860 "Proxy-Authenticate: Mock\r\n"
7861 "Proxy-Connection: close\r\n"
7862 "\r\n");
7863 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7864 MockRead data_reads_2[] = {
7865 // First connection attempt fails
7866 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7867 MockRead(true, kRejectConnectResponse,
7868 arraysize(kRejectConnectResponse) - 1, 1),
7869
7870 // Second connection attempt passes
7871 MockRead(true, kAcceptConnectResponse,
7872 arraysize(kAcceptConnectResponse) -1, 4),
7873
7874 // SPDY response
7875 CreateMockRead(*resp.get(), 6),
7876 CreateMockRead(*data.get(), 6),
7877 MockRead(true, 0, 0, 6),
7878 };
7879 scoped_refptr<OrderedSocketData> data_2(
7880 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7881 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307882
7883 SSLSocketDataProvider ssl(true, OK);
7884 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7885 ssl.next_proto = "spdy/2";
7886 ssl.was_npn_negotiated = true;
7887
7888 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597889 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307890 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7892
7893 // First round should work and provide the Alternate-Protocol state.
7894 TestCompletionCallback callback_1;
7895 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7896 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7897 EXPECT_EQ(ERR_IO_PENDING, rv);
7898 EXPECT_EQ(OK, callback_1.WaitForResult());
7899
7900 // Second round should attempt a tunnel connect and get an auth challenge.
7901 TestCompletionCallback callback_2;
7902 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7903 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7904 EXPECT_EQ(ERR_IO_PENDING, rv);
7905 EXPECT_EQ(OK, callback_2.WaitForResult());
7906 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7907 ASSERT_FALSE(response == NULL);
7908 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7909
7910 // Restart with auth. Tunnel should work and response received.
7911 TestCompletionCallback callback_3;
7912 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7913 EXPECT_EQ(ERR_IO_PENDING, rv);
7914 EXPECT_EQ(OK, callback_3.WaitForResult());
7915
7916 // After all that work, these two lines (or actually, just the scheme) are
7917 // what this test is all about. Make sure it happens correctly.
7918 const GURL& request_url = auth_handler->request_url();
7919 EXPECT_EQ("https", request_url.scheme());
7920 EXPECT_EQ("www.google.com", request_url.host());
7921
[email protected]8e6441ca2010-08-19 05:56:387922 HttpStreamFactory::set_next_protos("");
7923 HttpStreamFactory::set_use_alternate_protocols(false);
7924}
7925
7926// Test that if we cancel the transaction as the connection is completing, that
7927// everything tears down correctly.
7928TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7929 // Setup everything about the connection to complete synchronously, so that
7930 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7931 // for is the callback from the HttpStreamRequest.
7932 // Then cancel the transaction.
7933 // Verify that we don't crash.
7934 MockConnect mock_connect(false, OK);
7935 MockRead data_reads[] = {
7936 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7937 MockRead(false, "hello world"),
7938 MockRead(false, OK),
7939 };
7940
[email protected]8e6441ca2010-08-19 05:56:387941 HttpRequestInfo request;
7942 request.method = "GET";
7943 request.url = GURL("http://www.google.com/");
7944 request.load_flags = 0;
7945
[email protected]cb9bf6ca2011-01-28 13:15:277946 SessionDependencies session_deps;
7947 session_deps.host_resolver->set_synchronous_mode(true);
7948 scoped_ptr<HttpTransaction> trans(
7949 new HttpNetworkTransaction(CreateSession(&session_deps)));
7950
[email protected]8e6441ca2010-08-19 05:56:387951 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7952 data.set_connect_data(mock_connect);
7953 session_deps.socket_factory.AddSocketDataProvider(&data);
7954
7955 TestCompletionCallback callback;
7956
7957 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7958 int rv = trans->Start(&request, &callback, log.bound());
7959 EXPECT_EQ(ERR_IO_PENDING, rv);
7960 trans.reset(); // Cancel the transaction here.
7961
7962 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307963}
7964
[email protected]76a505b2010-08-25 06:23:007965// Test a basic GET request through a proxy.
7966TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007967 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007968 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7969 session_deps.net_log = log.bound().net_log();
7970 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7971
[email protected]76a505b2010-08-25 06:23:007972 HttpRequestInfo request;
7973 request.method = "GET";
7974 request.url = GURL("http://www.google.com/");
7975
7976 MockWrite data_writes1[] = {
7977 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7978 "Host: www.google.com\r\n"
7979 "Proxy-Connection: keep-alive\r\n\r\n"),
7980 };
7981
7982 MockRead data_reads1[] = {
7983 MockRead("HTTP/1.1 200 OK\r\n"),
7984 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7985 MockRead("Content-Length: 100\r\n\r\n"),
7986 MockRead(false, OK),
7987 };
7988
7989 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7990 data_writes1, arraysize(data_writes1));
7991 session_deps.socket_factory.AddSocketDataProvider(&data1);
7992
7993 TestCompletionCallback callback1;
7994
[email protected]0b0bf032010-09-21 18:08:507995 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7996
[email protected]76a505b2010-08-25 06:23:007997 int rv = trans->Start(&request, &callback1, log.bound());
7998 EXPECT_EQ(ERR_IO_PENDING, rv);
7999
8000 rv = callback1.WaitForResult();
8001 EXPECT_EQ(OK, rv);
8002
8003 const HttpResponseInfo* response = trans->GetResponseInfo();
8004 ASSERT_FALSE(response == NULL);
8005
8006 EXPECT_TRUE(response->headers->IsKeepAlive());
8007 EXPECT_EQ(200, response->headers->response_code());
8008 EXPECT_EQ(100, response->headers->GetContentLength());
8009 EXPECT_TRUE(response->was_fetched_via_proxy);
8010 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8011}
8012
8013// Test a basic HTTPS GET request through a proxy.
8014TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008015 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008016 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8017 session_deps.net_log = log.bound().net_log();
8018 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8019
[email protected]76a505b2010-08-25 06:23:008020 HttpRequestInfo request;
8021 request.method = "GET";
8022 request.url = GURL("https://www.google.com/");
8023
8024 // Since we have proxy, should try to establish tunnel.
8025 MockWrite data_writes1[] = {
8026 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8027 "Host: www.google.com\r\n"
8028 "Proxy-Connection: keep-alive\r\n\r\n"),
8029
8030 MockWrite("GET / HTTP/1.1\r\n"
8031 "Host: www.google.com\r\n"
8032 "Connection: keep-alive\r\n\r\n"),
8033 };
8034
8035 MockRead data_reads1[] = {
8036 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8037
8038 MockRead("HTTP/1.1 200 OK\r\n"),
8039 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8040 MockRead("Content-Length: 100\r\n\r\n"),
8041 MockRead(false, OK),
8042 };
8043
8044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8045 data_writes1, arraysize(data_writes1));
8046 session_deps.socket_factory.AddSocketDataProvider(&data1);
8047 SSLSocketDataProvider ssl(true, OK);
8048 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8049
8050 TestCompletionCallback callback1;
8051
[email protected]0b0bf032010-09-21 18:08:508052 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8053
[email protected]76a505b2010-08-25 06:23:008054 int rv = trans->Start(&request, &callback1, log.bound());
8055 EXPECT_EQ(ERR_IO_PENDING, rv);
8056
8057 rv = callback1.WaitForResult();
8058 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408059 net::CapturingNetLog::EntryList entries;
8060 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008061 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408062 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008063 NetLog::PHASE_NONE);
8064 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408065 entries, pos,
[email protected]76a505b2010-08-25 06:23:008066 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8067 NetLog::PHASE_NONE);
8068
8069 const HttpResponseInfo* response = trans->GetResponseInfo();
8070 ASSERT_FALSE(response == NULL);
8071
8072 EXPECT_TRUE(response->headers->IsKeepAlive());
8073 EXPECT_EQ(200, response->headers->response_code());
8074 EXPECT_EQ(100, response->headers->GetContentLength());
8075 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8076 EXPECT_TRUE(response->was_fetched_via_proxy);
8077}
8078
8079// Test a basic HTTPS GET request through a proxy, but the server hangs up
8080// while establishing the tunnel.
8081TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008082 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008083 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8084 session_deps.net_log = log.bound().net_log();
8085 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8086
[email protected]76a505b2010-08-25 06:23:008087 HttpRequestInfo request;
8088 request.method = "GET";
8089 request.url = GURL("https://www.google.com/");
8090
8091 // Since we have proxy, should try to establish tunnel.
8092 MockWrite data_writes1[] = {
8093 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8094 "Host: www.google.com\r\n"
8095 "Proxy-Connection: keep-alive\r\n\r\n"),
8096
8097 MockWrite("GET / HTTP/1.1\r\n"
8098 "Host: www.google.com\r\n"
8099 "Connection: keep-alive\r\n\r\n"),
8100 };
8101
8102 MockRead data_reads1[] = {
8103 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8104 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8105 MockRead(true, 0, 0), // EOF
8106 };
8107
8108 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8109 data_writes1, arraysize(data_writes1));
8110 session_deps.socket_factory.AddSocketDataProvider(&data1);
8111 SSLSocketDataProvider ssl(true, OK);
8112 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8113
8114 TestCompletionCallback callback1;
8115
[email protected]0b0bf032010-09-21 18:08:508116 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8117
[email protected]76a505b2010-08-25 06:23:008118 int rv = trans->Start(&request, &callback1, log.bound());
8119 EXPECT_EQ(ERR_IO_PENDING, rv);
8120
8121 rv = callback1.WaitForResult();
8122 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408123 net::CapturingNetLog::EntryList entries;
8124 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008125 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408126 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008127 NetLog::PHASE_NONE);
8128 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408129 entries, pos,
[email protected]76a505b2010-08-25 06:23:008130 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8131 NetLog::PHASE_NONE);
8132}
8133
[email protected]749eefa82010-09-13 22:14:038134// Test for crbug.com/55424.
8135TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8136 SessionDependencies session_deps;
8137
8138 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8139 "https://www.google.com", false, 1, LOWEST));
8140 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8141
8142 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8143 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8144 MockRead spdy_reads[] = {
8145 CreateMockRead(*resp),
8146 CreateMockRead(*data),
8147 MockRead(true, 0, 0),
8148 };
8149
8150 scoped_refptr<DelayedSocketData> spdy_data(
8151 new DelayedSocketData(
8152 1, // wait for one write to finish before reading.
8153 spdy_reads, arraysize(spdy_reads),
8154 spdy_writes, arraysize(spdy_writes)));
8155 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8156
8157 SSLSocketDataProvider ssl(true, OK);
8158 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8159 ssl.next_proto = "spdy/2";
8160 ssl.was_npn_negotiated = true;
8161 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8162
8163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8164
8165 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388166 HostPortPair host_port_pair("www.google.com", 443);
8167 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038168 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318169 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:278170 scoped_refptr<TCPSocketParams> tcp_params(
8171 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:388172 TestCompletionCallback callback;
8173
8174 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8175 EXPECT_EQ(ERR_IO_PENDING,
8176 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
8177 &callback, session->tcp_socket_pool(),
8178 BoundNetLog()));
8179 EXPECT_EQ(OK, callback.WaitForResult());
8180 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038181
8182 HttpRequestInfo request;
8183 request.method = "GET";
8184 request.url = GURL("https://www.google.com/");
8185 request.load_flags = 0;
8186
8187 // This is the important line that marks this as a preconnect.
8188 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8189
8190 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8191
[email protected]749eefa82010-09-13 22:14:038192 int rv = trans->Start(&request, &callback, BoundNetLog());
8193 EXPECT_EQ(ERR_IO_PENDING, rv);
8194 EXPECT_EQ(OK, callback.WaitForResult());
8195}
8196
[email protected]73b8dd222010-11-11 19:55:248197// Given a net error, cause that error to be returned from the first Write()
8198// call and verify that the HttpTransaction fails with that error.
8199static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278200 net::HttpRequestInfo request_info;
8201 request_info.url = GURL("https://www.example.com/");
8202 request_info.method = "GET";
8203 request_info.load_flags = net::LOAD_NORMAL;
8204
[email protected]73b8dd222010-11-11 19:55:248205 SessionDependencies session_deps;
8206
8207 SSLSocketDataProvider ssl_data(async, OK);
8208 net::MockWrite data_writes[] = {
8209 net::MockWrite(async, error),
8210 };
8211 net::StaticSocketDataProvider data(NULL, 0,
8212 data_writes, arraysize(data_writes));
8213 session_deps.socket_factory.AddSocketDataProvider(&data);
8214 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8215
8216 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8217 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8218
[email protected]73b8dd222010-11-11 19:55:248219 TestCompletionCallback callback;
8220 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8221 if (rv == net::ERR_IO_PENDING)
8222 rv = callback.WaitForResult();
8223 ASSERT_EQ(error, rv);
8224}
8225
8226TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8227 // Just check a grab bag of cert errors.
8228 static const int kErrors[] = {
8229 ERR_CERT_COMMON_NAME_INVALID,
8230 ERR_CERT_AUTHORITY_INVALID,
8231 ERR_CERT_DATE_INVALID,
8232 };
8233 for (size_t i = 0; i < arraysize(kErrors); i++) {
8234 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8235 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8236 }
8237}
8238
8239// Test that the transaction is restarted in the event of an NPN misprediction.
8240TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
[email protected]cb9bf6ca2011-01-28 13:15:278241 net::HttpRequestInfo request_info;
8242 request_info.url = GURL("https://www.example.com/");
8243 request_info.method = "GET";
8244 request_info.load_flags = net::LOAD_NORMAL;
8245
[email protected]73b8dd222010-11-11 19:55:248246 SessionDependencies session_deps;
8247
8248 SSLSocketDataProvider ssl_data1(true /* async */, OK);
8249 SSLSocketDataProvider ssl_data2(true /* async */, OK);
8250
8251 net::MockWrite data1_writes[] = {
8252 net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION),
8253 };
8254 net::MockRead data2_reads[] = {
8255 net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8256 net::MockRead("hello world"),
8257 net::MockRead(false, net::OK),
8258 };
8259 net::MockWrite data2_writes[] = {
8260 net::MockWrite("GET / HTTP/1.1\r\n"
8261 "Host: www.example.com\r\n"
8262 "Connection: keep-alive\r\n\r\n"),
8263 };
8264 net::StaticSocketDataProvider data1(
8265 NULL, 0, data1_writes, arraysize(data1_writes));
8266 net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads),
8267 data2_writes, arraysize(data2_writes));
8268
8269 session_deps.socket_factory.AddSocketDataProvider(&data1);
8270 session_deps.socket_factory.AddSocketDataProvider(&data2);
8271 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8272 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8273
8274 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8275 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8276
[email protected]73b8dd222010-11-11 19:55:248277 TestCompletionCallback callback;
8278 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8279 if (rv == net::ERR_IO_PENDING)
8280 rv = callback.WaitForResult();
8281 ASSERT_EQ(OK, rv);
8282
8283 std::string contents;
8284 rv = ReadTransaction(trans.get(), &contents);
8285 EXPECT_EQ(net::OK, rv);
8286 EXPECT_EQ("hello world", contents);
8287}
8288
[email protected]bd0b6772011-01-11 19:59:308289// Ensure that a client certificate is removed from the SSL client auth
8290// cache when:
8291// 1) No proxy is involved.
8292// 2) TLS False Start is disabled.
8293// 3) The initial TLS handshake requests a client certificate.
8294// 4) The client supplies an invalid/unacceptable certificate.
8295TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278296 net::HttpRequestInfo request_info;
8297 request_info.url = GURL("https://www.example.com/");
8298 request_info.method = "GET";
8299 request_info.load_flags = net::LOAD_NORMAL;
8300
[email protected]bd0b6772011-01-11 19:59:308301 SessionDependencies session_deps;
8302
8303 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8304 cert_request->host_and_port = "www.example.com:443";
8305
8306 // [ssl_]data1 contains the data for the first SSL handshake. When a
8307 // CertificateRequest is received for the first time, the handshake will
8308 // be aborted to allow the caller to provide a certificate.
8309 SSLSocketDataProvider ssl_data1(true /* async */,
8310 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8311 ssl_data1.cert_request_info = cert_request.get();
8312 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8313 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8314 session_deps.socket_factory.AddSocketDataProvider(&data1);
8315
8316 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8317 // False Start is not being used, the result of the SSL handshake will be
8318 // returned as part of the SSLClientSocket::Connect() call. This test
8319 // matches the result of a server sending a handshake_failure alert,
8320 // rather than a Finished message, because it requires a client
8321 // certificate and none was supplied.
8322 SSLSocketDataProvider ssl_data2(true /* async */,
8323 net::ERR_SSL_PROTOCOL_ERROR);
8324 ssl_data2.cert_request_info = cert_request.get();
8325 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8326 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8327 session_deps.socket_factory.AddSocketDataProvider(&data2);
8328
8329 // [ssl_]data3 contains the data for the third SSL handshake. When a
8330 // connection to a server fails during an SSL handshake,
8331 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8332 // connection was attempted with TLSv1. This is transparent to the caller
8333 // of the HttpNetworkTransaction. Because this test failure is due to
8334 // requiring a client certificate, this fallback handshake should also
8335 // fail.
8336 SSLSocketDataProvider ssl_data3(true /* async */,
8337 net::ERR_SSL_PROTOCOL_ERROR);
8338 ssl_data3.cert_request_info = cert_request.get();
8339 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8340 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8341 session_deps.socket_factory.AddSocketDataProvider(&data3);
8342
8343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8344 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8345
[email protected]bd0b6772011-01-11 19:59:308346 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8347 TestCompletionCallback callback;
8348 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8349 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8350
8351 // Complete the SSL handshake, which should abort due to requiring a
8352 // client certificate.
8353 rv = callback.WaitForResult();
8354 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8355
8356 // Indicate that no certificate should be supplied. From the perspective
8357 // of SSLClientCertCache, NULL is just as meaningful as a real
8358 // certificate, so this is the same as supply a
8359 // legitimate-but-unacceptable certificate.
8360 rv = trans->RestartWithCertificate(NULL, &callback);
8361 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8362
8363 // Ensure the certificate was added to the client auth cache before
8364 // allowing the connection to continue restarting.
8365 scoped_refptr<X509Certificate> client_cert;
8366 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8367 &client_cert));
8368 ASSERT_EQ(NULL, client_cert.get());
8369
8370 // Restart the handshake. This will consume ssl_data2, which fails, and
8371 // then consume ssl_data3, which should also fail. The result code is
8372 // checked against what ssl_data3 should return.
8373 rv = callback.WaitForResult();
8374 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8375
8376 // Ensure that the client certificate is removed from the cache on a
8377 // handshake failure.
8378 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8379 &client_cert));
8380}
8381
8382// Ensure that a client certificate is removed from the SSL client auth
8383// cache when:
8384// 1) No proxy is involved.
8385// 2) TLS False Start is enabled.
8386// 3) The initial TLS handshake requests a client certificate.
8387// 4) The client supplies an invalid/unacceptable certificate.
8388TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278389 net::HttpRequestInfo request_info;
8390 request_info.url = GURL("https://www.example.com/");
8391 request_info.method = "GET";
8392 request_info.load_flags = net::LOAD_NORMAL;
8393
[email protected]bd0b6772011-01-11 19:59:308394 SessionDependencies session_deps;
8395
8396 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8397 cert_request->host_and_port = "www.example.com:443";
8398
8399 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8400 // return successfully after reading up to the peer's Certificate message.
8401 // This is to allow the caller to call SSLClientSocket::Write(), which can
8402 // enqueue application data to be sent in the same packet as the
8403 // ChangeCipherSpec and Finished messages.
8404 // The actual handshake will be finished when SSLClientSocket::Read() is
8405 // called, which expects to process the peer's ChangeCipherSpec and
8406 // Finished messages. If there was an error negotiating with the peer,
8407 // such as due to the peer requiring a client certificate when none was
8408 // supplied, the alert sent by the peer won't be processed until Read() is
8409 // called.
8410
8411 // Like the non-False Start case, when a client certificate is requested by
8412 // the peer, the handshake is aborted during the Connect() call.
8413 // [ssl_]data1 represents the initial SSL handshake with the peer.
8414 SSLSocketDataProvider ssl_data1(true /* async */,
8415 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8416 ssl_data1.cert_request_info = cert_request.get();
8417 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8418 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8419 session_deps.socket_factory.AddSocketDataProvider(&data1);
8420
8421 // When a client certificate is supplied, Connect() will not be aborted
8422 // when the peer requests the certificate. Instead, the handshake will
8423 // artificially succeed, allowing the caller to write the HTTP request to
8424 // the socket. The handshake messages are not processed until Read() is
8425 // called, which then detects that the handshake was aborted, due to the
8426 // peer sending a handshake_failure because it requires a client
8427 // certificate.
8428 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8429 ssl_data2.cert_request_info = cert_request.get();
8430 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8431 net::MockRead data2_reads[] = {
8432 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8433 };
8434 net::StaticSocketDataProvider data2(
8435 data2_reads, arraysize(data2_reads), NULL, 0);
8436 session_deps.socket_factory.AddSocketDataProvider(&data2);
8437
8438 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8439 // the data for the SSL handshake once the TLSv1 connection falls back to
8440 // SSLv3. It has the same behaviour as [ssl_]data2.
8441 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8442 ssl_data3.cert_request_info = cert_request.get();
8443 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8444 net::StaticSocketDataProvider data3(
8445 data2_reads, arraysize(data2_reads), NULL, 0);
8446 session_deps.socket_factory.AddSocketDataProvider(&data3);
8447
8448 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8449 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8450
[email protected]bd0b6772011-01-11 19:59:308451 // Begin the initial SSL handshake.
8452 TestCompletionCallback callback;
8453 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8454 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8455
8456 // Complete the SSL handshake, which should abort due to requiring a
8457 // client certificate.
8458 rv = callback.WaitForResult();
8459 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8460
8461 // Indicate that no certificate should be supplied. From the perspective
8462 // of SSLClientCertCache, NULL is just as meaningful as a real
8463 // certificate, so this is the same as supply a
8464 // legitimate-but-unacceptable certificate.
8465 rv = trans->RestartWithCertificate(NULL, &callback);
8466 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8467
8468 // Ensure the certificate was added to the client auth cache before
8469 // allowing the connection to continue restarting.
8470 scoped_refptr<X509Certificate> client_cert;
8471 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8472 &client_cert));
8473 ASSERT_EQ(NULL, client_cert.get());
8474
8475
8476 // Restart the handshake. This will consume ssl_data2, which fails, and
8477 // then consume ssl_data3, which should also fail. The result code is
8478 // checked against what ssl_data3 should return.
8479 rv = callback.WaitForResult();
8480 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8481
8482 // Ensure that the client certificate is removed from the cache on a
8483 // handshake failure.
8484 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8485 &client_cert));
8486}
8487
[email protected]8c405132011-01-11 22:03:188488// Ensure that a client certificate is removed from the SSL client auth
8489// cache when:
8490// 1) An HTTPS proxy is involved.
8491// 3) The HTTPS proxy requests a client certificate.
8492// 4) The client supplies an invalid/unacceptable certificate for the
8493// proxy.
8494// The test is repeated twice, first for connecting to an HTTPS endpoint,
8495// then for connecting to an HTTP endpoint.
8496TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8497 SessionDependencies session_deps(
8498 ProxyService::CreateFixed("https://proxy:70"));
8499 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8500 session_deps.net_log = log.bound().net_log();
8501
8502 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8503 cert_request->host_and_port = "proxy:70";
8504
8505 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8506 // [ssl_]data[1-3]. Rather than represending the endpoint
8507 // (www.example.com:443), they represent failures with the HTTPS proxy
8508 // (proxy:70).
8509 SSLSocketDataProvider ssl_data1(true /* async */,
8510 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8511 ssl_data1.cert_request_info = cert_request.get();
8512 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8513 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8514 session_deps.socket_factory.AddSocketDataProvider(&data1);
8515
8516 SSLSocketDataProvider ssl_data2(true /* async */,
8517 net::ERR_SSL_PROTOCOL_ERROR);
8518 ssl_data2.cert_request_info = cert_request.get();
8519 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8520 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8521 session_deps.socket_factory.AddSocketDataProvider(&data2);
8522
8523 SSLSocketDataProvider ssl_data3(true /* async */,
8524 net::ERR_SSL_PROTOCOL_ERROR);
8525 ssl_data3.cert_request_info = cert_request.get();
8526 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8527 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8528 session_deps.socket_factory.AddSocketDataProvider(&data3);
8529
8530 net::HttpRequestInfo requests[2];
8531 requests[0].url = GURL("https://www.example.com/");
8532 requests[0].method = "GET";
8533 requests[0].load_flags = net::LOAD_NORMAL;
8534
8535 requests[1].url = GURL("http://www.example.com/");
8536 requests[1].method = "GET";
8537 requests[1].load_flags = net::LOAD_NORMAL;
8538
8539 for (size_t i = 0; i < arraysize(requests); ++i) {
8540 session_deps.socket_factory.ResetNextMockIndexes();
8541 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8542 scoped_ptr<HttpNetworkTransaction> trans(
8543 new HttpNetworkTransaction(session));
8544
8545 // Begin the SSL handshake with the proxy.
8546 TestCompletionCallback callback;
8547 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8548 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8549
8550 // Complete the SSL handshake, which should abort due to requiring a
8551 // client certificate.
8552 rv = callback.WaitForResult();
8553 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8554
8555 // Indicate that no certificate should be supplied. From the perspective
8556 // of SSLClientCertCache, NULL is just as meaningful as a real
8557 // certificate, so this is the same as supply a
8558 // legitimate-but-unacceptable certificate.
8559 rv = trans->RestartWithCertificate(NULL, &callback);
8560 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8561
8562 // Ensure the certificate was added to the client auth cache before
8563 // allowing the connection to continue restarting.
8564 scoped_refptr<X509Certificate> client_cert;
8565 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8566 &client_cert));
8567 ASSERT_EQ(NULL, client_cert.get());
8568 // Ensure the certificate was NOT cached for the endpoint. This only
8569 // applies to HTTPS requests, but is fine to check for HTTP requests.
8570 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8571 &client_cert));
8572
8573 // Restart the handshake. This will consume ssl_data2, which fails, and
8574 // then consume ssl_data3, which should also fail. The result code is
8575 // checked against what ssl_data3 should return.
8576 rv = callback.WaitForResult();
8577 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8578
8579 // Now that the new handshake has failed, ensure that the client
8580 // certificate was removed from the client auth cache.
8581 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8582 &client_cert));
8583 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8584 &client_cert));
8585 }
8586}
8587
[email protected]89ceba9a2009-03-21 03:46:068588} // namespace net