blob: 333bc5184138e29c9f3a2dba6e91dd06dbb19975 [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]73c45322010-10-01 23:57:54105 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]822581d2010-12-16 17:27:15106 session_deps->cert_verifier.get(),
[email protected]2db580532010-10-08 14:32:37107 NULL /* dnsrr_resolver */,
[email protected]345c613b2010-11-22 19:33:18108 NULL /* dns_cert_checker */,
[email protected]7ab5bbd12010-10-19 13:33:21109 NULL /* ssl_host_info_factory */,
[email protected]80d6524d2009-08-18 03:58:09110 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42111 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10112 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56113 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17114 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44115 NULL,
[email protected]a7ea8832010-07-12 17:54:54116 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14117}
118
[email protected]89836e22008-09-25 20:33:42119class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52120 public:
[email protected]2ff8b312010-04-26 22:20:54121 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50122 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
123 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54124 spdy::SpdyFramer::set_enable_compression_default(false);
125 }
126
[email protected]0e75a732008-10-16 20:36:09127 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50128 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
129 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54130 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09131 // Empty the current queue.
132 MessageLoop::current()->RunAllPending();
133 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50134 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
135 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09136 }
137
[email protected]3d2a59b2008-09-26 19:44:25138 protected:
139 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52140
[email protected]ff007e162009-05-23 09:13:15141 struct SimpleGetHelperResult {
142 int rv;
143 std::string status_line;
144 std::string response_data;
145 };
initial.commit586acc5fe2008-07-26 22:42:52146
[email protected]31a2bfe2010-02-09 08:03:39147 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
148 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15149 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]ff007e162009-05-23 09:13:15151 HttpRequestInfo request;
152 request.method = "GET";
153 request.url = GURL("http://www.google.com/");
154 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]cb9bf6ca2011-01-28 13:15:27156 SessionDependencies session_deps;
157 scoped_ptr<HttpTransaction> trans(
158 new HttpNetworkTransaction(CreateSession(&session_deps)));
159
[email protected]31a2bfe2010-02-09 08:03:39160 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59161 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52162
[email protected]ff007e162009-05-23 09:13:15163 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52164
[email protected]169d0012010-05-10 23:20:12165 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40166 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12167 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15168 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52169
[email protected]ff007e162009-05-23 09:13:15170 out.rv = callback.WaitForResult();
171 if (out.rv != OK)
172 return out;
173
174 const HttpResponseInfo* response = trans->GetResponseInfo();
175 EXPECT_TRUE(response != NULL);
176
177 EXPECT_TRUE(response->headers != NULL);
178 out.status_line = response->headers->GetStatusLine();
179
180 rv = ReadTransaction(trans.get(), &out.response_data);
181 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40182
183 net::CapturingNetLog::EntryList entries;
184 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39185 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40186 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12187 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39188 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40189 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39190 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
191 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15192
[email protected]b2fcd0e2010-12-01 15:19:40193 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40194 NetLogHttpRequestParameter* request_params =
195 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
196 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
197 EXPECT_EQ("Host: www.google.com\r\n"
198 "Connection: keep-alive\r\n\r\n",
199 request_params->GetHeaders().ToString());
200
[email protected]aecfbf22008-10-16 02:02:47201 return out;
[email protected]ff007e162009-05-23 09:13:15202 }
initial.commit586acc5fe2008-07-26 22:42:52203
[email protected]ff007e162009-05-23 09:13:15204 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
205 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52206
[email protected]ff007e162009-05-23 09:13:15207 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15208};
[email protected]231d5a32008-09-13 00:45:27209
[email protected]15a5ccf82008-10-23 19:57:43210// Fill |str| with a long header list that consumes >= |size| bytes.
211void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19212 const char* row =
213 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
214 const int sizeof_row = strlen(row);
215 const int num_rows = static_cast<int>(
216 ceil(static_cast<float>(size) / sizeof_row));
217 const int sizeof_data = num_rows * sizeof_row;
218 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43219 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51220
[email protected]4ddaf2502008-10-23 18:26:19221 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43222 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19223}
224
[email protected]385a4672009-03-11 22:21:29225// Alternative functions that eliminate randomness and dependency on the local
226// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20227void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29228 static const uint8 bytes[] = {
229 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
230 };
231 static size_t current_byte = 0;
232 for (size_t i = 0; i < n; ++i) {
233 output[i] = bytes[current_byte++];
234 current_byte %= arraysize(bytes);
235 }
236}
237
[email protected]fe2bc6a2009-03-23 16:52:20238void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29239 static const uint8 bytes[] = {
240 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
241 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
242 };
243 static size_t current_byte = 0;
244 for (size_t i = 0; i < n; ++i) {
245 output[i] = bytes[current_byte++];
246 current_byte %= arraysize(bytes);
247 }
248}
249
[email protected]fe2bc6a2009-03-23 16:52:20250std::string MockGetHostName() {
251 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29252}
253
[email protected]e60e47a2010-07-14 03:37:18254template<typename ParentPool>
255class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31256 public:
[email protected]e60e47a2010-07-14 03:37:18257 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
258
[email protected]d80a4322009-08-14 07:07:49259 const std::string last_group_name_received() const {
260 return last_group_name_;
261 }
262
[email protected]684970b2009-08-14 04:54:46263 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49264 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31265 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31266 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46267 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53268 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31269 last_group_name_ = group_name;
270 return ERR_IO_PENDING;
271 }
[email protected]04e5be32009-06-26 20:00:31272 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21273 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31274 virtual void ReleaseSocket(const std::string& group_name,
275 ClientSocket* socket) {}
276 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31277 virtual int IdleSocketCount() const {
278 return 0;
279 }
280 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
281 return 0;
282 }
283 virtual LoadState GetLoadState(const std::string& group_name,
284 const ClientSocketHandle* handle) const {
285 return LOAD_STATE_IDLE;
286 }
[email protected]a796bcec2010-03-22 17:17:26287 virtual base::TimeDelta ConnectionTimeout() const {
288 return base::TimeDelta();
289 }
[email protected]d80a4322009-08-14 07:07:49290
291 private:
[email protected]04e5be32009-06-26 20:00:31292 std::string last_group_name_;
293};
294
[email protected]2d731a32010-04-29 01:04:06295typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11296CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13297typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
298CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06299typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11300CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18301typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
302CaptureGroupNameSSLSocketPool;
303
304template<typename ParentPool>
305CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
306 HttpNetworkSession* session)
307 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
308
309template<>
[email protected]2df19bb2010-08-25 20:13:46310CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
311 HttpNetworkSession* session)
312 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
313 NULL, NULL) {}
314
315template<>
[email protected]e60e47a2010-07-14 03:37:18316CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
317 HttpNetworkSession* session)
[email protected]822581d2010-12-16 17:27:15318 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
319 session->cert_verifier(), NULL, NULL,
[email protected]345c613b2010-11-22 19:33:18320 NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11321
[email protected]231d5a32008-09-13 00:45:27322//-----------------------------------------------------------------------------
323
[email protected]dae22c52010-07-30 02:16:35324// This is the expected list of advertised protocols from the browser's NPN
325// list.
326static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
327
328// This is the expected return from a current server advertising SPDY.
329static const char kAlternateProtocolHttpHeader[] =
330 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
331
[email protected]231d5a32008-09-13 00:45:27332TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59333 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40334 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43335 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27336}
337
338TEST_F(HttpNetworkTransactionTest, SimpleGET) {
339 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35340 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
341 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42342 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27343 };
[email protected]31a2bfe2010-02-09 08:03:39344 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
345 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42346 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27347 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
348 EXPECT_EQ("hello world", out.response_data);
349}
350
351// Response with no status line.
352TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
353 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35354 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42355 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27356 };
[email protected]31a2bfe2010-02-09 08:03:39357 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
358 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42359 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27360 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
361 EXPECT_EQ("hello world", out.response_data);
362}
363
364// Allow up to 4 bytes of junk to precede status line.
365TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
366 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35367 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42368 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27369 };
[email protected]31a2bfe2010-02-09 08:03:39370 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
371 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42372 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27373 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
374 EXPECT_EQ("DATA", out.response_data);
375}
376
377// Allow up to 4 bytes of junk to precede status line.
378TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
379 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35380 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42381 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27382 };
[email protected]31a2bfe2010-02-09 08:03:39383 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
384 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42385 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27386 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
387 EXPECT_EQ("DATA", out.response_data);
388}
389
390// Beyond 4 bytes of slop and it should fail to find a status line.
391TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
392 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35393 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42394 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27395 };
[email protected]31a2bfe2010-02-09 08:03:39396 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
397 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42398 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25399 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
400 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27401}
402
403// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
404TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
405 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35406 MockRead("\n"),
407 MockRead("\n"),
408 MockRead("Q"),
409 MockRead("J"),
410 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42411 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27412 };
[email protected]31a2bfe2010-02-09 08:03:39413 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
414 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42415 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27416 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
417 EXPECT_EQ("DATA", out.response_data);
418}
419
420// Close the connection before enough bytes to have a status line.
421TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
422 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35423 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42424 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27425 };
[email protected]31a2bfe2010-02-09 08:03:39426 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
427 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42428 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27429 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
430 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52431}
432
[email protected]f9d44aa2008-09-23 23:57:17433// Simulate a 204 response, lacking a Content-Length header, sent over a
434// persistent connection. The response should still terminate since a 204
435// cannot have a response body.
436TEST_F(HttpNetworkTransactionTest, StopsReading204) {
437 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35438 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
439 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42440 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17441 };
[email protected]31a2bfe2010-02-09 08:03:39442 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
443 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42444 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17445 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
446 EXPECT_EQ("", out.response_data);
447}
448
[email protected]0877e3d2009-10-17 22:29:57449// A simple request using chunked encoding with some extra data after.
450// (Like might be seen in a pipelined response.)
451TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
452 MockRead data_reads[] = {
453 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
454 MockRead("5\r\nHello\r\n"),
455 MockRead("1\r\n"),
456 MockRead(" \r\n"),
457 MockRead("5\r\nworld\r\n"),
458 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
459 MockRead(false, OK),
460 };
[email protected]31a2bfe2010-02-09 08:03:39461 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
462 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57463 EXPECT_EQ(OK, out.rv);
464 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
465 EXPECT_EQ("Hello world", out.response_data);
466}
467
[email protected]9fe44f52010-09-23 18:36:00468// Next tests deal with http://crbug.com/56344.
469
470TEST_F(HttpNetworkTransactionTest,
471 MultipleContentLengthHeadersNoTransferEncoding) {
472 MockRead data_reads[] = {
473 MockRead("HTTP/1.1 200 OK\r\n"),
474 MockRead("Content-Length: 10\r\n"),
475 MockRead("Content-Length: 5\r\n\r\n"),
476 };
477 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
478 arraysize(data_reads));
479 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
480}
481
482TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04483 DuplicateContentLengthHeadersNoTransferEncoding) {
484 MockRead data_reads[] = {
485 MockRead("HTTP/1.1 200 OK\r\n"),
486 MockRead("Content-Length: 5\r\n"),
487 MockRead("Content-Length: 5\r\n\r\n"),
488 MockRead("Hello"),
489 };
490 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
491 arraysize(data_reads));
492 EXPECT_EQ(OK, out.rv);
493 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
494 EXPECT_EQ("Hello", out.response_data);
495}
496
497TEST_F(HttpNetworkTransactionTest,
498 ComplexContentLengthHeadersNoTransferEncoding) {
499 // More than 2 dupes.
500 {
501 MockRead data_reads[] = {
502 MockRead("HTTP/1.1 200 OK\r\n"),
503 MockRead("Content-Length: 5\r\n"),
504 MockRead("Content-Length: 5\r\n"),
505 MockRead("Content-Length: 5\r\n\r\n"),
506 MockRead("Hello"),
507 };
508 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
509 arraysize(data_reads));
510 EXPECT_EQ(OK, out.rv);
511 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
512 EXPECT_EQ("Hello", out.response_data);
513 }
514 // HTTP/1.0
515 {
516 MockRead data_reads[] = {
517 MockRead("HTTP/1.0 200 OK\r\n"),
518 MockRead("Content-Length: 5\r\n"),
519 MockRead("Content-Length: 5\r\n"),
520 MockRead("Content-Length: 5\r\n\r\n"),
521 MockRead("Hello"),
522 };
523 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
524 arraysize(data_reads));
525 EXPECT_EQ(OK, out.rv);
526 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
527 EXPECT_EQ("Hello", out.response_data);
528 }
529 // 2 dupes and one mismatched.
530 {
531 MockRead data_reads[] = {
532 MockRead("HTTP/1.1 200 OK\r\n"),
533 MockRead("Content-Length: 10\r\n"),
534 MockRead("Content-Length: 10\r\n"),
535 MockRead("Content-Length: 5\r\n\r\n"),
536 };
537 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
538 arraysize(data_reads));
539 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
540 }
541}
542
543TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00544 MultipleContentLengthHeadersTransferEncoding) {
545 MockRead data_reads[] = {
546 MockRead("HTTP/1.1 200 OK\r\n"),
547 MockRead("Content-Length: 666\r\n"),
548 MockRead("Content-Length: 1337\r\n"),
549 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
550 MockRead("5\r\nHello\r\n"),
551 MockRead("1\r\n"),
552 MockRead(" \r\n"),
553 MockRead("5\r\nworld\r\n"),
554 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
555 MockRead(false, OK),
556 };
557 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
558 arraysize(data_reads));
559 EXPECT_EQ(OK, out.rv);
560 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
561 EXPECT_EQ("Hello world", out.response_data);
562}
563
[email protected]ef0faf2e72009-03-05 23:27:23564// Do a request using the HEAD method. Verify that we don't try to read the
565// message body (since HEAD has none).
566TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42567 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23568 request.method = "HEAD";
569 request.url = GURL("http://www.google.com/");
570 request.load_flags = 0;
571
[email protected]cb9bf6ca2011-01-28 13:15:27572 SessionDependencies session_deps;
573 scoped_ptr<HttpTransaction> trans(
574 new HttpNetworkTransaction(CreateSession(&session_deps)));
575
[email protected]ef0faf2e72009-03-05 23:27:23576 MockWrite data_writes1[] = {
577 MockWrite("HEAD / HTTP/1.1\r\n"
578 "Host: www.google.com\r\n"
579 "Connection: keep-alive\r\n"
580 "Content-Length: 0\r\n\r\n"),
581 };
582 MockRead data_reads1[] = {
583 MockRead("HTTP/1.1 404 Not Found\r\n"),
584 MockRead("Server: Blah\r\n"),
585 MockRead("Content-Length: 1234\r\n\r\n"),
586
587 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42588 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23589 };
590
[email protected]31a2bfe2010-02-09 08:03:39591 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
592 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59593 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23594
595 TestCompletionCallback callback1;
596
[email protected]5a1d7ca2010-04-28 20:12:27597 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42598 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23599
600 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42601 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23602
[email protected]1c773ea12009-04-28 19:58:42603 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23604 EXPECT_FALSE(response == NULL);
605
606 // Check that the headers got parsed.
607 EXPECT_TRUE(response->headers != NULL);
608 EXPECT_EQ(1234, response->headers->GetContentLength());
609 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
610
611 std::string server_header;
612 void* iter = NULL;
613 bool has_server_header = response->headers->EnumerateHeader(
614 &iter, "Server", &server_header);
615 EXPECT_TRUE(has_server_header);
616 EXPECT_EQ("Blah", server_header);
617
618 // Reading should give EOF right away, since there is no message body
619 // (despite non-zero content-length).
620 std::string response_data;
621 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42622 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23623 EXPECT_EQ("", response_data);
624}
625
initial.commit586acc5fe2008-07-26 22:42:52626TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59627 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27628 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52629
630 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35631 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
632 MockRead("hello"),
633 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
634 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42635 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52636 };
[email protected]31a2bfe2010-02-09 08:03:39637 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59638 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52639
[email protected]0b0bf032010-09-21 18:08:50640 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52641 "hello", "world"
642 };
643
644 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42645 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52646 request.method = "GET";
647 request.url = GURL("http://www.google.com/");
648 request.load_flags = 0;
649
[email protected]cb9bf6ca2011-01-28 13:15:27650 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
651
initial.commit586acc5fe2008-07-26 22:42:52652 TestCompletionCallback callback;
653
[email protected]5a1d7ca2010-04-28 20:12:27654 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42655 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52656
657 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42658 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52659
[email protected]1c773ea12009-04-28 19:58:42660 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52661 EXPECT_TRUE(response != NULL);
662
663 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25664 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52665
666 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57667 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25669 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52670 }
671}
672
673TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42674 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52675 request.method = "POST";
676 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42677 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52678 request.upload_data->AppendBytes("foo", 3);
679 request.load_flags = 0;
680
[email protected]cb9bf6ca2011-01-28 13:15:27681 SessionDependencies session_deps;
682 scoped_ptr<HttpTransaction> trans(
683 new HttpNetworkTransaction(CreateSession(&session_deps)));
684
initial.commit586acc5fe2008-07-26 22:42:52685 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35686 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
687 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
688 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42689 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52690 };
[email protected]31a2bfe2010-02-09 08:03:39691 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59692 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52693
694 TestCompletionCallback callback;
695
[email protected]5a1d7ca2010-04-28 20:12:27696 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42697 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52698
699 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52701
[email protected]1c773ea12009-04-28 19:58:42702 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52703 EXPECT_TRUE(response != NULL);
704
705 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25706 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52707
708 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57709 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42710 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25711 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52712}
713
[email protected]3a2d3662009-03-27 03:49:14714// This test is almost the same as Ignores100 above, but the response contains
715// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57716// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14717TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42718 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14719 request.method = "GET";
720 request.url = GURL("http://www.foo.com/");
721 request.load_flags = 0;
722
[email protected]cb9bf6ca2011-01-28 13:15:27723 SessionDependencies session_deps;
724 scoped_ptr<HttpTransaction> trans(
725 new HttpNetworkTransaction(CreateSession(&session_deps)));
726
[email protected]3a2d3662009-03-27 03:49:14727 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57728 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
729 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14730 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42731 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14732 };
[email protected]31a2bfe2010-02-09 08:03:39733 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59734 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14735
736 TestCompletionCallback callback;
737
[email protected]5a1d7ca2010-04-28 20:12:27738 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42739 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14740
741 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42742 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14743
[email protected]1c773ea12009-04-28 19:58:42744 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14745 EXPECT_TRUE(response != NULL);
746
747 EXPECT_TRUE(response->headers != NULL);
748 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
749
750 std::string response_data;
751 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42752 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14753 EXPECT_EQ("hello world", response_data);
754}
755
[email protected]ee9410e72010-01-07 01:42:38756TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38757 HttpRequestInfo request;
758 request.method = "POST";
759 request.url = GURL("http://www.foo.com/");
760 request.load_flags = 0;
761
[email protected]cb9bf6ca2011-01-28 13:15:27762 SessionDependencies session_deps;
763 scoped_ptr<HttpTransaction> trans(
764 new HttpNetworkTransaction(CreateSession(&session_deps)));
765
[email protected]ee9410e72010-01-07 01:42:38766 MockRead data_reads[] = {
767 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
768 MockRead(true, 0),
769 };
[email protected]31a2bfe2010-02-09 08:03:39770 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38771 session_deps.socket_factory.AddSocketDataProvider(&data);
772
773 TestCompletionCallback callback;
774
[email protected]5a1d7ca2010-04-28 20:12:27775 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38776 EXPECT_EQ(ERR_IO_PENDING, rv);
777
778 rv = callback.WaitForResult();
779 EXPECT_EQ(OK, rv);
780
781 std::string response_data;
782 rv = ReadTransaction(trans.get(), &response_data);
783 EXPECT_EQ(OK, rv);
784 EXPECT_EQ("", response_data);
785}
786
787TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38788 HttpRequestInfo request;
789 request.method = "POST";
790 request.url = GURL("http://www.foo.com/");
791 request.load_flags = 0;
792
[email protected]cb9bf6ca2011-01-28 13:15:27793 SessionDependencies session_deps;
794 scoped_ptr<HttpTransaction> trans(
795 new HttpNetworkTransaction(CreateSession(&session_deps)));
796
[email protected]ee9410e72010-01-07 01:42:38797 MockRead data_reads[] = {
798 MockRead(true, 0),
799 };
[email protected]31a2bfe2010-02-09 08:03:39800 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38801 session_deps.socket_factory.AddSocketDataProvider(&data);
802
803 TestCompletionCallback callback;
804
[email protected]5a1d7ca2010-04-28 20:12:27805 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38806 EXPECT_EQ(ERR_IO_PENDING, rv);
807
808 rv = callback.WaitForResult();
809 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
810}
811
[email protected]3d2a59b2008-09-26 19:44:25812// read_failure specifies a read failure that should cause the network
813// transaction to resend the request.
814void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
815 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:42816 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52817 request.method = "GET";
818 request.url = GURL("http://www.foo.com/");
819 request.load_flags = 0;
820
[email protected]cb9bf6ca2011-01-28 13:15:27821 SessionDependencies session_deps;
822 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
823
initial.commit586acc5fe2008-07-26 22:42:52824 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35825 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
826 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25827 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52828 };
[email protected]31a2bfe2010-02-09 08:03:39829 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59830 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52831
832 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
834 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42835 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52836 };
[email protected]31a2bfe2010-02-09 08:03:39837 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59838 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52839
840 const char* kExpectedResponseData[] = {
841 "hello", "world"
842 };
843
844 for (int i = 0; i < 2; ++i) {
845 TestCompletionCallback callback;
846
[email protected]5695b8c2009-09-30 21:36:43847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52848
[email protected]5a1d7ca2010-04-28 20:12:27849 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42850 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52851
852 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42853 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52854
[email protected]1c773ea12009-04-28 19:58:42855 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52856 EXPECT_TRUE(response != NULL);
857
858 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52860
861 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57862 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42863 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25864 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52865 }
866}
[email protected]3d2a59b2008-09-26 19:44:25867
868TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42869 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25870 KeepAliveConnectionResendRequestTest(read_failure);
871}
872
873TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42874 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25875 KeepAliveConnectionResendRequestTest(read_failure);
876}
877
878TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42879 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25880 request.method = "GET";
881 request.url = GURL("http://www.google.com/");
882 request.load_flags = 0;
883
[email protected]cb9bf6ca2011-01-28 13:15:27884 SessionDependencies session_deps;
885 scoped_ptr<HttpTransaction> trans(
886 new HttpNetworkTransaction(CreateSession(&session_deps)));
887
[email protected]3d2a59b2008-09-26 19:44:25888 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42889 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35890 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
891 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42892 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25893 };
[email protected]31a2bfe2010-02-09 08:03:39894 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59895 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25896
897 TestCompletionCallback callback;
898
[email protected]5a1d7ca2010-04-28 20:12:27899 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42900 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25901
902 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42903 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25904
[email protected]1c773ea12009-04-28 19:58:42905 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25906 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25907}
908
909// What do various browsers do when the server closes a non-keepalive
910// connection without sending any response header or body?
911//
912// IE7: error page
913// Safari 3.1.2 (Windows): error page
914// Firefox 3.0.1: blank page
915// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42916// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
917// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25918TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
919 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42920 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35921 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
922 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42923 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25924 };
[email protected]31a2bfe2010-02-09 08:03:39925 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
926 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42927 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25928}
[email protected]038e9a32008-10-08 22:40:16929
[email protected]0b0bf032010-09-21 18:08:50930// Test that we correctly reuse a keep-alive connection after not explicitly
931// reading the body.
932TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13933 HttpRequestInfo request;
934 request.method = "GET";
935 request.url = GURL("http://www.foo.com/");
936 request.load_flags = 0;
937
[email protected]cb9bf6ca2011-01-28 13:15:27938 SessionDependencies session_deps;
939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
940
[email protected]0b0bf032010-09-21 18:08:50941 // Note that because all these reads happen in the same
942 // StaticSocketDataProvider, it shows that the same socket is being reused for
943 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13944 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50945 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
946 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13947 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50948 MockRead("HTTP/1.1 302 Found\r\n"
949 "Content-Length: 0\r\n\r\n"),
950 MockRead("HTTP/1.1 302 Found\r\n"
951 "Content-Length: 5\r\n\r\n"
952 "hello"),
953 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
954 "Content-Length: 0\r\n\r\n"),
955 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
956 "Content-Length: 5\r\n\r\n"
957 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13958 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
959 MockRead("hello"),
960 };
961 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
962 session_deps.socket_factory.AddSocketDataProvider(&data1);
963
964 MockRead data2_reads[] = {
965 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
966 };
967 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
968 session_deps.socket_factory.AddSocketDataProvider(&data2);
969
[email protected]0b0bf032010-09-21 18:08:50970 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
971 std::string response_lines[kNumUnreadBodies];
972
973 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13974 TestCompletionCallback callback;
975
976 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
977
978 int rv = trans->Start(&request, &callback, BoundNetLog());
979 EXPECT_EQ(ERR_IO_PENDING, rv);
980
981 rv = callback.WaitForResult();
982 EXPECT_EQ(OK, rv);
983
984 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50985 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13986
[email protected]0b0bf032010-09-21 18:08:50987 ASSERT_TRUE(response->headers != NULL);
988 response_lines[i] = response->headers->GetStatusLine();
989
990 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13991 }
[email protected]0b0bf032010-09-21 18:08:50992
993 const char* const kStatusLines[] = {
994 "HTTP/1.1 204 No Content",
995 "HTTP/1.1 205 Reset Content",
996 "HTTP/1.1 304 Not Modified",
997 "HTTP/1.1 302 Found",
998 "HTTP/1.1 302 Found",
999 "HTTP/1.1 301 Moved Permanently",
1000 "HTTP/1.1 301 Moved Permanently",
1001 };
1002
1003 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1004 forgot_to_update_kStatusLines);
1005
1006 for (int i = 0; i < kNumUnreadBodies; ++i)
1007 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1008
1009 TestCompletionCallback callback;
1010 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1011 int rv = trans->Start(&request, &callback, BoundNetLog());
1012 EXPECT_EQ(ERR_IO_PENDING, rv);
1013 rv = callback.WaitForResult();
1014 EXPECT_EQ(OK, rv);
1015 const HttpResponseInfo* response = trans->GetResponseInfo();
1016 ASSERT_TRUE(response != NULL);
1017 ASSERT_TRUE(response->headers != NULL);
1018 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1019 std::string response_data;
1020 rv = ReadTransaction(trans.get(), &response_data);
1021 EXPECT_EQ(OK, rv);
1022 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131023}
1024
[email protected]038e9a32008-10-08 22:40:161025// Test the request-challenge-retry sequence for basic auth.
1026// (basic auth is the easiest to mock, because it has no randomness).
1027TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421028 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161029 request.method = "GET";
1030 request.url = GURL("http://www.google.com/");
1031 request.load_flags = 0;
1032
[email protected]cb9bf6ca2011-01-28 13:15:271033 SessionDependencies session_deps;
1034 scoped_ptr<HttpTransaction> trans(
1035 new HttpNetworkTransaction(CreateSession(&session_deps)));
1036
[email protected]f9ee6b52008-11-08 06:46:231037 MockWrite data_writes1[] = {
1038 MockWrite("GET / HTTP/1.1\r\n"
1039 "Host: www.google.com\r\n"
1040 "Connection: keep-alive\r\n\r\n"),
1041 };
1042
[email protected]038e9a32008-10-08 22:40:161043 MockRead data_reads1[] = {
1044 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1045 // Give a couple authenticate options (only the middle one is actually
1046 // supported).
[email protected]22927ad2009-09-21 19:56:191047 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1049 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1051 // Large content-length -- won't matter, as connection will be reset.
1052 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421053 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161054 };
1055
1056 // After calling trans->RestartWithAuth(), this is the request we should
1057 // be issuing -- the final header line contains the credentials.
1058 MockWrite data_writes2[] = {
1059 MockWrite("GET / HTTP/1.1\r\n"
1060 "Host: www.google.com\r\n"
1061 "Connection: keep-alive\r\n"
1062 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1063 };
1064
1065 // Lastly, the server responds with the actual content.
1066 MockRead data_reads2[] = {
1067 MockRead("HTTP/1.0 200 OK\r\n"),
1068 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1069 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421070 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161071 };
1072
[email protected]31a2bfe2010-02-09 08:03:391073 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1074 data_writes1, arraysize(data_writes1));
1075 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1076 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591077 session_deps.socket_factory.AddSocketDataProvider(&data1);
1078 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161079
1080 TestCompletionCallback callback1;
1081
[email protected]5a1d7ca2010-04-28 20:12:271082 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421083 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161084
1085 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421086 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161087
[email protected]1c773ea12009-04-28 19:58:421088 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161089 EXPECT_FALSE(response == NULL);
1090
1091 // The password prompt info should have been set in response->auth_challenge.
1092 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1093
[email protected]71e4573a2009-05-21 22:03:001094 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161095 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1096 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1097
1098 TestCompletionCallback callback2;
1099
[email protected]13c8a092010-07-29 06:15:441100 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421101 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161102
1103 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421104 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161105
1106 response = trans->GetResponseInfo();
1107 EXPECT_FALSE(response == NULL);
1108 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1109 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161110}
1111
[email protected]861fcd52009-08-26 02:33:461112TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461113 HttpRequestInfo request;
1114 request.method = "GET";
1115 request.url = GURL("http://www.google.com/");
1116 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1117
[email protected]cb9bf6ca2011-01-28 13:15:271118 SessionDependencies session_deps;
1119 scoped_ptr<HttpTransaction> trans(
1120 new HttpNetworkTransaction(CreateSession(&session_deps)));
1121
[email protected]861fcd52009-08-26 02:33:461122 MockWrite data_writes[] = {
1123 MockWrite("GET / HTTP/1.1\r\n"
1124 "Host: www.google.com\r\n"
1125 "Connection: keep-alive\r\n\r\n"),
1126 };
1127
1128 MockRead data_reads[] = {
1129 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1130 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1131 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1132 // Large content-length -- won't matter, as connection will be reset.
1133 MockRead("Content-Length: 10000\r\n\r\n"),
1134 MockRead(false, ERR_FAILED),
1135 };
1136
[email protected]31a2bfe2010-02-09 08:03:391137 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1138 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591139 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461140 TestCompletionCallback callback;
1141
[email protected]5a1d7ca2010-04-28 20:12:271142 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461143 EXPECT_EQ(ERR_IO_PENDING, rv);
1144
1145 rv = callback.WaitForResult();
1146 EXPECT_EQ(0, rv);
1147
1148 const HttpResponseInfo* response = trans->GetResponseInfo();
1149 ASSERT_FALSE(response == NULL);
1150 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1151}
1152
[email protected]2d2697f92009-02-18 21:00:321153// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1154// connection.
1155TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421156 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321157 request.method = "GET";
1158 request.url = GURL("http://www.google.com/");
1159 request.load_flags = 0;
1160
[email protected]cb9bf6ca2011-01-28 13:15:271161 SessionDependencies session_deps;
1162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1163
[email protected]2d2697f92009-02-18 21:00:321164 MockWrite data_writes1[] = {
1165 MockWrite("GET / HTTP/1.1\r\n"
1166 "Host: www.google.com\r\n"
1167 "Connection: keep-alive\r\n\r\n"),
1168
1169 // After calling trans->RestartWithAuth(), this is the request we should
1170 // be issuing -- the final header line contains the credentials.
1171 MockWrite("GET / HTTP/1.1\r\n"
1172 "Host: www.google.com\r\n"
1173 "Connection: keep-alive\r\n"
1174 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1175 };
1176
1177 MockRead data_reads1[] = {
1178 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1179 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1180 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1181 MockRead("Content-Length: 14\r\n\r\n"),
1182 MockRead("Unauthorized\r\n"),
1183
1184 // Lastly, the server responds with the actual content.
1185 MockRead("HTTP/1.1 200 OK\r\n"),
1186 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501187 MockRead("Content-Length: 5\r\n\r\n"),
1188 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321189 };
1190
[email protected]31a2bfe2010-02-09 08:03:391191 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1192 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591193 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321194
1195 TestCompletionCallback callback1;
1196
[email protected]0b0bf032010-09-21 18:08:501197 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271198 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421199 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321200
1201 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421202 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321203
[email protected]1c773ea12009-04-28 19:58:421204 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321205 EXPECT_FALSE(response == NULL);
1206
1207 // The password prompt info should have been set in response->auth_challenge.
1208 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1209
[email protected]71e4573a2009-05-21 22:03:001210 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321211 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1212 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1213
1214 TestCompletionCallback callback2;
1215
[email protected]13c8a092010-07-29 06:15:441216 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421217 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321218
1219 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421220 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321221
1222 response = trans->GetResponseInfo();
1223 EXPECT_FALSE(response == NULL);
1224 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501225 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321226}
1227
1228// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1229// connection and with no response body to drain.
1230TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421231 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321232 request.method = "GET";
1233 request.url = GURL("http://www.google.com/");
1234 request.load_flags = 0;
1235
[email protected]cb9bf6ca2011-01-28 13:15:271236 SessionDependencies session_deps;
1237 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1238
[email protected]2d2697f92009-02-18 21:00:321239 MockWrite data_writes1[] = {
1240 MockWrite("GET / HTTP/1.1\r\n"
1241 "Host: www.google.com\r\n"
1242 "Connection: keep-alive\r\n\r\n"),
1243
1244 // After calling trans->RestartWithAuth(), this is the request we should
1245 // be issuing -- the final header line contains the credentials.
1246 MockWrite("GET / HTTP/1.1\r\n"
1247 "Host: www.google.com\r\n"
1248 "Connection: keep-alive\r\n"
1249 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1250 };
1251
[email protected]2d2697f92009-02-18 21:00:321252 MockRead data_reads1[] = {
1253 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1254 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311255 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321256
1257 // Lastly, the server responds with the actual content.
1258 MockRead("HTTP/1.1 200 OK\r\n"),
1259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501260 MockRead("Content-Length: 5\r\n\r\n"),
1261 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321262 };
1263
[email protected]31a2bfe2010-02-09 08:03:391264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1265 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591266 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321267
1268 TestCompletionCallback callback1;
1269
[email protected]0b0bf032010-09-21 18:08:501270 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271271 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421272 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321273
1274 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421275 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321276
[email protected]1c773ea12009-04-28 19:58:421277 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321278 EXPECT_FALSE(response == NULL);
1279
1280 // The password prompt info should have been set in response->auth_challenge.
1281 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1282
[email protected]71e4573a2009-05-21 22:03:001283 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321284 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1285 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1286
1287 TestCompletionCallback callback2;
1288
[email protected]13c8a092010-07-29 06:15:441289 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421290 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321291
1292 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421293 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321294
1295 response = trans->GetResponseInfo();
1296 EXPECT_FALSE(response == NULL);
1297 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501298 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321299}
1300
1301// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1302// connection and with a large response body to drain.
1303TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421304 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321305 request.method = "GET";
1306 request.url = GURL("http://www.google.com/");
1307 request.load_flags = 0;
1308
[email protected]cb9bf6ca2011-01-28 13:15:271309 SessionDependencies session_deps;
1310 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1311
[email protected]2d2697f92009-02-18 21:00:321312 MockWrite data_writes1[] = {
1313 MockWrite("GET / HTTP/1.1\r\n"
1314 "Host: www.google.com\r\n"
1315 "Connection: keep-alive\r\n\r\n"),
1316
1317 // After calling trans->RestartWithAuth(), this is the request we should
1318 // be issuing -- the final header line contains the credentials.
1319 MockWrite("GET / HTTP/1.1\r\n"
1320 "Host: www.google.com\r\n"
1321 "Connection: keep-alive\r\n"
1322 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1323 };
1324
1325 // Respond with 5 kb of response body.
1326 std::string large_body_string("Unauthorized");
1327 large_body_string.append(5 * 1024, ' ');
1328 large_body_string.append("\r\n");
1329
1330 MockRead data_reads1[] = {
1331 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1332 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1333 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1334 // 5134 = 12 + 5 * 1024 + 2
1335 MockRead("Content-Length: 5134\r\n\r\n"),
1336 MockRead(true, large_body_string.data(), large_body_string.size()),
1337
1338 // Lastly, the server responds with the actual content.
1339 MockRead("HTTP/1.1 200 OK\r\n"),
1340 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501341 MockRead("Content-Length: 5\r\n\r\n"),
1342 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321343 };
1344
[email protected]31a2bfe2010-02-09 08:03:391345 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1346 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591347 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321348
1349 TestCompletionCallback callback1;
1350
[email protected]0b0bf032010-09-21 18:08:501351 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271352 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421353 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321354
1355 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421356 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321357
[email protected]1c773ea12009-04-28 19:58:421358 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321359 EXPECT_FALSE(response == NULL);
1360
1361 // The password prompt info should have been set in response->auth_challenge.
1362 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1363
[email protected]71e4573a2009-05-21 22:03:001364 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321365 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1366 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1367
1368 TestCompletionCallback callback2;
1369
[email protected]13c8a092010-07-29 06:15:441370 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421371 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321372
1373 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421374 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321375
1376 response = trans->GetResponseInfo();
1377 EXPECT_FALSE(response == NULL);
1378 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501379 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321380}
1381
1382// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311383// connection, but the server gets impatient and closes the connection.
1384TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311385 HttpRequestInfo request;
1386 request.method = "GET";
1387 request.url = GURL("http://www.google.com/");
1388 request.load_flags = 0;
1389
[email protected]cb9bf6ca2011-01-28 13:15:271390 SessionDependencies session_deps;
1391 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1392
[email protected]11203f012009-11-12 23:02:311393 MockWrite data_writes1[] = {
1394 MockWrite("GET / HTTP/1.1\r\n"
1395 "Host: www.google.com\r\n"
1396 "Connection: keep-alive\r\n\r\n"),
1397 // This simulates the seemingly successful write to a closed connection
1398 // if the bug is not fixed.
1399 MockWrite("GET / HTTP/1.1\r\n"
1400 "Host: www.google.com\r\n"
1401 "Connection: keep-alive\r\n"
1402 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1403 };
1404
1405 MockRead data_reads1[] = {
1406 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1407 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1409 MockRead("Content-Length: 14\r\n\r\n"),
1410 // Tell MockTCPClientSocket to simulate the server closing the connection.
1411 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1412 MockRead("Unauthorized\r\n"),
1413 MockRead(false, OK), // The server closes the connection.
1414 };
1415
1416 // After calling trans->RestartWithAuth(), this is the request we should
1417 // be issuing -- the final header line contains the credentials.
1418 MockWrite data_writes2[] = {
1419 MockWrite("GET / HTTP/1.1\r\n"
1420 "Host: www.google.com\r\n"
1421 "Connection: keep-alive\r\n"
1422 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1423 };
1424
1425 // Lastly, the server responds with the actual content.
1426 MockRead data_reads2[] = {
1427 MockRead("HTTP/1.1 200 OK\r\n"),
1428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501429 MockRead("Content-Length: 5\r\n\r\n"),
1430 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311431 };
1432
[email protected]31a2bfe2010-02-09 08:03:391433 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1434 data_writes1, arraysize(data_writes1));
1435 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1436 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311437 session_deps.socket_factory.AddSocketDataProvider(&data1);
1438 session_deps.socket_factory.AddSocketDataProvider(&data2);
1439
1440 TestCompletionCallback callback1;
1441
[email protected]0b0bf032010-09-21 18:08:501442 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271443 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311444 EXPECT_EQ(ERR_IO_PENDING, rv);
1445
1446 rv = callback1.WaitForResult();
1447 EXPECT_EQ(OK, rv);
1448
1449 const HttpResponseInfo* response = trans->GetResponseInfo();
1450 EXPECT_FALSE(response == NULL);
1451
1452 // The password prompt info should have been set in response->auth_challenge.
1453 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1454
1455 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1456 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1457 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1458
1459 TestCompletionCallback callback2;
1460
[email protected]13c8a092010-07-29 06:15:441461 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311462 EXPECT_EQ(ERR_IO_PENDING, rv);
1463
1464 rv = callback2.WaitForResult();
1465 EXPECT_EQ(OK, rv);
1466
1467 response = trans->GetResponseInfo();
1468 ASSERT_FALSE(response == NULL);
1469 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501470 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311471}
1472
[email protected]394816e92010-08-03 07:38:591473// Test the request-challenge-retry sequence for basic auth, over a connection
1474// that requires a restart when setting up an SSL tunnel.
1475TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591476 HttpRequestInfo request;
1477 request.method = "GET";
1478 request.url = GURL("https://www.google.com/");
1479 // when the no authentication data flag is set.
1480 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1481
[email protected]cb9bf6ca2011-01-28 13:15:271482 // Configure against proxy server "myproxy:70".
1483 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1484 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1485 session_deps.net_log = log.bound().net_log();
1486 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1487
[email protected]394816e92010-08-03 07:38:591488 // Since we have proxy, should try to establish tunnel.
1489 MockWrite data_writes1[] = {
1490 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1491 "Host: www.google.com\r\n"
1492 "Proxy-Connection: keep-alive\r\n\r\n"),
1493
1494 // After calling trans->RestartWithAuth(), this is the request we should
1495 // be issuing -- the final header line contains the credentials.
1496 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1497 "Host: www.google.com\r\n"
1498 "Proxy-Connection: keep-alive\r\n"
1499 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1500
1501 MockWrite("GET / HTTP/1.1\r\n"
1502 "Host: www.google.com\r\n"
1503 "Connection: keep-alive\r\n\r\n"),
1504 };
1505
1506 // The proxy responds to the connect with a 407, using a persistent
1507 // connection.
1508 MockRead data_reads1[] = {
1509 // No credentials.
1510 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1511 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1512 MockRead("Proxy-Connection: close\r\n\r\n"),
1513
1514 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1515
1516 MockRead("HTTP/1.1 200 OK\r\n"),
1517 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501518 MockRead("Content-Length: 5\r\n\r\n"),
1519 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591520 };
1521
1522 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1523 data_writes1, arraysize(data_writes1));
1524 session_deps.socket_factory.AddSocketDataProvider(&data1);
1525 SSLSocketDataProvider ssl(true, OK);
1526 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1527
1528 TestCompletionCallback callback1;
1529
[email protected]0b0bf032010-09-21 18:08:501530 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1531
[email protected]394816e92010-08-03 07:38:591532 int rv = trans->Start(&request, &callback1, log.bound());
1533 EXPECT_EQ(ERR_IO_PENDING, rv);
1534
1535 rv = callback1.WaitForResult();
1536 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401537 net::CapturingNetLog::EntryList entries;
1538 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591539 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401540 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591541 NetLog::PHASE_NONE);
1542 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401543 entries, pos,
[email protected]394816e92010-08-03 07:38:591544 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1545 NetLog::PHASE_NONE);
1546
1547 const HttpResponseInfo* response = trans->GetResponseInfo();
1548 ASSERT_FALSE(response == NULL);
1549
1550 EXPECT_EQ(407, response->headers->response_code());
1551 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1552
1553 // The password prompt info should have been set in response->auth_challenge.
1554 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1555
1556 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1557 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1558 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1559
1560 TestCompletionCallback callback2;
1561
1562 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1563 EXPECT_EQ(ERR_IO_PENDING, rv);
1564
1565 rv = callback2.WaitForResult();
1566 EXPECT_EQ(OK, rv);
1567
1568 response = trans->GetResponseInfo();
1569 ASSERT_FALSE(response == NULL);
1570
1571 EXPECT_TRUE(response->headers->IsKeepAlive());
1572 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501573 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591574 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1575
1576 // The password prompt info should not be set.
1577 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501578
1579 trans.reset();
1580 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591581}
1582
[email protected]11203f012009-11-12 23:02:311583// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321584// proxy connection, when setting up an SSL tunnel.
1585TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271586 HttpRequestInfo request;
1587 request.method = "GET";
1588 request.url = GURL("https://www.google.com/");
1589 // Ensure that proxy authentication is attempted even
1590 // when the no authentication data flag is set.
1591 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1592
[email protected]2d2697f92009-02-18 21:00:321593 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001594 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541595 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1596 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591597 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321598
[email protected]5695b8c2009-09-30 21:36:431599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321600
[email protected]2d2697f92009-02-18 21:00:321601 // Since we have proxy, should try to establish tunnel.
1602 MockWrite data_writes1[] = {
1603 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451604 "Host: www.google.com\r\n"
1605 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321606
1607 // After calling trans->RestartWithAuth(), this is the request we should
1608 // be issuing -- the final header line contains the credentials.
1609 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1610 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451611 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321612 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1613 };
1614
1615 // The proxy responds to the connect with a 407, using a persistent
1616 // connection.
1617 MockRead data_reads1[] = {
1618 // No credentials.
1619 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1620 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1621 MockRead("Content-Length: 10\r\n\r\n"),
1622 MockRead("0123456789"),
1623
1624 // Wrong credentials (wrong password).
1625 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1626 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1627 MockRead("Content-Length: 10\r\n\r\n"),
1628 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421629 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321630 };
1631
[email protected]31a2bfe2010-02-09 08:03:391632 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1633 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591634 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321635
1636 TestCompletionCallback callback1;
1637
[email protected]dbb83db2010-05-11 18:13:391638 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421639 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321640
1641 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421642 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401643 net::CapturingNetLog::EntryList entries;
1644 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391645 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401646 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391647 NetLog::PHASE_NONE);
1648 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401649 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391650 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1651 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321652
[email protected]1c773ea12009-04-28 19:58:421653 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321654 EXPECT_FALSE(response == NULL);
1655
1656 EXPECT_TRUE(response->headers->IsKeepAlive());
1657 EXPECT_EQ(407, response->headers->response_code());
1658 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421659 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321660
1661 // The password prompt info should have been set in response->auth_challenge.
1662 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1663
[email protected]71e4573a2009-05-21 22:03:001664 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321665 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1666 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1667
1668 TestCompletionCallback callback2;
1669
1670 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441671 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421672 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321673
1674 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421675 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321676
1677 response = trans->GetResponseInfo();
1678 EXPECT_FALSE(response == NULL);
1679
1680 EXPECT_TRUE(response->headers->IsKeepAlive());
1681 EXPECT_EQ(407, response->headers->response_code());
1682 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421683 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321684
1685 // The password prompt info should have been set in response->auth_challenge.
1686 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1687
[email protected]71e4573a2009-05-21 22:03:001688 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321689 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1690 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131691
[email protected]e60e47a2010-07-14 03:37:181692 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1693 // out of scope.
1694 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321695}
1696
[email protected]a8e9b162009-03-12 00:06:441697// Test that we don't read the response body when we fail to establish a tunnel,
1698// even if the user cancels the proxy's auth attempt.
1699TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271700 HttpRequestInfo request;
1701 request.method = "GET";
1702 request.url = GURL("https://www.google.com/");
1703 request.load_flags = 0;
1704
[email protected]a8e9b162009-03-12 00:06:441705 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001706 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441707
[email protected]e44de5d2009-06-05 20:12:451708 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441709
[email protected]5695b8c2009-09-30 21:36:431710 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441711
[email protected]a8e9b162009-03-12 00:06:441712 // Since we have proxy, should try to establish tunnel.
1713 MockWrite data_writes[] = {
1714 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451715 "Host: www.google.com\r\n"
1716 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441717 };
1718
1719 // The proxy responds to the connect with a 407.
1720 MockRead data_reads[] = {
1721 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1722 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1723 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421724 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441725 };
1726
[email protected]31a2bfe2010-02-09 08:03:391727 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1728 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591729 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441730
1731 TestCompletionCallback callback;
1732
[email protected]5a1d7ca2010-04-28 20:12:271733 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421734 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441735
1736 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421737 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441738
[email protected]1c773ea12009-04-28 19:58:421739 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441740 EXPECT_FALSE(response == NULL);
1741
1742 EXPECT_TRUE(response->headers->IsKeepAlive());
1743 EXPECT_EQ(407, response->headers->response_code());
1744 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421745 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441746
1747 std::string response_data;
1748 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421749 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181750
1751 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1752 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441753}
1754
[email protected]8fdbcd22010-05-05 02:54:521755// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1756// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1757TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521758 HttpRequestInfo request;
1759 request.method = "GET";
1760 request.url = GURL("http://www.google.com/");
1761 request.load_flags = 0;
1762
[email protected]cb9bf6ca2011-01-28 13:15:271763 // We are using a DIRECT connection (i.e. no proxy) for this session.
1764 SessionDependencies session_deps;
1765 scoped_ptr<HttpTransaction> trans(
1766 new HttpNetworkTransaction(CreateSession(&session_deps)));
1767
[email protected]8fdbcd22010-05-05 02:54:521768 MockWrite data_writes1[] = {
1769 MockWrite("GET / HTTP/1.1\r\n"
1770 "Host: www.google.com\r\n"
1771 "Connection: keep-alive\r\n\r\n"),
1772 };
1773
1774 MockRead data_reads1[] = {
1775 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1777 // Large content-length -- won't matter, as connection will be reset.
1778 MockRead("Content-Length: 10000\r\n\r\n"),
1779 MockRead(false, ERR_FAILED),
1780 };
1781
1782 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1783 data_writes1, arraysize(data_writes1));
1784 session_deps.socket_factory.AddSocketDataProvider(&data1);
1785
1786 TestCompletionCallback callback;
1787
1788 int rv = trans->Start(&request, &callback, BoundNetLog());
1789 EXPECT_EQ(ERR_IO_PENDING, rv);
1790
1791 rv = callback.WaitForResult();
1792 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1793}
1794
[email protected]7a67a8152010-11-05 18:31:101795// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1796// through a non-authenticating proxy. The request should fail with
1797// ERR_UNEXPECTED_PROXY_AUTH.
1798// Note that it is impossible to detect if an HTTP server returns a 407 through
1799// a non-authenticating proxy - there is nothing to indicate whether the
1800// response came from the proxy or the server, so it is treated as if the proxy
1801// issued the challenge.
1802TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271803 HttpRequestInfo request;
1804 request.method = "GET";
1805 request.url = GURL("https://www.google.com/");
1806
[email protected]7a67a8152010-11-05 18:31:101807 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1808 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1809 session_deps.net_log = log.bound().net_log();
1810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1811
[email protected]7a67a8152010-11-05 18:31:101812 // Since we have proxy, should try to establish tunnel.
1813 MockWrite data_writes1[] = {
1814 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1815 "Host: www.google.com\r\n"
1816 "Proxy-Connection: keep-alive\r\n\r\n"),
1817
1818 MockWrite("GET / HTTP/1.1\r\n"
1819 "Host: www.google.com\r\n"
1820 "Connection: keep-alive\r\n\r\n"),
1821 };
1822
1823 MockRead data_reads1[] = {
1824 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1825
1826 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1827 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1828 MockRead("\r\n"),
1829 MockRead(false, OK),
1830 };
1831
1832 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1833 data_writes1, arraysize(data_writes1));
1834 session_deps.socket_factory.AddSocketDataProvider(&data1);
1835 SSLSocketDataProvider ssl(true, OK);
1836 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1837
1838 TestCompletionCallback callback1;
1839
1840 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1841
1842 int rv = trans->Start(&request, &callback1, log.bound());
1843 EXPECT_EQ(ERR_IO_PENDING, rv);
1844
1845 rv = callback1.WaitForResult();
1846 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401847 net::CapturingNetLog::EntryList entries;
1848 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101849 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401850 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101851 NetLog::PHASE_NONE);
1852 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401853 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101854 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1855 NetLog::PHASE_NONE);
1856}
[email protected]2df19bb2010-08-25 20:13:461857
1858// Test a simple get through an HTTPS Proxy.
1859TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271860 HttpRequestInfo request;
1861 request.method = "GET";
1862 request.url = GURL("http://www.google.com/");
1863
[email protected]2df19bb2010-08-25 20:13:461864 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001865 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461866 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1867 session_deps.net_log = log.bound().net_log();
1868 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1869
[email protected]2df19bb2010-08-25 20:13:461870 // Since we have proxy, should use full url
1871 MockWrite data_writes1[] = {
1872 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1873 "Host: www.google.com\r\n"
1874 "Proxy-Connection: keep-alive\r\n\r\n"),
1875 };
1876
1877 MockRead data_reads1[] = {
1878 MockRead("HTTP/1.1 200 OK\r\n"),
1879 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1880 MockRead("Content-Length: 100\r\n\r\n"),
1881 MockRead(false, OK),
1882 };
1883
1884 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1885 data_writes1, arraysize(data_writes1));
1886 session_deps.socket_factory.AddSocketDataProvider(&data1);
1887 SSLSocketDataProvider ssl(true, OK);
1888 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1889
1890 TestCompletionCallback callback1;
1891
[email protected]0b0bf032010-09-21 18:08:501892 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1893
[email protected]2df19bb2010-08-25 20:13:461894 int rv = trans->Start(&request, &callback1, log.bound());
1895 EXPECT_EQ(ERR_IO_PENDING, rv);
1896
1897 rv = callback1.WaitForResult();
1898 EXPECT_EQ(OK, rv);
1899
1900 const HttpResponseInfo* response = trans->GetResponseInfo();
1901 ASSERT_FALSE(response == NULL);
1902
1903 EXPECT_TRUE(response->headers->IsKeepAlive());
1904 EXPECT_EQ(200, response->headers->response_code());
1905 EXPECT_EQ(100, response->headers->GetContentLength());
1906 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1907
1908 // The password prompt info should not be set.
1909 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1910}
1911
[email protected]7642b5ae2010-09-01 20:55:171912// Test a SPDY get through an HTTPS Proxy.
1913TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271914 HttpRequestInfo request;
1915 request.method = "GET";
1916 request.url = GURL("http://www.google.com/");
1917 request.load_flags = 0;
1918
[email protected]7642b5ae2010-09-01 20:55:171919 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001920 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171921 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1922 session_deps.net_log = log.bound().net_log();
1923 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1924
[email protected]7642b5ae2010-09-01 20:55:171925 // fetch http://www.google.com/ via SPDY
1926 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1927 false));
1928 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1929
1930 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1931 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1932 MockRead spdy_reads[] = {
1933 CreateMockRead(*resp),
1934 CreateMockRead(*data),
1935 MockRead(true, 0, 0),
1936 };
1937
1938 scoped_refptr<DelayedSocketData> spdy_data(
1939 new DelayedSocketData(
1940 1, // wait for one write to finish before reading.
1941 spdy_reads, arraysize(spdy_reads),
1942 spdy_writes, arraysize(spdy_writes)));
1943 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1944
1945 SSLSocketDataProvider ssl(true, OK);
1946 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1947 ssl.next_proto = "spdy/2";
1948 ssl.was_npn_negotiated = true;
1949 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1950
1951 TestCompletionCallback callback1;
1952
[email protected]0b0bf032010-09-21 18:08:501953 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1954
[email protected]7642b5ae2010-09-01 20:55:171955 int rv = trans->Start(&request, &callback1, log.bound());
1956 EXPECT_EQ(ERR_IO_PENDING, rv);
1957
1958 rv = callback1.WaitForResult();
1959 EXPECT_EQ(OK, rv);
1960
1961 const HttpResponseInfo* response = trans->GetResponseInfo();
1962 ASSERT_TRUE(response != NULL);
1963 ASSERT_TRUE(response->headers != NULL);
1964 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1965
1966 std::string response_data;
1967 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1968 EXPECT_EQ(net::kUploadData, response_data);
1969}
1970
[email protected]dc7bd1c52010-11-12 00:01:131971// Test a SPDY get through an HTTPS Proxy.
1972TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:271973 HttpRequestInfo request;
1974 request.method = "GET";
1975 request.url = GURL("http://www.google.com/");
1976 request.load_flags = 0;
1977
[email protected]dc7bd1c52010-11-12 00:01:131978 // Configure against https proxy server "proxy:70".
1979 SessionDependencies session_deps(
1980 ProxyService::CreateFixed("https://proxy:70"));
1981 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1982 session_deps.net_log = log.bound().net_log();
1983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1984
[email protected]dc7bd1c52010-11-12 00:01:131985 // The first request will be a bare GET, the second request will be a
1986 // GET with a Proxy-Authorization header.
1987 scoped_ptr<spdy::SpdyFrame> req_get(
1988 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
1989 const char* const kExtraAuthorizationHeaders[] = {
1990 "proxy-authorization",
1991 "Basic Zm9vOmJhcg==",
1992 };
1993 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
1994 ConstructSpdyGet(
1995 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
1996 false, 3, LOWEST, false));
1997 MockWrite spdy_writes[] = {
1998 CreateMockWrite(*req_get, 1),
1999 CreateMockWrite(*req_get_authorization, 4),
2000 };
2001
2002 // The first response is a 407 proxy authentication challenge, and the second
2003 // response will be a 200 response since the second request includes a valid
2004 // Authorization header.
2005 const char* const kExtraAuthenticationHeaders[] = {
2006 "Proxy-Authenticate",
2007 "Basic realm=\"MyRealm1\""
2008 };
2009 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2010 ConstructSpdySynReplyError(
2011 "407 Proxy Authentication Required",
2012 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2013 1));
2014 scoped_ptr<spdy::SpdyFrame> body_authentication(
2015 ConstructSpdyBodyFrame(1, true));
2016 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2017 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2018 MockRead spdy_reads[] = {
2019 CreateMockRead(*resp_authentication, 2),
2020 CreateMockRead(*body_authentication, 3),
2021 CreateMockRead(*resp_data, 5),
2022 CreateMockRead(*body_data, 6),
2023 MockRead(true, 0, 7),
2024 };
2025
2026 scoped_refptr<OrderedSocketData> data(
2027 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2028 spdy_writes, arraysize(spdy_writes)));
2029 session_deps.socket_factory.AddSocketDataProvider(data);
2030
2031 SSLSocketDataProvider ssl(true, OK);
2032 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2033 ssl.next_proto = "spdy/2";
2034 ssl.was_npn_negotiated = true;
2035 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2036
2037 TestCompletionCallback callback1;
2038
2039 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2040
2041 int rv = trans->Start(&request, &callback1, log.bound());
2042 EXPECT_EQ(ERR_IO_PENDING, rv);
2043
2044 rv = callback1.WaitForResult();
2045 EXPECT_EQ(OK, rv);
2046
2047 const HttpResponseInfo* const response = trans->GetResponseInfo();
2048
2049 ASSERT_TRUE(response != NULL);
2050 ASSERT_TRUE(response->headers != NULL);
2051 EXPECT_EQ(407, response->headers->response_code());
2052 EXPECT_TRUE(response->was_fetched_via_spdy);
2053
2054 // The password prompt info should have been set in response->auth_challenge.
2055 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2056 EXPECT_TRUE(response->auth_challenge->is_proxy);
2057 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2058 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2059 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2060
2061 TestCompletionCallback callback2;
2062
2063 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2064 EXPECT_EQ(ERR_IO_PENDING, rv);
2065
2066 rv = callback2.WaitForResult();
2067 EXPECT_EQ(OK, rv);
2068
2069 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2070
2071 ASSERT_TRUE(response_restart != NULL);
2072 ASSERT_TRUE(response_restart->headers != NULL);
2073 EXPECT_EQ(200, response_restart->headers->response_code());
2074 // The password prompt info should not be set.
2075 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2076}
2077
[email protected]d9da5fe2010-10-13 22:37:162078// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2079TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272080 HttpRequestInfo request;
2081 request.method = "GET";
2082 request.url = GURL("https://www.google.com/");
2083 request.load_flags = 0;
2084
[email protected]d9da5fe2010-10-13 22:37:162085 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002086 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162087 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2088 session_deps.net_log = log.bound().net_log();
2089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2090
2091 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2092
[email protected]d9da5fe2010-10-13 22:37:162093 // CONNECT to www.google.com:443 via SPDY
2094 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2095 // fetch https://www.google.com/ via HTTP
2096
2097 const char get[] = "GET / HTTP/1.1\r\n"
2098 "Host: www.google.com\r\n"
2099 "Connection: keep-alive\r\n\r\n";
2100 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2101 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2102 MockWrite spdy_writes[] = {
2103 CreateMockWrite(*connect, 1),
2104 CreateMockWrite(*wrapped_get, 3)
2105 };
2106
2107 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2108 const char resp[] = "HTTP/1.1 200 OK\r\n"
2109 "Content-Length: 10\r\n\r\n";
2110
2111 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2112 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2113 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2114 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2115 MockRead spdy_reads[] = {
2116 CreateMockRead(*conn_resp, 2, true),
2117 CreateMockRead(*wrapped_get_resp, 4, true),
2118 CreateMockRead(*wrapped_body, 5, true),
2119 CreateMockRead(*wrapped_body, 6, true),
2120 MockRead(true, 0, 7),
2121 };
2122
2123 scoped_refptr<OrderedSocketData> spdy_data(
2124 new OrderedSocketData(
2125 spdy_reads, arraysize(spdy_reads),
2126 spdy_writes, arraysize(spdy_writes)));
2127 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2128
2129 SSLSocketDataProvider ssl(true, OK);
2130 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2131 ssl.next_proto = "spdy/2";
2132 ssl.was_npn_negotiated = true;
2133 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2134 SSLSocketDataProvider ssl2(true, OK);
2135 ssl2.was_npn_negotiated = false;
2136 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2137
2138 TestCompletionCallback callback1;
2139
2140 int rv = trans->Start(&request, &callback1, log.bound());
2141 EXPECT_EQ(ERR_IO_PENDING, rv);
2142
2143 rv = callback1.WaitForResult();
2144 EXPECT_EQ(OK, rv);
2145
2146 const HttpResponseInfo* response = trans->GetResponseInfo();
2147 ASSERT_TRUE(response != NULL);
2148 ASSERT_TRUE(response->headers != NULL);
2149 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2150
2151 std::string response_data;
2152 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2153 EXPECT_EQ("1234567890", response_data);
2154}
2155
2156// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2157TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272158 HttpRequestInfo request;
2159 request.method = "GET";
2160 request.url = GURL("https://www.google.com/");
2161 request.load_flags = 0;
2162
[email protected]d9da5fe2010-10-13 22:37:162163 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002164 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162165 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2166 session_deps.net_log = log.bound().net_log();
2167 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2168
2169 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2170
[email protected]d9da5fe2010-10-13 22:37:162171 // CONNECT to www.google.com:443 via SPDY
2172 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2173 // fetch https://www.google.com/ via SPDY
2174 const char* const kMyUrl = "https://www.google.com/";
2175 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2176 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2177 MockWrite spdy_writes[] = {
2178 CreateMockWrite(*connect, 1),
2179 CreateMockWrite(*wrapped_get, 3)
2180 };
2181
2182 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2183 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2184 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2185 ConstructWrappedSpdyFrame(get_resp, 1));
2186 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2187 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2188 MockRead spdy_reads[] = {
2189 CreateMockRead(*conn_resp, 2, true),
2190 CreateMockRead(*wrapped_get_resp, 4, true),
2191 CreateMockRead(*wrapped_body, 5, true),
2192 MockRead(true, 0, 1),
2193 };
2194
2195 scoped_refptr<OrderedSocketData> spdy_data(
2196 new OrderedSocketData(
2197 spdy_reads, arraysize(spdy_reads),
2198 spdy_writes, arraysize(spdy_writes)));
2199 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2200
2201 SSLSocketDataProvider ssl(true, OK);
2202 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2203 ssl.next_proto = "spdy/2";
2204 ssl.was_npn_negotiated = true;
2205 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2206 SSLSocketDataProvider ssl2(true, OK);
2207 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2208 ssl2.next_proto = "spdy/2";
2209 ssl2.was_npn_negotiated = true;
2210 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2211
2212 TestCompletionCallback callback1;
2213
2214 int rv = trans->Start(&request, &callback1, log.bound());
2215 EXPECT_EQ(ERR_IO_PENDING, rv);
2216
2217 rv = callback1.WaitForResult();
2218 EXPECT_EQ(OK, rv);
2219
2220 const HttpResponseInfo* response = trans->GetResponseInfo();
2221 ASSERT_TRUE(response != NULL);
2222 ASSERT_TRUE(response->headers != NULL);
2223 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2224
2225 std::string response_data;
2226 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2227 EXPECT_EQ(net::kUploadData, response_data);
2228}
2229
2230// Test a SPDY CONNECT failure through an HTTPS Proxy.
2231TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272232 HttpRequestInfo request;
2233 request.method = "GET";
2234 request.url = GURL("https://www.google.com/");
2235 request.load_flags = 0;
2236
[email protected]d9da5fe2010-10-13 22:37:162237 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002238 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162239 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2240 session_deps.net_log = log.bound().net_log();
2241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2242
2243 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2244
[email protected]d9da5fe2010-10-13 22:37:162245 // CONNECT to www.google.com:443 via SPDY
2246 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2247 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2248
2249 MockWrite spdy_writes[] = {
2250 CreateMockWrite(*connect, 1),
2251 CreateMockWrite(*get, 3),
2252 };
2253
2254 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2255 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2256 MockRead spdy_reads[] = {
2257 CreateMockRead(*resp, 2, true),
2258 MockRead(true, 0, 4),
2259 };
2260
2261 scoped_refptr<OrderedSocketData> spdy_data(
2262 new OrderedSocketData(
2263 spdy_reads, arraysize(spdy_reads),
2264 spdy_writes, arraysize(spdy_writes)));
2265 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2266
2267 SSLSocketDataProvider ssl(true, OK);
2268 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2269 ssl.next_proto = "spdy/2";
2270 ssl.was_npn_negotiated = true;
2271 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2272 SSLSocketDataProvider ssl2(true, OK);
2273 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2274 ssl2.next_proto = "spdy/2";
2275 ssl2.was_npn_negotiated = true;
2276 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2277
2278 TestCompletionCallback callback1;
2279
2280 int rv = trans->Start(&request, &callback1, log.bound());
2281 EXPECT_EQ(ERR_IO_PENDING, rv);
2282
2283 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292284 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162285
2286 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292287 ASSERT_FALSE(response == NULL);
2288 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162289}
2290
[email protected]2df19bb2010-08-25 20:13:462291// Test the challenge-response-retry sequence through an HTTPS Proxy
2292TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462293 HttpRequestInfo request;
2294 request.method = "GET";
2295 request.url = GURL("http://www.google.com/");
2296 // when the no authentication data flag is set.
2297 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2298
[email protected]cb9bf6ca2011-01-28 13:15:272299 // Configure against https proxy server "proxy:70".
2300 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2301 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2302 session_deps.net_log = log.bound().net_log();
2303 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2304
[email protected]2df19bb2010-08-25 20:13:462305 // Since we have proxy, should use full url
2306 MockWrite data_writes1[] = {
2307 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2308 "Host: www.google.com\r\n"
2309 "Proxy-Connection: keep-alive\r\n\r\n"),
2310
2311 // After calling trans->RestartWithAuth(), this is the request we should
2312 // be issuing -- the final header line contains the credentials.
2313 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2314 "Host: www.google.com\r\n"
2315 "Proxy-Connection: keep-alive\r\n"
2316 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2317 };
2318
2319 // The proxy responds to the GET with a 407, using a persistent
2320 // connection.
2321 MockRead data_reads1[] = {
2322 // No credentials.
2323 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2324 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2325 MockRead("Proxy-Connection: keep-alive\r\n"),
2326 MockRead("Content-Length: 0\r\n\r\n"),
2327
2328 MockRead("HTTP/1.1 200 OK\r\n"),
2329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2330 MockRead("Content-Length: 100\r\n\r\n"),
2331 MockRead(false, OK),
2332 };
2333
2334 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2335 data_writes1, arraysize(data_writes1));
2336 session_deps.socket_factory.AddSocketDataProvider(&data1);
2337 SSLSocketDataProvider ssl(true, OK);
2338 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2339
2340 TestCompletionCallback callback1;
2341
[email protected]0b0bf032010-09-21 18:08:502342 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2343
[email protected]2df19bb2010-08-25 20:13:462344 int rv = trans->Start(&request, &callback1, log.bound());
2345 EXPECT_EQ(ERR_IO_PENDING, rv);
2346
2347 rv = callback1.WaitForResult();
2348 EXPECT_EQ(OK, rv);
2349
2350 const HttpResponseInfo* response = trans->GetResponseInfo();
2351 ASSERT_FALSE(response == NULL);
2352
2353 EXPECT_EQ(407, response->headers->response_code());
2354 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2355
2356 // The password prompt info should have been set in response->auth_challenge.
2357 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2358
2359 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2360 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2361 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2362
2363 TestCompletionCallback callback2;
2364
2365 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2366 EXPECT_EQ(ERR_IO_PENDING, rv);
2367
2368 rv = callback2.WaitForResult();
2369 EXPECT_EQ(OK, rv);
2370
2371 response = trans->GetResponseInfo();
2372 ASSERT_FALSE(response == NULL);
2373
2374 EXPECT_TRUE(response->headers->IsKeepAlive());
2375 EXPECT_EQ(200, response->headers->response_code());
2376 EXPECT_EQ(100, response->headers->GetContentLength());
2377 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2378
2379 // The password prompt info should not be set.
2380 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2381}
2382
[email protected]ff007e162009-05-23 09:13:152383void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082384 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422385 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082386 request.method = "GET";
2387 request.url = GURL("https://www.google.com/");
2388 request.load_flags = 0;
2389
[email protected]cb9bf6ca2011-01-28 13:15:272390 // Configure against proxy server "myproxy:70".
2391 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2392
2393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2394
[email protected]c744cf22009-02-27 07:28:082395 // Since we have proxy, should try to establish tunnel.
2396 MockWrite data_writes[] = {
2397 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452398 "Host: www.google.com\r\n"
2399 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082400 };
2401
2402 MockRead data_reads[] = {
2403 status,
2404 MockRead("Content-Length: 10\r\n\r\n"),
2405 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422406 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082407 };
2408
[email protected]31a2bfe2010-02-09 08:03:392409 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2410 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592411 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082412
2413 TestCompletionCallback callback;
2414
[email protected]0b0bf032010-09-21 18:08:502415 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2416
[email protected]5a1d7ca2010-04-28 20:12:272417 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422418 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082419
2420 rv = callback.WaitForResult();
2421 EXPECT_EQ(expected_status, rv);
2422}
2423
[email protected]ff007e162009-05-23 09:13:152424void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082425 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422426 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082427}
2428
2429TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2430 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2431}
2432
2433TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2434 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2435}
2436
2437TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2438 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2439}
2440
2441TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2442 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2443}
2444
2445TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2446 ConnectStatusHelper(
2447 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2448}
2449
2450TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2451 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2452}
2453
2454TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2455 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2456}
2457
2458TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2459 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2460}
2461
2462TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2463 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2464}
2465
2466TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2467 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2468}
2469
2470TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2471 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2472}
2473
2474TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2475 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2476}
2477
2478TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2479 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2480}
2481
2482TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2483 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2484}
2485
2486TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2487 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2488}
2489
2490TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2491 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2492}
2493
2494TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2495 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2496}
2497
2498TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2499 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2500}
2501
2502TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2503 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2504}
2505
2506TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2507 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2508}
2509
2510TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2511 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2512}
2513
2514TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2515 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2516}
2517
2518TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2519 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2520}
2521
2522TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2523 ConnectStatusHelperWithExpectedStatus(
2524 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542525 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082526}
2527
2528TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2529 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2530}
2531
2532TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2533 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2534}
2535
2536TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2537 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2538}
2539
2540TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2541 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2542}
2543
2544TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2545 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2546}
2547
2548TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2549 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2550}
2551
2552TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2553 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2554}
2555
2556TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2557 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2558}
2559
2560TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2561 ConnectStatusHelper(
2562 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2563}
2564
2565TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2566 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2567}
2568
2569TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2570 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2571}
2572
2573TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2574 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2575}
2576
2577TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2578 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2579}
2580
2581TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2582 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2586 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2590 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2591}
2592
[email protected]038e9a32008-10-08 22:40:162593// Test the flow when both the proxy server AND origin server require
2594// authentication. Again, this uses basic auth for both since that is
2595// the simplest to mock.
2596TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272597 HttpRequestInfo request;
2598 request.method = "GET";
2599 request.url = GURL("http://www.google.com/");
2600 request.load_flags = 0;
2601
[email protected]81cdfcd2010-10-16 00:49:002602 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012603
[email protected]038e9a32008-10-08 22:40:162604 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422605 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432606 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162607
[email protected]f9ee6b52008-11-08 06:46:232608 MockWrite data_writes1[] = {
2609 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2610 "Host: www.google.com\r\n"
2611 "Proxy-Connection: keep-alive\r\n\r\n"),
2612 };
2613
[email protected]038e9a32008-10-08 22:40:162614 MockRead data_reads1[] = {
2615 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2616 // Give a couple authenticate options (only the middle one is actually
2617 // supported).
[email protected]22927ad2009-09-21 19:56:192618 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2620 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2622 // Large content-length -- won't matter, as connection will be reset.
2623 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422624 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162625 };
2626
2627 // After calling trans->RestartWithAuth() the first time, this is the
2628 // request we should be issuing -- the final header line contains the
2629 // proxy's credentials.
2630 MockWrite data_writes2[] = {
2631 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2632 "Host: www.google.com\r\n"
2633 "Proxy-Connection: keep-alive\r\n"
2634 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2635 };
2636
2637 // Now the proxy server lets the request pass through to origin server.
2638 // The origin server responds with a 401.
2639 MockRead data_reads2[] = {
2640 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2641 // Note: We are using the same realm-name as the proxy server. This is
2642 // completely valid, as realms are unique across hosts.
2643 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2644 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2645 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422646 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162647 };
2648
2649 // After calling trans->RestartWithAuth() the second time, we should send
2650 // the credentials for both the proxy and origin server.
2651 MockWrite data_writes3[] = {
2652 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2653 "Host: www.google.com\r\n"
2654 "Proxy-Connection: keep-alive\r\n"
2655 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2656 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2657 };
2658
2659 // Lastly we get the desired content.
2660 MockRead data_reads3[] = {
2661 MockRead("HTTP/1.0 200 OK\r\n"),
2662 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2663 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422664 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162665 };
2666
[email protected]31a2bfe2010-02-09 08:03:392667 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2668 data_writes1, arraysize(data_writes1));
2669 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2670 data_writes2, arraysize(data_writes2));
2671 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2672 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592673 session_deps.socket_factory.AddSocketDataProvider(&data1);
2674 session_deps.socket_factory.AddSocketDataProvider(&data2);
2675 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162676
2677 TestCompletionCallback callback1;
2678
[email protected]5a1d7ca2010-04-28 20:12:272679 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422680 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162681
2682 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422683 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162684
[email protected]1c773ea12009-04-28 19:58:422685 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162686 EXPECT_FALSE(response == NULL);
2687
2688 // The password prompt info should have been set in response->auth_challenge.
2689 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2690
[email protected]71e4573a2009-05-21 22:03:002691 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162692 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2693 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2694
2695 TestCompletionCallback callback2;
2696
[email protected]13c8a092010-07-29 06:15:442697 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422698 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162699
2700 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422701 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162702
2703 response = trans->GetResponseInfo();
2704 EXPECT_FALSE(response == NULL);
2705 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2706
[email protected]71e4573a2009-05-21 22:03:002707 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162708 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2709 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2710
2711 TestCompletionCallback callback3;
2712
[email protected]13c8a092010-07-29 06:15:442713 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162715
2716 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422717 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162718
2719 response = trans->GetResponseInfo();
2720 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2721 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162722}
[email protected]4ddaf2502008-10-23 18:26:192723
[email protected]ea9dc9a2009-09-05 00:43:322724// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2725// can't hook into its internals to cause it to generate predictable NTLM
2726// authorization headers.
2727#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292728// The NTLM authentication unit tests were generated by capturing the HTTP
2729// requests and responses using Fiddler 2 and inspecting the generated random
2730// bytes in the debugger.
2731
2732// Enter the correct password and authenticate successfully.
2733TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422734 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242735 request.method = "GET";
2736 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2737 request.load_flags = 0;
2738
[email protected]cb9bf6ca2011-01-28 13:15:272739 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2740 MockGetHostName);
2741 SessionDependencies session_deps;
2742 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2743
[email protected]3f918782009-02-28 01:29:242744 MockWrite data_writes1[] = {
2745 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2746 "Host: 172.22.68.17\r\n"
2747 "Connection: keep-alive\r\n\r\n"),
2748 };
2749
2750 MockRead data_reads1[] = {
2751 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042752 // Negotiate and NTLM are often requested together. However, we only want
2753 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2754 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242755 MockRead("WWW-Authenticate: NTLM\r\n"),
2756 MockRead("Connection: close\r\n"),
2757 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362758 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242759 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422760 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242761 };
2762
2763 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222764 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242765 // request we should be issuing -- the final header line contains a Type
2766 // 1 message.
2767 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2768 "Host: 172.22.68.17\r\n"
2769 "Connection: keep-alive\r\n"
2770 "Authorization: NTLM "
2771 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2772
2773 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2774 // (the credentials for the origin server). The second request continues
2775 // on the same connection.
2776 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2777 "Host: 172.22.68.17\r\n"
2778 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292779 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2780 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2781 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2782 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2783 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242784 };
2785
2786 MockRead data_reads2[] = {
2787 // The origin server responds with a Type 2 message.
2788 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2789 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292790 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242791 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2792 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2793 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2794 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2795 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2796 "BtAAAAAAA=\r\n"),
2797 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362798 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242799 MockRead("You are not authorized to view this page\r\n"),
2800
2801 // Lastly we get the desired content.
2802 MockRead("HTTP/1.1 200 OK\r\n"),
2803 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2804 MockRead("Content-Length: 13\r\n\r\n"),
2805 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422806 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242807 };
2808
[email protected]31a2bfe2010-02-09 08:03:392809 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2810 data_writes1, arraysize(data_writes1));
2811 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2812 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592813 session_deps.socket_factory.AddSocketDataProvider(&data1);
2814 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242815
2816 TestCompletionCallback callback1;
2817
[email protected]0b0bf032010-09-21 18:08:502818 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2819
[email protected]5a1d7ca2010-04-28 20:12:272820 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422821 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242822
2823 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422824 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242825
[email protected]0757e7702009-03-27 04:00:222826 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2827
[email protected]1c773ea12009-04-28 19:58:422828 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:252829 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:242830
[email protected]aef04272010-06-28 18:03:042831 // The password prompt info should have been set in
2832 // response->auth_challenge.
[email protected]10af5fe72011-01-31 16:17:252833 ASSERT_FALSE(response->auth_challenge.get() == NULL);
[email protected]3f918782009-02-28 01:29:242834
[email protected]71e4573a2009-05-21 22:03:002835 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242836 EXPECT_EQ(L"", response->auth_challenge->realm);
2837 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2838
[email protected]10af5fe72011-01-31 16:17:252839 TestCompletionCallback callback2;
2840
2841 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2842 EXPECT_EQ(ERR_IO_PENDING, rv);
2843
2844 rv = callback2.WaitForResult();
2845 EXPECT_EQ(OK, rv);
2846
2847 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2848
2849 response = trans->GetResponseInfo();
2850 ASSERT_TRUE(response != NULL);
2851
2852 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2853
[email protected]0757e7702009-03-27 04:00:222854 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242855
[email protected]10af5fe72011-01-31 16:17:252856 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422857 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242858
[email protected]0757e7702009-03-27 04:00:222859 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422860 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242861
2862 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042863 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242864 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2865 EXPECT_EQ(13, response->headers->GetContentLength());
2866}
2867
[email protected]385a4672009-03-11 22:21:292868// Enter a wrong password, and then the correct one.
2869TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422870 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292871 request.method = "GET";
2872 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2873 request.load_flags = 0;
2874
[email protected]cb9bf6ca2011-01-28 13:15:272875 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2876 MockGetHostName);
2877 SessionDependencies session_deps;
2878 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2879
[email protected]385a4672009-03-11 22:21:292880 MockWrite data_writes1[] = {
2881 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2882 "Host: 172.22.68.17\r\n"
2883 "Connection: keep-alive\r\n\r\n"),
2884 };
2885
2886 MockRead data_reads1[] = {
2887 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042888 // Negotiate and NTLM are often requested together. However, we only want
2889 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2890 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292891 MockRead("WWW-Authenticate: NTLM\r\n"),
2892 MockRead("Connection: close\r\n"),
2893 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362894 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292895 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422896 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292897 };
2898
2899 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222900 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292901 // request we should be issuing -- the final header line contains a Type
2902 // 1 message.
2903 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2904 "Host: 172.22.68.17\r\n"
2905 "Connection: keep-alive\r\n"
2906 "Authorization: NTLM "
2907 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2908
2909 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2910 // (the credentials for the origin server). The second request continues
2911 // on the same connection.
2912 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2913 "Host: 172.22.68.17\r\n"
2914 "Connection: keep-alive\r\n"
2915 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2916 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2917 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2918 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2919 "4Ww7b7E=\r\n\r\n"),
2920 };
2921
2922 MockRead data_reads2[] = {
2923 // The origin server responds with a Type 2 message.
2924 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2925 MockRead("WWW-Authenticate: NTLM "
2926 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2927 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2928 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2929 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2930 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2931 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2932 "BtAAAAAAA=\r\n"),
2933 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362934 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292935 MockRead("You are not authorized to view this page\r\n"),
2936
2937 // Wrong password.
2938 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292939 MockRead("WWW-Authenticate: NTLM\r\n"),
2940 MockRead("Connection: close\r\n"),
2941 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362942 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292943 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422944 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292945 };
2946
2947 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222948 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292949 // request we should be issuing -- the final header line contains a Type
2950 // 1 message.
2951 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2952 "Host: 172.22.68.17\r\n"
2953 "Connection: keep-alive\r\n"
2954 "Authorization: NTLM "
2955 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2956
2957 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2958 // (the credentials for the origin server). The second request continues
2959 // on the same connection.
2960 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2961 "Host: 172.22.68.17\r\n"
2962 "Connection: keep-alive\r\n"
2963 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2964 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2965 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2966 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2967 "+4MUm7c=\r\n\r\n"),
2968 };
2969
2970 MockRead data_reads3[] = {
2971 // The origin server responds with a Type 2 message.
2972 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2973 MockRead("WWW-Authenticate: NTLM "
2974 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2975 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2976 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2977 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2978 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2979 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2980 "BtAAAAAAA=\r\n"),
2981 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362982 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292983 MockRead("You are not authorized to view this page\r\n"),
2984
2985 // Lastly we get the desired content.
2986 MockRead("HTTP/1.1 200 OK\r\n"),
2987 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2988 MockRead("Content-Length: 13\r\n\r\n"),
2989 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422990 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292991 };
2992
[email protected]31a2bfe2010-02-09 08:03:392993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2994 data_writes1, arraysize(data_writes1));
2995 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2996 data_writes2, arraysize(data_writes2));
2997 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2998 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592999 session_deps.socket_factory.AddSocketDataProvider(&data1);
3000 session_deps.socket_factory.AddSocketDataProvider(&data2);
3001 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293002
3003 TestCompletionCallback callback1;
3004
[email protected]0b0bf032010-09-21 18:08:503005 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3006
[email protected]5a1d7ca2010-04-28 20:12:273007 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423008 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293009
3010 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423011 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293012
[email protected]0757e7702009-03-27 04:00:223013 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293014
[email protected]1c773ea12009-04-28 19:58:423015 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293016 EXPECT_FALSE(response == NULL);
3017
3018 // The password prompt info should have been set in response->auth_challenge.
3019 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3020
[email protected]71e4573a2009-05-21 22:03:003021 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293022 EXPECT_EQ(L"", response->auth_challenge->realm);
3023 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3024
[email protected]10af5fe72011-01-31 16:17:253025 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293026
[email protected]0757e7702009-03-27 04:00:223027 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253028 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423029 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293030
[email protected]10af5fe72011-01-31 16:17:253031 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423032 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293033
[email protected]0757e7702009-03-27 04:00:223034 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:253035 TestCompletionCallback callback3;
3036 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423037 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253038 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423039 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223040 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3041
3042 response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:253043 ASSERT_TRUE(response != NULL);
[email protected]0757e7702009-03-27 04:00:223044
3045 // The password prompt info should have been set in response->auth_challenge.
3046 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3047
[email protected]71e4573a2009-05-21 22:03:003048 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223049 EXPECT_EQ(L"", response->auth_challenge->realm);
3050 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3051
[email protected]10af5fe72011-01-31 16:17:253052 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223053
3054 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253055 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3056 EXPECT_EQ(ERR_IO_PENDING, rv);
3057
3058 rv = callback4.WaitForResult();
3059 EXPECT_EQ(OK, rv);
3060
3061 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3062
3063 TestCompletionCallback callback5;
3064
3065 // One more roundtrip
3066 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423067 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223068
3069 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423070 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223071
[email protected]385a4672009-03-11 22:21:293072 response = trans->GetResponseInfo();
3073 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3074 EXPECT_EQ(13, response->headers->GetContentLength());
3075}
[email protected]ea9dc9a2009-09-05 00:43:323076#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293077
[email protected]4ddaf2502008-10-23 18:26:193078// Test reading a server response which has only headers, and no body.
3079// After some maximum number of bytes is consumed, the transaction should
3080// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3081TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423082 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193083 request.method = "GET";
3084 request.url = GURL("http://www.google.com/");
3085 request.load_flags = 0;
3086
[email protected]cb9bf6ca2011-01-28 13:15:273087 SessionDependencies session_deps;
3088 scoped_ptr<HttpTransaction> trans(
3089 new HttpNetworkTransaction(CreateSession(&session_deps)));
3090
[email protected]b75b7b2f2009-10-06 00:54:533091 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433092 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533093 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193094
3095 MockRead data_reads[] = {
3096 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433097 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193098 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423099 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193100 };
[email protected]31a2bfe2010-02-09 08:03:393101 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593102 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193103
3104 TestCompletionCallback callback;
3105
[email protected]5a1d7ca2010-04-28 20:12:273106 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193108
3109 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423110 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193111
[email protected]1c773ea12009-04-28 19:58:423112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193113 EXPECT_TRUE(response == NULL);
3114}
[email protected]f4e426b2008-11-05 00:24:493115
3116// Make sure that we don't try to reuse a TCPClientSocket when failing to
3117// establish tunnel.
3118// http://code.google.com/p/chromium/issues/detail?id=3772
3119TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273120 HttpRequestInfo request;
3121 request.method = "GET";
3122 request.url = GURL("https://www.google.com/");
3123 request.load_flags = 0;
3124
[email protected]f4e426b2008-11-05 00:24:493125 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003126 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013127
[email protected]228ff742009-06-05 01:19:593128 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493129
[email protected]5695b8c2009-09-30 21:36:433130 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493131
[email protected]f4e426b2008-11-05 00:24:493132 // Since we have proxy, should try to establish tunnel.
3133 MockWrite data_writes1[] = {
3134 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453135 "Host: www.google.com\r\n"
3136 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493137 };
3138
[email protected]77848d12008-11-14 00:00:223139 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493140 // connection. Usually a proxy would return 501 (not implemented),
3141 // or 200 (tunnel established).
3142 MockRead data_reads1[] = {
3143 MockRead("HTTP/1.1 404 Not Found\r\n"),
3144 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423145 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493146 };
3147
[email protected]31a2bfe2010-02-09 08:03:393148 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3149 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593150 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493151
3152 TestCompletionCallback callback1;
3153
[email protected]5a1d7ca2010-04-28 20:12:273154 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423155 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493156
3157 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423158 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493159
[email protected]1c773ea12009-04-28 19:58:423160 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083161 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493162
[email protected]b4404c02009-04-10 16:38:523163 // Empty the current queue. This is necessary because idle sockets are
3164 // added to the connection pool asynchronously with a PostTask.
3165 MessageLoop::current()->RunAllPending();
3166
[email protected]f4e426b2008-11-05 00:24:493167 // We now check to make sure the TCPClientSocket was not added back to
3168 // the pool.
[email protected]a937a06d2009-08-19 21:19:243169 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493170 trans.reset();
[email protected]b4404c02009-04-10 16:38:523171 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493172 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:243173 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493174}
[email protected]372d34a2008-11-05 21:30:513175
[email protected]1b157c02009-04-21 01:55:403176// Make sure that we recycle a socket after reading all of the response body.
3177TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423178 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403179 request.method = "GET";
3180 request.url = GURL("http://www.google.com/");
3181 request.load_flags = 0;
3182
[email protected]cb9bf6ca2011-01-28 13:15:273183 SessionDependencies session_deps;
3184 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3185
3186 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3187
[email protected]1b157c02009-04-21 01:55:403188 MockRead data_reads[] = {
3189 // A part of the response body is received with the response headers.
3190 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3191 // The rest of the response body is received in two parts.
3192 MockRead("lo"),
3193 MockRead(" world"),
3194 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423195 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403196 };
3197
[email protected]31a2bfe2010-02-09 08:03:393198 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593199 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403200
3201 TestCompletionCallback callback;
3202
[email protected]5a1d7ca2010-04-28 20:12:273203 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423204 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403205
3206 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423207 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403208
[email protected]1c773ea12009-04-28 19:58:423209 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403210 EXPECT_TRUE(response != NULL);
3211
3212 EXPECT_TRUE(response->headers != NULL);
3213 std::string status_line = response->headers->GetStatusLine();
3214 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3215
[email protected]a937a06d2009-08-19 21:19:243216 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403217
3218 std::string response_data;
3219 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423220 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403221 EXPECT_EQ("hello world", response_data);
3222
3223 // Empty the current queue. This is necessary because idle sockets are
3224 // added to the connection pool asynchronously with a PostTask.
3225 MessageLoop::current()->RunAllPending();
3226
3227 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243228 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403229}
3230
[email protected]76a505b2010-08-25 06:23:003231// Make sure that we recycle a SSL socket after reading all of the response
3232// body.
3233TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3234 SessionDependencies session_deps;
3235 HttpRequestInfo request;
3236 request.method = "GET";
3237 request.url = GURL("https://www.google.com/");
3238 request.load_flags = 0;
3239
3240 MockWrite data_writes[] = {
3241 MockWrite("GET / HTTP/1.1\r\n"
3242 "Host: www.google.com\r\n"
3243 "Connection: keep-alive\r\n\r\n"),
3244 };
3245
3246 MockRead data_reads[] = {
3247 MockRead("HTTP/1.1 200 OK\r\n"),
3248 MockRead("Content-Length: 11\r\n\r\n"),
3249 MockRead("hello world"),
3250 MockRead(false, OK),
3251 };
3252
3253 SSLSocketDataProvider ssl(true, OK);
3254 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3255
3256 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3257 data_writes, arraysize(data_writes));
3258 session_deps.socket_factory.AddSocketDataProvider(&data);
3259
3260 TestCompletionCallback callback;
3261
3262 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3263 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3264
3265 int rv = trans->Start(&request, &callback, BoundNetLog());
3266
3267 EXPECT_EQ(ERR_IO_PENDING, rv);
3268 EXPECT_EQ(OK, callback.WaitForResult());
3269
3270 const HttpResponseInfo* response = trans->GetResponseInfo();
3271 ASSERT_TRUE(response != NULL);
3272 ASSERT_TRUE(response->headers != NULL);
3273 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3274
3275 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3276
3277 std::string response_data;
3278 rv = ReadTransaction(trans.get(), &response_data);
3279 EXPECT_EQ(OK, rv);
3280 EXPECT_EQ("hello world", response_data);
3281
3282 // Empty the current queue. This is necessary because idle sockets are
3283 // added to the connection pool asynchronously with a PostTask.
3284 MessageLoop::current()->RunAllPending();
3285
3286 // We now check to make sure the socket was added back to the pool.
3287 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3288}
3289
3290// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3291// from the pool and make sure that we recover okay.
3292TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3293 SessionDependencies session_deps;
3294 HttpRequestInfo request;
3295 request.method = "GET";
3296 request.url = GURL("https://www.google.com/");
3297 request.load_flags = 0;
3298
3299 MockWrite data_writes[] = {
3300 MockWrite("GET / HTTP/1.1\r\n"
3301 "Host: www.google.com\r\n"
3302 "Connection: keep-alive\r\n\r\n"),
3303 MockWrite("GET / HTTP/1.1\r\n"
3304 "Host: www.google.com\r\n"
3305 "Connection: keep-alive\r\n\r\n"),
3306 };
3307
3308 MockRead data_reads[] = {
3309 MockRead("HTTP/1.1 200 OK\r\n"),
3310 MockRead("Content-Length: 11\r\n\r\n"),
3311 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3312 MockRead("hello world"),
3313 MockRead(true, 0, 0) // EOF
3314 };
3315
3316 SSLSocketDataProvider ssl(true, OK);
3317 SSLSocketDataProvider ssl2(true, OK);
3318 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3319 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3320
3321 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3322 data_writes, arraysize(data_writes));
3323 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3324 data_writes, arraysize(data_writes));
3325 session_deps.socket_factory.AddSocketDataProvider(&data);
3326 session_deps.socket_factory.AddSocketDataProvider(&data2);
3327
3328 TestCompletionCallback callback;
3329
3330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3331 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3332
3333 int rv = trans->Start(&request, &callback, BoundNetLog());
3334
3335 EXPECT_EQ(ERR_IO_PENDING, rv);
3336 EXPECT_EQ(OK, callback.WaitForResult());
3337
3338 const HttpResponseInfo* response = trans->GetResponseInfo();
3339 ASSERT_TRUE(response != NULL);
3340 ASSERT_TRUE(response->headers != NULL);
3341 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3342
3343 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3344
3345 std::string response_data;
3346 rv = ReadTransaction(trans.get(), &response_data);
3347 EXPECT_EQ(OK, rv);
3348 EXPECT_EQ("hello world", response_data);
3349
3350 // Empty the current queue. This is necessary because idle sockets are
3351 // added to the connection pool asynchronously with a PostTask.
3352 MessageLoop::current()->RunAllPending();
3353
3354 // We now check to make sure the socket was added back to the pool.
3355 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3356
3357 // Now start the second transaction, which should reuse the previous socket.
3358
3359 trans.reset(new HttpNetworkTransaction(session));
3360
3361 rv = trans->Start(&request, &callback, BoundNetLog());
3362
3363 EXPECT_EQ(ERR_IO_PENDING, rv);
3364 EXPECT_EQ(OK, callback.WaitForResult());
3365
3366 response = trans->GetResponseInfo();
3367 ASSERT_TRUE(response != NULL);
3368 ASSERT_TRUE(response->headers != NULL);
3369 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3370
3371 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3372
3373 rv = ReadTransaction(trans.get(), &response_data);
3374 EXPECT_EQ(OK, rv);
3375 EXPECT_EQ("hello world", response_data);
3376
3377 // Empty the current queue. This is necessary because idle sockets are
3378 // added to the connection pool asynchronously with a PostTask.
3379 MessageLoop::current()->RunAllPending();
3380
3381 // We now check to make sure the socket was added back to the pool.
3382 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3383}
3384
[email protected]b4404c02009-04-10 16:38:523385// Make sure that we recycle a socket after a zero-length response.
3386// http://crbug.com/9880
3387TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423388 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523389 request.method = "GET";
3390 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3391 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3392 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3393 "rt=prt.2642,ol.2649,xjs.2951");
3394 request.load_flags = 0;
3395
[email protected]cb9bf6ca2011-01-28 13:15:273396 SessionDependencies session_deps;
3397 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3398
3399 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3400
[email protected]b4404c02009-04-10 16:38:523401 MockRead data_reads[] = {
3402 MockRead("HTTP/1.1 204 No Content\r\n"
3403 "Content-Length: 0\r\n"
3404 "Content-Type: text/html\r\n\r\n"),
3405 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423406 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523407 };
3408
[email protected]31a2bfe2010-02-09 08:03:393409 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593410 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523411
3412 TestCompletionCallback callback;
3413
[email protected]5a1d7ca2010-04-28 20:12:273414 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423415 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523416
3417 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423418 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523419
[email protected]1c773ea12009-04-28 19:58:423420 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523421 EXPECT_TRUE(response != NULL);
3422
3423 EXPECT_TRUE(response->headers != NULL);
3424 std::string status_line = response->headers->GetStatusLine();
3425 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3426
[email protected]a937a06d2009-08-19 21:19:243427 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523428
3429 std::string response_data;
3430 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423431 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523432 EXPECT_EQ("", response_data);
3433
3434 // Empty the current queue. This is necessary because idle sockets are
3435 // added to the connection pool asynchronously with a PostTask.
3436 MessageLoop::current()->RunAllPending();
3437
3438 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243439 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523440}
3441
[email protected]372d34a2008-11-05 21:30:513442TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423443 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513444 // Transaction 1: a GET request that succeeds. The socket is recycled
3445 // after use.
3446 request[0].method = "GET";
3447 request[0].url = GURL("http://www.google.com/");
3448 request[0].load_flags = 0;
3449 // Transaction 2: a POST request. Reuses the socket kept alive from
3450 // transaction 1. The first attempts fails when writing the POST data.
3451 // This causes the transaction to retry with a new socket. The second
3452 // attempt succeeds.
3453 request[1].method = "POST";
3454 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423455 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513456 request[1].upload_data->AppendBytes("foo", 3);
3457 request[1].load_flags = 0;
3458
[email protected]228ff742009-06-05 01:19:593459 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273460 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513461
3462 // The first socket is used for transaction 1 and the first attempt of
3463 // transaction 2.
3464
3465 // The response of transaction 1.
3466 MockRead data_reads1[] = {
3467 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3468 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423469 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513470 };
3471 // The mock write results of transaction 1 and the first attempt of
3472 // transaction 2.
3473 MockWrite data_writes1[] = {
3474 MockWrite(false, 64), // GET
3475 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423476 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513477 };
[email protected]31a2bfe2010-02-09 08:03:393478 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3479 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513480
3481 // The second socket is used for the second attempt of transaction 2.
3482
3483 // The response of transaction 2.
3484 MockRead data_reads2[] = {
3485 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3486 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423487 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513488 };
3489 // The mock write results of the second attempt of transaction 2.
3490 MockWrite data_writes2[] = {
3491 MockWrite(false, 93), // POST
3492 MockWrite(false, 3), // POST data
3493 };
[email protected]31a2bfe2010-02-09 08:03:393494 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3495 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513496
[email protected]5ecc992a42009-11-11 01:41:593497 session_deps.socket_factory.AddSocketDataProvider(&data1);
3498 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513499
3500 const char* kExpectedResponseData[] = {
3501 "hello world", "welcome"
3502 };
3503
3504 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423505 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433506 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513507
3508 TestCompletionCallback callback;
3509
[email protected]5a1d7ca2010-04-28 20:12:273510 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423511 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513512
3513 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423514 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513515
[email protected]1c773ea12009-04-28 19:58:423516 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513517 EXPECT_TRUE(response != NULL);
3518
3519 EXPECT_TRUE(response->headers != NULL);
3520 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3521
3522 std::string response_data;
3523 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423524 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513525 EXPECT_EQ(kExpectedResponseData[i], response_data);
3526 }
3527}
[email protected]f9ee6b52008-11-08 06:46:233528
3529// Test the request-challenge-retry sequence for basic auth when there is
3530// an identity in the URL. The request should be sent as normal, but when
3531// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323532TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423533 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233534 request.method = "GET";
3535 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293536 request.url = GURL("http://foo:b@[email protected]/");
3537
[email protected]cb9bf6ca2011-01-28 13:15:273538 SessionDependencies session_deps;
3539 scoped_ptr<HttpTransaction> trans(
3540 new HttpNetworkTransaction(CreateSession(&session_deps)));
3541
[email protected]a97cca42009-08-14 01:00:293542 // The password contains an escaped character -- for this test to pass it
3543 // will need to be unescaped by HttpNetworkTransaction.
3544 EXPECT_EQ("b%40r", request.url.password());
3545
[email protected]ea9dc9a2009-09-05 00:43:323546 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233547
3548 MockWrite data_writes1[] = {
3549 MockWrite("GET / HTTP/1.1\r\n"
3550 "Host: www.google.com\r\n"
3551 "Connection: keep-alive\r\n\r\n"),
3552 };
3553
3554 MockRead data_reads1[] = {
3555 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3556 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3557 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423558 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233559 };
3560
3561 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323562 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233563 MockWrite data_writes2[] = {
3564 MockWrite("GET / HTTP/1.1\r\n"
3565 "Host: www.google.com\r\n"
3566 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293567 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233568 };
3569
3570 MockRead data_reads2[] = {
3571 MockRead("HTTP/1.0 200 OK\r\n"),
3572 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423573 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233574 };
3575
[email protected]31a2bfe2010-02-09 08:03:393576 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3577 data_writes1, arraysize(data_writes1));
3578 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3579 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593580 session_deps.socket_factory.AddSocketDataProvider(&data1);
3581 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233582
3583 TestCompletionCallback callback1;
3584
[email protected]5a1d7ca2010-04-28 20:12:273585 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423586 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233587
3588 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423589 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233590
[email protected]0757e7702009-03-27 04:00:223591 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3592 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443593 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423594 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223595 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423596 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223597 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3598
[email protected]1c773ea12009-04-28 19:58:423599 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233600 EXPECT_FALSE(response == NULL);
3601
3602 // There is no challenge info, since the identity in URL worked.
3603 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3604
3605 EXPECT_EQ(100, response->headers->GetContentLength());
3606
3607 // Empty the current queue.
3608 MessageLoop::current()->RunAllPending();
3609}
3610
[email protected]ea9dc9a2009-09-05 00:43:323611// Test the request-challenge-retry sequence for basic auth when there is
3612// an incorrect identity in the URL. The identity from the URL should be used
3613// only once.
3614TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323615 HttpRequestInfo request;
3616 request.method = "GET";
3617 // Note: the URL has a username:password in it. The password "baz" is
3618 // wrong (should be "bar").
3619 request.url = GURL("http://foo:[email protected]/");
3620
3621 request.load_flags = LOAD_NORMAL;
3622
[email protected]cb9bf6ca2011-01-28 13:15:273623 SessionDependencies session_deps;
3624 scoped_ptr<HttpTransaction> trans(
3625 new HttpNetworkTransaction(CreateSession(&session_deps)));
3626
[email protected]ea9dc9a2009-09-05 00:43:323627 MockWrite data_writes1[] = {
3628 MockWrite("GET / HTTP/1.1\r\n"
3629 "Host: www.google.com\r\n"
3630 "Connection: keep-alive\r\n\r\n"),
3631 };
3632
3633 MockRead data_reads1[] = {
3634 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3635 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3636 MockRead("Content-Length: 10\r\n\r\n"),
3637 MockRead(false, ERR_FAILED),
3638 };
3639
3640 // After the challenge above, the transaction will be restarted using the
3641 // identity from the url (foo, baz) to answer the challenge.
3642 MockWrite data_writes2[] = {
3643 MockWrite("GET / HTTP/1.1\r\n"
3644 "Host: www.google.com\r\n"
3645 "Connection: keep-alive\r\n"
3646 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3647 };
3648
3649 MockRead data_reads2[] = {
3650 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3651 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3652 MockRead("Content-Length: 10\r\n\r\n"),
3653 MockRead(false, ERR_FAILED),
3654 };
3655
3656 // After the challenge above, the transaction will be restarted using the
3657 // identity supplied by the user (foo, bar) to answer the challenge.
3658 MockWrite data_writes3[] = {
3659 MockWrite("GET / HTTP/1.1\r\n"
3660 "Host: www.google.com\r\n"
3661 "Connection: keep-alive\r\n"
3662 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3663 };
3664
3665 MockRead data_reads3[] = {
3666 MockRead("HTTP/1.0 200 OK\r\n"),
3667 MockRead("Content-Length: 100\r\n\r\n"),
3668 MockRead(false, OK),
3669 };
3670
[email protected]31a2bfe2010-02-09 08:03:393671 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3672 data_writes1, arraysize(data_writes1));
3673 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3674 data_writes2, arraysize(data_writes2));
3675 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3676 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593677 session_deps.socket_factory.AddSocketDataProvider(&data1);
3678 session_deps.socket_factory.AddSocketDataProvider(&data2);
3679 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323680
3681 TestCompletionCallback callback1;
3682
[email protected]5a1d7ca2010-04-28 20:12:273683 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323684 EXPECT_EQ(ERR_IO_PENDING, rv);
3685
3686 rv = callback1.WaitForResult();
3687 EXPECT_EQ(OK, rv);
3688
3689 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3690 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443691 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323692 EXPECT_EQ(ERR_IO_PENDING, rv);
3693 rv = callback2.WaitForResult();
3694 EXPECT_EQ(OK, rv);
3695 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3696
3697 const HttpResponseInfo* response = trans->GetResponseInfo();
3698 EXPECT_FALSE(response == NULL);
3699 // The password prompt info should have been set in response->auth_challenge.
3700 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3701
3702 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3703 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3704 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3705
3706 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443707 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323708 EXPECT_EQ(ERR_IO_PENDING, rv);
3709 rv = callback3.WaitForResult();
3710 EXPECT_EQ(OK, rv);
3711 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3712
3713 response = trans->GetResponseInfo();
3714 EXPECT_FALSE(response == NULL);
3715
3716 // There is no challenge info, since the identity worked.
3717 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3718
3719 EXPECT_EQ(100, response->headers->GetContentLength());
3720
3721 // Empty the current queue.
3722 MessageLoop::current()->RunAllPending();
3723}
3724
[email protected]f9ee6b52008-11-08 06:46:233725// Test that previously tried username/passwords for a realm get re-used.
3726TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593727 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273728 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233729
3730 // Transaction 1: authenticate (foo, bar) on MyRealm1
3731 {
[email protected]1c773ea12009-04-28 19:58:423732 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233733 request.method = "GET";
3734 request.url = GURL("http://www.google.com/x/y/z");
3735 request.load_flags = 0;
3736
[email protected]cb9bf6ca2011-01-28 13:15:273737 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3738
[email protected]f9ee6b52008-11-08 06:46:233739 MockWrite data_writes1[] = {
3740 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3741 "Host: www.google.com\r\n"
3742 "Connection: keep-alive\r\n\r\n"),
3743 };
3744
3745 MockRead data_reads1[] = {
3746 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3747 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3748 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423749 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233750 };
3751
3752 // Resend with authorization (username=foo, password=bar)
3753 MockWrite data_writes2[] = {
3754 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3755 "Host: www.google.com\r\n"
3756 "Connection: keep-alive\r\n"
3757 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3758 };
3759
3760 // Sever accepts the authorization.
3761 MockRead data_reads2[] = {
3762 MockRead("HTTP/1.0 200 OK\r\n"),
3763 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423764 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233765 };
3766
[email protected]31a2bfe2010-02-09 08:03:393767 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3768 data_writes1, arraysize(data_writes1));
3769 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3770 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593771 session_deps.socket_factory.AddSocketDataProvider(&data1);
3772 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233773
3774 TestCompletionCallback callback1;
3775
[email protected]5a1d7ca2010-04-28 20:12:273776 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423777 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233778
3779 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423780 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233781
[email protected]1c773ea12009-04-28 19:58:423782 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233783 EXPECT_FALSE(response == NULL);
3784
3785 // The password prompt info should have been set in
3786 // response->auth_challenge.
3787 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3788
[email protected]71e4573a2009-05-21 22:03:003789 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233790 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3791 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3792
3793 TestCompletionCallback callback2;
3794
[email protected]13c8a092010-07-29 06:15:443795 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423796 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233797
3798 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423799 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233800
3801 response = trans->GetResponseInfo();
3802 EXPECT_FALSE(response == NULL);
3803 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3804 EXPECT_EQ(100, response->headers->GetContentLength());
3805 }
3806
3807 // ------------------------------------------------------------------------
3808
3809 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3810 {
[email protected]1c773ea12009-04-28 19:58:423811 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233812 request.method = "GET";
3813 // Note that Transaction 1 was at /x/y/z, so this is in the same
3814 // protection space as MyRealm1.
3815 request.url = GURL("http://www.google.com/x/y/a/b");
3816 request.load_flags = 0;
3817
[email protected]cb9bf6ca2011-01-28 13:15:273818 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3819
[email protected]f9ee6b52008-11-08 06:46:233820 MockWrite data_writes1[] = {
3821 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3822 "Host: www.google.com\r\n"
3823 "Connection: keep-alive\r\n"
3824 // Send preemptive authorization for MyRealm1
3825 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3826 };
3827
3828 // The server didn't like the preemptive authorization, and
3829 // challenges us for a different realm (MyRealm2).
3830 MockRead data_reads1[] = {
3831 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3832 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3833 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423834 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233835 };
3836
3837 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3838 MockWrite data_writes2[] = {
3839 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3840 "Host: www.google.com\r\n"
3841 "Connection: keep-alive\r\n"
3842 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3843 };
3844
3845 // Sever accepts the authorization.
3846 MockRead data_reads2[] = {
3847 MockRead("HTTP/1.0 200 OK\r\n"),
3848 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423849 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233850 };
3851
[email protected]31a2bfe2010-02-09 08:03:393852 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3853 data_writes1, arraysize(data_writes1));
3854 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3855 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593856 session_deps.socket_factory.AddSocketDataProvider(&data1);
3857 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233858
3859 TestCompletionCallback callback1;
3860
[email protected]5a1d7ca2010-04-28 20:12:273861 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423862 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233863
3864 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423865 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233866
[email protected]1c773ea12009-04-28 19:58:423867 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233868 EXPECT_FALSE(response == NULL);
3869
3870 // The password prompt info should have been set in
3871 // response->auth_challenge.
3872 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3873
[email protected]71e4573a2009-05-21 22:03:003874 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233875 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3876 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3877
3878 TestCompletionCallback callback2;
3879
[email protected]13c8a092010-07-29 06:15:443880 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423881 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233882
3883 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423884 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233885
3886 response = trans->GetResponseInfo();
3887 EXPECT_FALSE(response == NULL);
3888 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3889 EXPECT_EQ(100, response->headers->GetContentLength());
3890 }
3891
3892 // ------------------------------------------------------------------------
3893
3894 // Transaction 3: Resend a request in MyRealm's protection space --
3895 // succeed with preemptive authorization.
3896 {
[email protected]1c773ea12009-04-28 19:58:423897 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233898 request.method = "GET";
3899 request.url = GURL("http://www.google.com/x/y/z2");
3900 request.load_flags = 0;
3901
[email protected]cb9bf6ca2011-01-28 13:15:273902 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3903
[email protected]f9ee6b52008-11-08 06:46:233904 MockWrite data_writes1[] = {
3905 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3906 "Host: www.google.com\r\n"
3907 "Connection: keep-alive\r\n"
3908 // The authorization for MyRealm1 gets sent preemptively
3909 // (since the url is in the same protection space)
3910 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3911 };
3912
3913 // Sever accepts the preemptive authorization
3914 MockRead data_reads1[] = {
3915 MockRead("HTTP/1.0 200 OK\r\n"),
3916 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423917 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233918 };
3919
[email protected]31a2bfe2010-02-09 08:03:393920 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3921 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593922 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233923
3924 TestCompletionCallback callback1;
3925
[email protected]5a1d7ca2010-04-28 20:12:273926 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423927 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233928
3929 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423930 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233931
[email protected]1c773ea12009-04-28 19:58:423932 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233933 EXPECT_FALSE(response == NULL);
3934
3935 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3936 EXPECT_EQ(100, response->headers->GetContentLength());
3937 }
3938
3939 // ------------------------------------------------------------------------
3940
3941 // Transaction 4: request another URL in MyRealm (however the
3942 // url is not known to belong to the protection space, so no pre-auth).
3943 {
[email protected]1c773ea12009-04-28 19:58:423944 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233945 request.method = "GET";
3946 request.url = GURL("http://www.google.com/x/1");
3947 request.load_flags = 0;
3948
[email protected]cb9bf6ca2011-01-28 13:15:273949 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3950
[email protected]f9ee6b52008-11-08 06:46:233951 MockWrite data_writes1[] = {
3952 MockWrite("GET /x/1 HTTP/1.1\r\n"
3953 "Host: www.google.com\r\n"
3954 "Connection: keep-alive\r\n\r\n"),
3955 };
3956
3957 MockRead data_reads1[] = {
3958 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3959 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3960 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423961 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233962 };
3963
3964 // Resend with authorization from MyRealm's cache.
3965 MockWrite data_writes2[] = {
3966 MockWrite("GET /x/1 HTTP/1.1\r\n"
3967 "Host: www.google.com\r\n"
3968 "Connection: keep-alive\r\n"
3969 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3970 };
3971
3972 // Sever accepts the authorization.
3973 MockRead data_reads2[] = {
3974 MockRead("HTTP/1.0 200 OK\r\n"),
3975 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423976 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233977 };
3978
[email protected]31a2bfe2010-02-09 08:03:393979 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3980 data_writes1, arraysize(data_writes1));
3981 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3982 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593983 session_deps.socket_factory.AddSocketDataProvider(&data1);
3984 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233985
3986 TestCompletionCallback callback1;
3987
[email protected]5a1d7ca2010-04-28 20:12:273988 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423989 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233990
3991 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423992 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233993
[email protected]0757e7702009-03-27 04:00:223994 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3995 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443996 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423997 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223998 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423999 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224000 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4001
[email protected]1c773ea12009-04-28 19:58:424002 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234003 EXPECT_FALSE(response == NULL);
4004 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4005 EXPECT_EQ(100, response->headers->GetContentLength());
4006 }
4007
4008 // ------------------------------------------------------------------------
4009
4010 // Transaction 5: request a URL in MyRealm, but the server rejects the
4011 // cached identity. Should invalidate and re-prompt.
4012 {
[email protected]1c773ea12009-04-28 19:58:424013 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234014 request.method = "GET";
4015 request.url = GURL("http://www.google.com/p/q/t");
4016 request.load_flags = 0;
4017
[email protected]cb9bf6ca2011-01-28 13:15:274018 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4019
[email protected]f9ee6b52008-11-08 06:46:234020 MockWrite data_writes1[] = {
4021 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4022 "Host: www.google.com\r\n"
4023 "Connection: keep-alive\r\n\r\n"),
4024 };
4025
4026 MockRead data_reads1[] = {
4027 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4028 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4029 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424030 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234031 };
4032
4033 // Resend with authorization from cache for MyRealm.
4034 MockWrite data_writes2[] = {
4035 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4036 "Host: www.google.com\r\n"
4037 "Connection: keep-alive\r\n"
4038 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4039 };
4040
4041 // Sever rejects the authorization.
4042 MockRead data_reads2[] = {
4043 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4044 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4045 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424046 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234047 };
4048
4049 // At this point we should prompt for new credentials for MyRealm.
4050 // Restart with username=foo3, password=foo4.
4051 MockWrite data_writes3[] = {
4052 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4053 "Host: www.google.com\r\n"
4054 "Connection: keep-alive\r\n"
4055 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4056 };
4057
4058 // Sever accepts the authorization.
4059 MockRead data_reads3[] = {
4060 MockRead("HTTP/1.0 200 OK\r\n"),
4061 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424062 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234063 };
4064
[email protected]31a2bfe2010-02-09 08:03:394065 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4066 data_writes1, arraysize(data_writes1));
4067 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4068 data_writes2, arraysize(data_writes2));
4069 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4070 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594071 session_deps.socket_factory.AddSocketDataProvider(&data1);
4072 session_deps.socket_factory.AddSocketDataProvider(&data2);
4073 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234074
4075 TestCompletionCallback callback1;
4076
[email protected]5a1d7ca2010-04-28 20:12:274077 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424078 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234079
4080 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424081 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234082
[email protected]0757e7702009-03-27 04:00:224083 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4084 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444085 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224087 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424088 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224089 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4090
[email protected]1c773ea12009-04-28 19:58:424091 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234092 EXPECT_FALSE(response == NULL);
4093
4094 // The password prompt info should have been set in
4095 // response->auth_challenge.
4096 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4097
[email protected]71e4573a2009-05-21 22:03:004098 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234099 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4100 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4101
[email protected]0757e7702009-03-27 04:00:224102 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234103
[email protected]13c8a092010-07-29 06:15:444104 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424105 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234106
[email protected]0757e7702009-03-27 04:00:224107 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424108 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234109
4110 response = trans->GetResponseInfo();
4111 EXPECT_FALSE(response == NULL);
4112 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4113 EXPECT_EQ(100, response->headers->GetContentLength());
4114 }
4115}
[email protected]89ceba9a2009-03-21 03:46:064116
[email protected]3c32c5f2010-05-18 15:18:124117// Tests that nonce count increments when multiple auth attempts
4118// are started with the same nonce.
4119TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4120 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444121 HttpAuthHandlerDigest::Factory* digest_factory =
4122 new HttpAuthHandlerDigest::Factory();
4123 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4124 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4125 digest_factory->set_nonce_generator(nonce_generator);
4126 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124128
4129 // Transaction 1: authenticate (foo, bar) on MyRealm1
4130 {
[email protected]3c32c5f2010-05-18 15:18:124131 HttpRequestInfo request;
4132 request.method = "GET";
4133 request.url = GURL("http://www.google.com/x/y/z");
4134 request.load_flags = 0;
4135
[email protected]cb9bf6ca2011-01-28 13:15:274136 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4137
[email protected]3c32c5f2010-05-18 15:18:124138 MockWrite data_writes1[] = {
4139 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4140 "Host: www.google.com\r\n"
4141 "Connection: keep-alive\r\n\r\n"),
4142 };
4143
4144 MockRead data_reads1[] = {
4145 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4146 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4147 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4148 MockRead(false, OK),
4149 };
4150
4151 // Resend with authorization (username=foo, password=bar)
4152 MockWrite data_writes2[] = {
4153 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4154 "Host: www.google.com\r\n"
4155 "Connection: keep-alive\r\n"
4156 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4157 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4158 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4159 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4160 };
4161
4162 // Sever accepts the authorization.
4163 MockRead data_reads2[] = {
4164 MockRead("HTTP/1.0 200 OK\r\n"),
4165 MockRead(false, OK),
4166 };
4167
4168 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4169 data_writes1, arraysize(data_writes1));
4170 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4171 data_writes2, arraysize(data_writes2));
4172 session_deps.socket_factory.AddSocketDataProvider(&data1);
4173 session_deps.socket_factory.AddSocketDataProvider(&data2);
4174
4175 TestCompletionCallback callback1;
4176
4177 int rv = trans->Start(&request, &callback1, BoundNetLog());
4178 EXPECT_EQ(ERR_IO_PENDING, rv);
4179
4180 rv = callback1.WaitForResult();
4181 EXPECT_EQ(OK, rv);
4182
4183 const HttpResponseInfo* response = trans->GetResponseInfo();
4184 ASSERT_FALSE(response == NULL);
4185
4186 // The password prompt info should have been set in
4187 // response->auth_challenge.
4188 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4189
4190 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4191 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4192 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4193
4194 TestCompletionCallback callback2;
4195
[email protected]13c8a092010-07-29 06:15:444196 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124197 EXPECT_EQ(ERR_IO_PENDING, rv);
4198
4199 rv = callback2.WaitForResult();
4200 EXPECT_EQ(OK, rv);
4201
4202 response = trans->GetResponseInfo();
4203 ASSERT_FALSE(response == NULL);
4204 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4205 }
4206
4207 // ------------------------------------------------------------------------
4208
4209 // Transaction 2: Request another resource in digestive's protection space.
4210 // This will preemptively add an Authorization header which should have an
4211 // "nc" value of 2 (as compared to 1 in the first use.
4212 {
[email protected]3c32c5f2010-05-18 15:18:124213 HttpRequestInfo request;
4214 request.method = "GET";
4215 // Note that Transaction 1 was at /x/y/z, so this is in the same
4216 // protection space as digest.
4217 request.url = GURL("http://www.google.com/x/y/a/b");
4218 request.load_flags = 0;
4219
[email protected]cb9bf6ca2011-01-28 13:15:274220 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4221
[email protected]3c32c5f2010-05-18 15:18:124222 MockWrite data_writes1[] = {
4223 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4224 "Host: www.google.com\r\n"
4225 "Connection: keep-alive\r\n"
4226 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4227 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4228 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4229 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4230 };
4231
4232 // Sever accepts the authorization.
4233 MockRead data_reads1[] = {
4234 MockRead("HTTP/1.0 200 OK\r\n"),
4235 MockRead("Content-Length: 100\r\n\r\n"),
4236 MockRead(false, OK),
4237 };
4238
4239 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4240 data_writes1, arraysize(data_writes1));
4241 session_deps.socket_factory.AddSocketDataProvider(&data1);
4242
4243 TestCompletionCallback callback1;
4244
4245 int rv = trans->Start(&request, &callback1, BoundNetLog());
4246 EXPECT_EQ(ERR_IO_PENDING, rv);
4247
4248 rv = callback1.WaitForResult();
4249 EXPECT_EQ(OK, rv);
4250
4251 const HttpResponseInfo* response = trans->GetResponseInfo();
4252 ASSERT_FALSE(response == NULL);
4253 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4254 }
4255}
4256
[email protected]89ceba9a2009-03-21 03:46:064257// Test the ResetStateForRestart() private method.
4258TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4259 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594260 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404261 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434262 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064263
4264 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064265 trans->read_buf_ = new IOBuffer(15);
4266 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204267 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064268
4269 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144270 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574271 response->auth_challenge = new AuthChallengeInfo();
4272 response->ssl_info.cert_status = -15;
4273 response->response_time = base::Time::Now();
4274 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064275
4276 { // Setup state for response_.vary_data
4277 HttpRequestInfo request;
4278 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4279 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274280 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434281 request.extra_headers.SetHeader("Foo", "1");
4282 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574283 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064284 }
4285
4286 // Cause the above state to be reset.
4287 trans->ResetStateForRestart();
4288
4289 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074290 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064291 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204292 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574293 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4294 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044295 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574296 EXPECT_EQ(0, response->ssl_info.cert_status);
4297 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064298}
4299
[email protected]bacff652009-03-31 17:50:334300// Test HTTPS connections to a site with a bad certificate
4301TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334302 HttpRequestInfo request;
4303 request.method = "GET";
4304 request.url = GURL("https://www.google.com/");
4305 request.load_flags = 0;
4306
[email protected]cb9bf6ca2011-01-28 13:15:274307 SessionDependencies session_deps;
4308 scoped_ptr<HttpTransaction> trans(
4309 new HttpNetworkTransaction(CreateSession(&session_deps)));
4310
[email protected]bacff652009-03-31 17:50:334311 MockWrite data_writes[] = {
4312 MockWrite("GET / HTTP/1.1\r\n"
4313 "Host: www.google.com\r\n"
4314 "Connection: keep-alive\r\n\r\n"),
4315 };
4316
4317 MockRead data_reads[] = {
4318 MockRead("HTTP/1.0 200 OK\r\n"),
4319 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4320 MockRead("Content-Length: 100\r\n\r\n"),
4321 MockRead(false, OK),
4322 };
4323
[email protected]5ecc992a42009-11-11 01:41:594324 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394325 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4326 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594327 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4328 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334329
[email protected]5ecc992a42009-11-11 01:41:594330 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4331 session_deps.socket_factory.AddSocketDataProvider(&data);
4332 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4333 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334334
4335 TestCompletionCallback callback;
4336
[email protected]5a1d7ca2010-04-28 20:12:274337 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334338 EXPECT_EQ(ERR_IO_PENDING, rv);
4339
4340 rv = callback.WaitForResult();
4341 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4342
4343 rv = trans->RestartIgnoringLastError(&callback);
4344 EXPECT_EQ(ERR_IO_PENDING, rv);
4345
4346 rv = callback.WaitForResult();
4347 EXPECT_EQ(OK, rv);
4348
4349 const HttpResponseInfo* response = trans->GetResponseInfo();
4350
4351 EXPECT_FALSE(response == NULL);
4352 EXPECT_EQ(100, response->headers->GetContentLength());
4353}
4354
4355// Test HTTPS connections to a site with a bad certificate, going through a
4356// proxy
4357TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004358 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334359
4360 HttpRequestInfo request;
4361 request.method = "GET";
4362 request.url = GURL("https://www.google.com/");
4363 request.load_flags = 0;
4364
4365 MockWrite proxy_writes[] = {
4366 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454367 "Host: www.google.com\r\n"
4368 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334369 };
4370
4371 MockRead proxy_reads[] = {
4372 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424373 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334374 };
4375
4376 MockWrite data_writes[] = {
4377 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454378 "Host: www.google.com\r\n"
4379 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334380 MockWrite("GET / HTTP/1.1\r\n"
4381 "Host: www.google.com\r\n"
4382 "Connection: keep-alive\r\n\r\n"),
4383 };
4384
4385 MockRead data_reads[] = {
4386 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4387 MockRead("HTTP/1.0 200 OK\r\n"),
4388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4389 MockRead("Content-Length: 100\r\n\r\n"),
4390 MockRead(false, OK),
4391 };
4392
[email protected]31a2bfe2010-02-09 08:03:394393 StaticSocketDataProvider ssl_bad_certificate(
4394 proxy_reads, arraysize(proxy_reads),
4395 proxy_writes, arraysize(proxy_writes));
4396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4397 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594398 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4399 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334400
[email protected]5ecc992a42009-11-11 01:41:594401 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4402 session_deps.socket_factory.AddSocketDataProvider(&data);
4403 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4404 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334405
4406 TestCompletionCallback callback;
4407
4408 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594409 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334410
[email protected]d207a5f2009-06-04 05:28:404411 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434412 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334413
[email protected]5a1d7ca2010-04-28 20:12:274414 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334415 EXPECT_EQ(ERR_IO_PENDING, rv);
4416
4417 rv = callback.WaitForResult();
4418 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4419
4420 rv = trans->RestartIgnoringLastError(&callback);
4421 EXPECT_EQ(ERR_IO_PENDING, rv);
4422
4423 rv = callback.WaitForResult();
4424 EXPECT_EQ(OK, rv);
4425
4426 const HttpResponseInfo* response = trans->GetResponseInfo();
4427
4428 EXPECT_FALSE(response == NULL);
4429 EXPECT_EQ(100, response->headers->GetContentLength());
4430 }
4431}
4432
[email protected]2df19bb2010-08-25 20:13:464433
4434// Test HTTPS connections to a site, going through an HTTPS proxy
4435TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004436 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464437
4438 HttpRequestInfo request;
4439 request.method = "GET";
4440 request.url = GURL("https://www.google.com/");
4441 request.load_flags = 0;
4442
4443 MockWrite data_writes[] = {
4444 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4445 "Host: www.google.com\r\n"
4446 "Proxy-Connection: keep-alive\r\n\r\n"),
4447 MockWrite("GET / HTTP/1.1\r\n"
4448 "Host: www.google.com\r\n"
4449 "Connection: keep-alive\r\n\r\n"),
4450 };
4451
4452 MockRead data_reads[] = {
4453 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4454 MockRead("HTTP/1.1 200 OK\r\n"),
4455 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4456 MockRead("Content-Length: 100\r\n\r\n"),
4457 MockRead(false, OK),
4458 };
4459
4460 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4461 data_writes, arraysize(data_writes));
4462 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4463 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4464
4465 session_deps.socket_factory.AddSocketDataProvider(&data);
4466 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4467 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4468
4469 TestCompletionCallback callback;
4470
4471 scoped_ptr<HttpTransaction> trans(
4472 new HttpNetworkTransaction(CreateSession(&session_deps)));
4473
4474 int rv = trans->Start(&request, &callback, BoundNetLog());
4475 EXPECT_EQ(ERR_IO_PENDING, rv);
4476
4477 rv = callback.WaitForResult();
4478 EXPECT_EQ(OK, rv);
4479 const HttpResponseInfo* response = trans->GetResponseInfo();
4480
4481 ASSERT_FALSE(response == NULL);
4482
4483 EXPECT_TRUE(response->headers->IsKeepAlive());
4484 EXPECT_EQ(200, response->headers->response_code());
4485 EXPECT_EQ(100, response->headers->GetContentLength());
4486 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4487}
4488
[email protected]511f6f52010-12-17 03:58:294489// Test an HTTPS Proxy's ability to redirect a CONNECT request
4490TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4491 SessionDependencies session_deps(
4492 ProxyService::CreateFixed("https://proxy:70"));
4493
4494 HttpRequestInfo request;
4495 request.method = "GET";
4496 request.url = GURL("https://www.google.com/");
4497 request.load_flags = 0;
4498
4499 MockWrite data_writes[] = {
4500 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4501 "Host: www.google.com\r\n"
4502 "Proxy-Connection: keep-alive\r\n\r\n"),
4503 };
4504
4505 MockRead data_reads[] = {
4506 MockRead("HTTP/1.1 302 Redirect\r\n"),
4507 MockRead("Location: http://login.example.com/\r\n"),
4508 MockRead("Content-Length: 0\r\n\r\n"),
4509 MockRead(false, OK),
4510 };
4511
4512 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4513 data_writes, arraysize(data_writes));
4514 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4515
4516 session_deps.socket_factory.AddSocketDataProvider(&data);
4517 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4518
4519 TestCompletionCallback callback;
4520
4521 scoped_ptr<HttpTransaction> trans(
4522 new HttpNetworkTransaction(CreateSession(&session_deps)));
4523
4524 int rv = trans->Start(&request, &callback, BoundNetLog());
4525 EXPECT_EQ(ERR_IO_PENDING, rv);
4526
4527 rv = callback.WaitForResult();
4528 EXPECT_EQ(OK, rv);
4529 const HttpResponseInfo* response = trans->GetResponseInfo();
4530
4531 ASSERT_FALSE(response == NULL);
4532
4533 EXPECT_EQ(302, response->headers->response_code());
4534 std::string url;
4535 EXPECT_TRUE(response->headers->IsRedirect(&url));
4536 EXPECT_EQ("http://login.example.com/", url);
4537}
4538
4539// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4540TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4541 SessionDependencies session_deps(
4542 ProxyService::CreateFixed("https://proxy:70"));
4543
4544 HttpRequestInfo request;
4545 request.method = "GET";
4546 request.url = GURL("https://www.google.com/");
4547 request.load_flags = 0;
4548
4549 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4550 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4551 MockWrite data_writes[] = {
4552 CreateMockWrite(*conn.get(), 0, false),
4553 };
4554
4555 static const char* const kExtraHeaders[] = {
4556 "location",
4557 "http://login.example.com/",
4558 };
4559 scoped_ptr<spdy::SpdyFrame> resp(
4560 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4561 arraysize(kExtraHeaders)/2, 1));
4562 MockRead data_reads[] = {
4563 CreateMockRead(*resp.get(), 1, false),
4564 MockRead(true, 0, 2), // EOF
4565 };
4566
4567 scoped_refptr<DelayedSocketData> data(
4568 new DelayedSocketData(
4569 1, // wait for one write to finish before reading.
4570 data_reads, arraysize(data_reads),
4571 data_writes, arraysize(data_writes)));
4572 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4573 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4574 proxy_ssl.next_proto = "spdy/2";
4575 proxy_ssl.was_npn_negotiated = true;
4576
4577 session_deps.socket_factory.AddSocketDataProvider(data.get());
4578 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4579
4580 TestCompletionCallback callback;
4581
4582 scoped_ptr<HttpTransaction> trans(
4583 new HttpNetworkTransaction(CreateSession(&session_deps)));
4584
4585 int rv = trans->Start(&request, &callback, BoundNetLog());
4586 EXPECT_EQ(ERR_IO_PENDING, rv);
4587
4588 rv = callback.WaitForResult();
4589 EXPECT_EQ(OK, rv);
4590 const HttpResponseInfo* response = trans->GetResponseInfo();
4591
4592 ASSERT_FALSE(response == NULL);
4593
4594 EXPECT_EQ(302, response->headers->response_code());
4595 std::string url;
4596 EXPECT_TRUE(response->headers->IsRedirect(&url));
4597 EXPECT_EQ("http://login.example.com/", url);
4598}
4599
4600// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4601TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4602 SessionDependencies session_deps(
4603 ProxyService::CreateFixed("https://proxy:70"));
4604
4605 HttpRequestInfo request;
4606 request.method = "GET";
4607 request.url = GURL("https://www.google.com/");
4608 request.load_flags = 0;
4609
4610 MockWrite data_writes[] = {
4611 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4612 "Host: www.google.com\r\n"
4613 "Proxy-Connection: keep-alive\r\n\r\n"),
4614 };
4615
4616 MockRead data_reads[] = {
4617 MockRead("HTTP/1.1 404 Not Found\r\n"),
4618 MockRead("Content-Length: 23\r\n\r\n"),
4619 MockRead("The host does not exist"),
4620 MockRead(false, OK),
4621 };
4622
4623 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4624 data_writes, arraysize(data_writes));
4625 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4626
4627 session_deps.socket_factory.AddSocketDataProvider(&data);
4628 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4629
4630 TestCompletionCallback callback;
4631
4632 scoped_ptr<HttpTransaction> trans(
4633 new HttpNetworkTransaction(CreateSession(&session_deps)));
4634
4635 int rv = trans->Start(&request, &callback, BoundNetLog());
4636 EXPECT_EQ(ERR_IO_PENDING, rv);
4637
4638 rv = callback.WaitForResult();
4639 EXPECT_EQ(OK, rv);
4640 const HttpResponseInfo* response = trans->GetResponseInfo();
4641
4642 ASSERT_FALSE(response == NULL);
4643
4644 EXPECT_EQ(404, response->headers->response_code());
4645 EXPECT_EQ(23, response->headers->GetContentLength());
4646 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4647 EXPECT_FALSE(response->ssl_info.is_valid());
4648
4649 std::string response_data;
4650 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4651 EXPECT_EQ("The host does not exist", response_data);
4652}
4653
4654// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4655// request
4656TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4657 SessionDependencies session_deps(
4658 ProxyService::CreateFixed("https://proxy:70"));
4659
4660 HttpRequestInfo request;
4661 request.method = "GET";
4662 request.url = GURL("https://www.google.com/");
4663 request.load_flags = 0;
4664
4665 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4666 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4667 MockWrite data_writes[] = {
4668 CreateMockWrite(*conn.get(), 0, false),
4669 };
4670
4671 static const char* const kExtraHeaders[] = {
4672 "location",
4673 "http://login.example.com/",
4674 };
4675 scoped_ptr<spdy::SpdyFrame> resp(
4676 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4677 arraysize(kExtraHeaders)/2, 1));
4678 scoped_ptr<spdy::SpdyFrame> body(
4679 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4680 MockRead data_reads[] = {
4681 CreateMockRead(*resp.get(), 1, false),
4682 CreateMockRead(*body.get(), 2, false),
4683 MockRead(true, 0, 3), // EOF
4684 };
4685
4686 scoped_refptr<DelayedSocketData> data(
4687 new DelayedSocketData(
4688 1, // wait for one write to finish before reading.
4689 data_reads, arraysize(data_reads),
4690 data_writes, arraysize(data_writes)));
4691 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4692 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4693 proxy_ssl.next_proto = "spdy/2";
4694 proxy_ssl.was_npn_negotiated = true;
4695
4696 session_deps.socket_factory.AddSocketDataProvider(data.get());
4697 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4698
4699 TestCompletionCallback callback;
4700
4701 scoped_ptr<HttpTransaction> trans(
4702 new HttpNetworkTransaction(CreateSession(&session_deps)));
4703
4704 int rv = trans->Start(&request, &callback, BoundNetLog());
4705 EXPECT_EQ(ERR_IO_PENDING, rv);
4706
4707 rv = callback.WaitForResult();
4708 EXPECT_EQ(OK, rv);
4709 const HttpResponseInfo* response = trans->GetResponseInfo();
4710
4711 ASSERT_FALSE(response == NULL);
4712
4713 EXPECT_EQ(404, response->headers->response_code());
4714 EXPECT_FALSE(response->ssl_info.is_valid());
4715
4716 std::string response_data;
4717 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4718 EXPECT_EQ("The host does not exist", response_data);
4719}
4720
[email protected]2df19bb2010-08-25 20:13:464721// Test HTTPS connections to a site with a bad certificate, going through an
4722// HTTPS proxy
4723TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004724 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464725
4726 HttpRequestInfo request;
4727 request.method = "GET";
4728 request.url = GURL("https://www.google.com/");
4729 request.load_flags = 0;
4730
4731 // Attempt to fetch the URL from a server with a bad cert
4732 MockWrite bad_cert_writes[] = {
4733 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4734 "Host: www.google.com\r\n"
4735 "Proxy-Connection: keep-alive\r\n\r\n"),
4736 };
4737
4738 MockRead bad_cert_reads[] = {
4739 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4740 MockRead(false, OK)
4741 };
4742
4743 // Attempt to fetch the URL with a good cert
4744 MockWrite good_data_writes[] = {
4745 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4746 "Host: www.google.com\r\n"
4747 "Proxy-Connection: keep-alive\r\n\r\n"),
4748 MockWrite("GET / HTTP/1.1\r\n"
4749 "Host: www.google.com\r\n"
4750 "Connection: keep-alive\r\n\r\n"),
4751 };
4752
4753 MockRead good_cert_reads[] = {
4754 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4755 MockRead("HTTP/1.0 200 OK\r\n"),
4756 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4757 MockRead("Content-Length: 100\r\n\r\n"),
4758 MockRead(false, OK),
4759 };
4760
4761 StaticSocketDataProvider ssl_bad_certificate(
4762 bad_cert_reads, arraysize(bad_cert_reads),
4763 bad_cert_writes, arraysize(bad_cert_writes));
4764 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4765 good_data_writes, arraysize(good_data_writes));
4766 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4767 SSLSocketDataProvider ssl(true, OK);
4768
4769 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4770 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4771 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4772 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4773
4774 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4775 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4776 session_deps.socket_factory.AddSocketDataProvider(&data);
4777 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4778
4779 TestCompletionCallback callback;
4780
4781 scoped_ptr<HttpTransaction> trans(
4782 new HttpNetworkTransaction(CreateSession(&session_deps)));
4783
4784 int rv = trans->Start(&request, &callback, BoundNetLog());
4785 EXPECT_EQ(ERR_IO_PENDING, rv);
4786
4787 rv = callback.WaitForResult();
4788 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4789
4790 rv = trans->RestartIgnoringLastError(&callback);
4791 EXPECT_EQ(ERR_IO_PENDING, rv);
4792
4793 rv = callback.WaitForResult();
4794 EXPECT_EQ(OK, rv);
4795
4796 const HttpResponseInfo* response = trans->GetResponseInfo();
4797
4798 EXPECT_FALSE(response == NULL);
4799 EXPECT_EQ(100, response->headers->GetContentLength());
4800}
4801
[email protected]1c773ea12009-04-28 19:58:424802TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424803 HttpRequestInfo request;
4804 request.method = "GET";
4805 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434806 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4807 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424808
[email protected]cb9bf6ca2011-01-28 13:15:274809 SessionDependencies session_deps;
4810 scoped_ptr<HttpTransaction> trans(
4811 new HttpNetworkTransaction(CreateSession(&session_deps)));
4812
[email protected]1c773ea12009-04-28 19:58:424813 MockWrite data_writes[] = {
4814 MockWrite("GET / HTTP/1.1\r\n"
4815 "Host: www.google.com\r\n"
4816 "Connection: keep-alive\r\n"
4817 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4818 };
4819
4820 // Lastly, the server responds with the actual content.
4821 MockRead data_reads[] = {
4822 MockRead("HTTP/1.0 200 OK\r\n"),
4823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4824 MockRead("Content-Length: 100\r\n\r\n"),
4825 MockRead(false, OK),
4826 };
4827
[email protected]31a2bfe2010-02-09 08:03:394828 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4829 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594830 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424831
4832 TestCompletionCallback callback;
4833
[email protected]5a1d7ca2010-04-28 20:12:274834 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424835 EXPECT_EQ(ERR_IO_PENDING, rv);
4836
4837 rv = callback.WaitForResult();
4838 EXPECT_EQ(OK, rv);
4839}
4840
[email protected]da81f132010-08-18 23:39:294841TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294842 HttpRequestInfo request;
4843 request.method = "GET";
4844 request.url = GURL("https://www.google.com/");
4845 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4846 "Chromium Ultra Awesome X Edition");
4847
[email protected]cb9bf6ca2011-01-28 13:15:274848 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4849 scoped_ptr<HttpTransaction> trans(
4850 new HttpNetworkTransaction(CreateSession(&session_deps)));
4851
[email protected]da81f132010-08-18 23:39:294852 MockWrite data_writes[] = {
4853 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4854 "Host: www.google.com\r\n"
4855 "Proxy-Connection: keep-alive\r\n"
4856 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4857 };
4858 MockRead data_reads[] = {
4859 // Return an error, so the transaction stops here (this test isn't
4860 // interested in the rest).
4861 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4862 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4863 MockRead("Proxy-Connection: close\r\n\r\n"),
4864 };
4865
4866 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4867 data_writes, arraysize(data_writes));
4868 session_deps.socket_factory.AddSocketDataProvider(&data);
4869
4870 TestCompletionCallback callback;
4871
4872 int rv = trans->Start(&request, &callback, BoundNetLog());
4873 EXPECT_EQ(ERR_IO_PENDING, rv);
4874
4875 rv = callback.WaitForResult();
4876 EXPECT_EQ(OK, rv);
4877}
4878
[email protected]1c773ea12009-04-28 19:58:424879TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424880 HttpRequestInfo request;
4881 request.method = "GET";
4882 request.url = GURL("http://www.google.com/");
4883 request.load_flags = 0;
4884 request.referrer = GURL("http://the.previous.site.com/");
4885
[email protected]cb9bf6ca2011-01-28 13:15:274886 SessionDependencies session_deps;
4887 scoped_ptr<HttpTransaction> trans(
4888 new HttpNetworkTransaction(CreateSession(&session_deps)));
4889
[email protected]1c773ea12009-04-28 19:58:424890 MockWrite data_writes[] = {
4891 MockWrite("GET / HTTP/1.1\r\n"
4892 "Host: www.google.com\r\n"
4893 "Connection: keep-alive\r\n"
4894 "Referer: http://the.previous.site.com/\r\n\r\n"),
4895 };
4896
4897 // Lastly, the server responds with the actual content.
4898 MockRead data_reads[] = {
4899 MockRead("HTTP/1.0 200 OK\r\n"),
4900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4901 MockRead("Content-Length: 100\r\n\r\n"),
4902 MockRead(false, OK),
4903 };
4904
[email protected]31a2bfe2010-02-09 08:03:394905 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4906 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594907 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424908
4909 TestCompletionCallback callback;
4910
[email protected]5a1d7ca2010-04-28 20:12:274911 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424912 EXPECT_EQ(ERR_IO_PENDING, rv);
4913
4914 rv = callback.WaitForResult();
4915 EXPECT_EQ(OK, rv);
4916}
4917
4918TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424919 HttpRequestInfo request;
4920 request.method = "POST";
4921 request.url = GURL("http://www.google.com/");
4922
[email protected]cb9bf6ca2011-01-28 13:15:274923 SessionDependencies session_deps;
4924 scoped_ptr<HttpTransaction> trans(
4925 new HttpNetworkTransaction(CreateSession(&session_deps)));
4926
[email protected]1c773ea12009-04-28 19:58:424927 MockWrite data_writes[] = {
4928 MockWrite("POST / HTTP/1.1\r\n"
4929 "Host: www.google.com\r\n"
4930 "Connection: keep-alive\r\n"
4931 "Content-Length: 0\r\n\r\n"),
4932 };
4933
4934 // Lastly, the server responds with the actual content.
4935 MockRead data_reads[] = {
4936 MockRead("HTTP/1.0 200 OK\r\n"),
4937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4938 MockRead("Content-Length: 100\r\n\r\n"),
4939 MockRead(false, OK),
4940 };
4941
[email protected]31a2bfe2010-02-09 08:03:394942 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4943 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594944 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424945
4946 TestCompletionCallback callback;
4947
[email protected]5a1d7ca2010-04-28 20:12:274948 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424949 EXPECT_EQ(ERR_IO_PENDING, rv);
4950
4951 rv = callback.WaitForResult();
4952 EXPECT_EQ(OK, rv);
4953}
4954
4955TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424956 HttpRequestInfo request;
4957 request.method = "PUT";
4958 request.url = GURL("http://www.google.com/");
4959
[email protected]cb9bf6ca2011-01-28 13:15:274960 SessionDependencies session_deps;
4961 scoped_ptr<HttpTransaction> trans(
4962 new HttpNetworkTransaction(CreateSession(&session_deps)));
4963
[email protected]1c773ea12009-04-28 19:58:424964 MockWrite data_writes[] = {
4965 MockWrite("PUT / HTTP/1.1\r\n"
4966 "Host: www.google.com\r\n"
4967 "Connection: keep-alive\r\n"
4968 "Content-Length: 0\r\n\r\n"),
4969 };
4970
4971 // Lastly, the server responds with the actual content.
4972 MockRead data_reads[] = {
4973 MockRead("HTTP/1.0 200 OK\r\n"),
4974 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4975 MockRead("Content-Length: 100\r\n\r\n"),
4976 MockRead(false, OK),
4977 };
4978
[email protected]31a2bfe2010-02-09 08:03:394979 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4980 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594981 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424982
4983 TestCompletionCallback callback;
4984
[email protected]5a1d7ca2010-04-28 20:12:274985 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424986 EXPECT_EQ(ERR_IO_PENDING, rv);
4987
4988 rv = callback.WaitForResult();
4989 EXPECT_EQ(OK, rv);
4990}
4991
4992TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424993 HttpRequestInfo request;
4994 request.method = "HEAD";
4995 request.url = GURL("http://www.google.com/");
4996
[email protected]cb9bf6ca2011-01-28 13:15:274997 SessionDependencies session_deps;
4998 scoped_ptr<HttpTransaction> trans(
4999 new HttpNetworkTransaction(CreateSession(&session_deps)));
5000
[email protected]1c773ea12009-04-28 19:58:425001 MockWrite data_writes[] = {
5002 MockWrite("HEAD / HTTP/1.1\r\n"
5003 "Host: www.google.com\r\n"
5004 "Connection: keep-alive\r\n"
5005 "Content-Length: 0\r\n\r\n"),
5006 };
5007
5008 // Lastly, the server responds with the actual content.
5009 MockRead data_reads[] = {
5010 MockRead("HTTP/1.0 200 OK\r\n"),
5011 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5012 MockRead("Content-Length: 100\r\n\r\n"),
5013 MockRead(false, OK),
5014 };
5015
[email protected]31a2bfe2010-02-09 08:03:395016 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5017 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595018 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425019
5020 TestCompletionCallback callback;
5021
[email protected]5a1d7ca2010-04-28 20:12:275022 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425023 EXPECT_EQ(ERR_IO_PENDING, rv);
5024
5025 rv = callback.WaitForResult();
5026 EXPECT_EQ(OK, rv);
5027}
5028
5029TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425030 HttpRequestInfo request;
5031 request.method = "GET";
5032 request.url = GURL("http://www.google.com/");
5033 request.load_flags = LOAD_BYPASS_CACHE;
5034
[email protected]cb9bf6ca2011-01-28 13:15:275035 SessionDependencies session_deps;
5036 scoped_ptr<HttpTransaction> trans(
5037 new HttpNetworkTransaction(CreateSession(&session_deps)));
5038
[email protected]1c773ea12009-04-28 19:58:425039 MockWrite data_writes[] = {
5040 MockWrite("GET / HTTP/1.1\r\n"
5041 "Host: www.google.com\r\n"
5042 "Connection: keep-alive\r\n"
5043 "Pragma: no-cache\r\n"
5044 "Cache-Control: no-cache\r\n\r\n"),
5045 };
5046
5047 // Lastly, the server responds with the actual content.
5048 MockRead data_reads[] = {
5049 MockRead("HTTP/1.0 200 OK\r\n"),
5050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5051 MockRead("Content-Length: 100\r\n\r\n"),
5052 MockRead(false, OK),
5053 };
5054
[email protected]31a2bfe2010-02-09 08:03:395055 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5056 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595057 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425058
5059 TestCompletionCallback callback;
5060
[email protected]5a1d7ca2010-04-28 20:12:275061 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425062 EXPECT_EQ(ERR_IO_PENDING, rv);
5063
5064 rv = callback.WaitForResult();
5065 EXPECT_EQ(OK, rv);
5066}
5067
5068TEST_F(HttpNetworkTransactionTest,
5069 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425070 HttpRequestInfo request;
5071 request.method = "GET";
5072 request.url = GURL("http://www.google.com/");
5073 request.load_flags = LOAD_VALIDATE_CACHE;
5074
[email protected]cb9bf6ca2011-01-28 13:15:275075 SessionDependencies session_deps;
5076 scoped_ptr<HttpTransaction> trans(
5077 new HttpNetworkTransaction(CreateSession(&session_deps)));
5078
[email protected]1c773ea12009-04-28 19:58:425079 MockWrite data_writes[] = {
5080 MockWrite("GET / HTTP/1.1\r\n"
5081 "Host: www.google.com\r\n"
5082 "Connection: keep-alive\r\n"
5083 "Cache-Control: max-age=0\r\n\r\n"),
5084 };
5085
5086 // Lastly, the server responds with the actual content.
5087 MockRead data_reads[] = {
5088 MockRead("HTTP/1.0 200 OK\r\n"),
5089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5090 MockRead("Content-Length: 100\r\n\r\n"),
5091 MockRead(false, OK),
5092 };
5093
[email protected]31a2bfe2010-02-09 08:03:395094 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5095 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595096 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425097
5098 TestCompletionCallback callback;
5099
[email protected]5a1d7ca2010-04-28 20:12:275100 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425101 EXPECT_EQ(ERR_IO_PENDING, rv);
5102
5103 rv = callback.WaitForResult();
5104 EXPECT_EQ(OK, rv);
5105}
5106
5107TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425108 HttpRequestInfo request;
5109 request.method = "GET";
5110 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435111 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425112
[email protected]cb9bf6ca2011-01-28 13:15:275113 SessionDependencies session_deps;
5114 scoped_ptr<HttpTransaction> trans(
5115 new HttpNetworkTransaction(CreateSession(&session_deps)));
5116
[email protected]1c773ea12009-04-28 19:58:425117 MockWrite data_writes[] = {
5118 MockWrite("GET / HTTP/1.1\r\n"
5119 "Host: www.google.com\r\n"
5120 "Connection: keep-alive\r\n"
5121 "FooHeader: Bar\r\n\r\n"),
5122 };
5123
5124 // Lastly, the server responds with the actual content.
5125 MockRead data_reads[] = {
5126 MockRead("HTTP/1.0 200 OK\r\n"),
5127 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5128 MockRead("Content-Length: 100\r\n\r\n"),
5129 MockRead(false, OK),
5130 };
5131
[email protected]31a2bfe2010-02-09 08:03:395132 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5133 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595134 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425135
5136 TestCompletionCallback callback;
5137
[email protected]5a1d7ca2010-04-28 20:12:275138 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425139 EXPECT_EQ(ERR_IO_PENDING, rv);
5140
5141 rv = callback.WaitForResult();
5142 EXPECT_EQ(OK, rv);
5143}
5144
[email protected]270c6412010-03-29 22:02:475145TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475146 HttpRequestInfo request;
5147 request.method = "GET";
5148 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435149 request.extra_headers.SetHeader("referer", "www.foo.com");
5150 request.extra_headers.SetHeader("hEllo", "Kitty");
5151 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475152
[email protected]cb9bf6ca2011-01-28 13:15:275153 SessionDependencies session_deps;
5154 scoped_ptr<HttpTransaction> trans(
5155 new HttpNetworkTransaction(CreateSession(&session_deps)));
5156
[email protected]270c6412010-03-29 22:02:475157 MockWrite data_writes[] = {
5158 MockWrite("GET / HTTP/1.1\r\n"
5159 "Host: www.google.com\r\n"
5160 "Connection: keep-alive\r\n"
5161 "hEllo: Kitty\r\n"
5162 "FoO: bar\r\n\r\n"),
5163 };
5164
5165 // Lastly, the server responds with the actual content.
5166 MockRead data_reads[] = {
5167 MockRead("HTTP/1.0 200 OK\r\n"),
5168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5169 MockRead("Content-Length: 100\r\n\r\n"),
5170 MockRead(false, OK),
5171 };
5172
5173 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5174 data_writes, arraysize(data_writes));
5175 session_deps.socket_factory.AddSocketDataProvider(&data);
5176
5177 TestCompletionCallback callback;
5178
[email protected]5a1d7ca2010-04-28 20:12:275179 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475180 EXPECT_EQ(ERR_IO_PENDING, rv);
5181
5182 rv = callback.WaitForResult();
5183 EXPECT_EQ(OK, rv);
5184}
5185
[email protected]3cd17242009-06-23 02:59:025186TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275187 HttpRequestInfo request;
5188 request.method = "GET";
5189 request.url = GURL("http://www.google.com/");
5190 request.load_flags = 0;
5191
[email protected]80d6524d2009-08-18 03:58:095192 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005193 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025194
5195 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435196 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025197
[email protected]3cd17242009-06-23 02:59:025198 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5199 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5200
5201 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355202 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025203 MockWrite("GET / HTTP/1.1\r\n"
5204 "Host: www.google.com\r\n"
5205 "Connection: keep-alive\r\n\r\n")
5206 };
5207
5208 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595209 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025210 MockRead("HTTP/1.0 200 OK\r\n"),
5211 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5212 MockRead("Payload"),
5213 MockRead(false, OK)
5214 };
5215
[email protected]31a2bfe2010-02-09 08:03:395216 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5217 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595218 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025219
5220 TestCompletionCallback callback;
5221
[email protected]5a1d7ca2010-04-28 20:12:275222 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025223 EXPECT_EQ(ERR_IO_PENDING, rv);
5224
5225 rv = callback.WaitForResult();
5226 EXPECT_EQ(OK, rv);
5227
5228 const HttpResponseInfo* response = trans->GetResponseInfo();
5229 EXPECT_FALSE(response == NULL);
5230
5231 std::string response_text;
5232 rv = ReadTransaction(trans.get(), &response_text);
5233 EXPECT_EQ(OK, rv);
5234 EXPECT_EQ("Payload", response_text);
5235}
5236
5237TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275238 HttpRequestInfo request;
5239 request.method = "GET";
5240 request.url = GURL("https://www.google.com/");
5241 request.load_flags = 0;
5242
[email protected]80d6524d2009-08-18 03:58:095243 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005244 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025245
5246 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435247 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025248
[email protected]3cd17242009-06-23 02:59:025249 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5250 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5251
5252 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355253 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5254 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025255 MockWrite("GET / HTTP/1.1\r\n"
5256 "Host: www.google.com\r\n"
5257 "Connection: keep-alive\r\n\r\n")
5258 };
5259
5260 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355261 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5262 arraysize(read_buffer)),
5263 MockRead("HTTP/1.0 200 OK\r\n"),
5264 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5265 MockRead("Payload"),
5266 MockRead(false, OK)
5267 };
5268
[email protected]31a2bfe2010-02-09 08:03:395269 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5270 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595271 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355272
[email protected]5ecc992a42009-11-11 01:41:595273 SSLSocketDataProvider ssl(true, OK);
5274 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355275
5276 TestCompletionCallback callback;
5277
[email protected]5a1d7ca2010-04-28 20:12:275278 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355279 EXPECT_EQ(ERR_IO_PENDING, rv);
5280
5281 rv = callback.WaitForResult();
5282 EXPECT_EQ(OK, rv);
5283
5284 const HttpResponseInfo* response = trans->GetResponseInfo();
5285 EXPECT_FALSE(response == NULL);
5286
5287 std::string response_text;
5288 rv = ReadTransaction(trans.get(), &response_text);
5289 EXPECT_EQ(OK, rv);
5290 EXPECT_EQ("Payload", response_text);
5291}
5292
5293TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275294 HttpRequestInfo request;
5295 request.method = "GET";
5296 request.url = GURL("http://www.google.com/");
5297 request.load_flags = 0;
5298
[email protected]80d6524d2009-08-18 03:58:095299 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005300 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355301
5302 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435303 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355304
[email protected]e0c27be2009-07-15 13:09:355305 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5306 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375307 const char kSOCKS5OkRequest[] = {
5308 0x05, // Version
5309 0x01, // Command (CONNECT)
5310 0x00, // Reserved.
5311 0x03, // Address type (DOMAINNAME).
5312 0x0E, // Length of domain (14)
5313 // Domain string:
5314 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5315 0x00, 0x50, // 16-bit port (80)
5316 };
[email protected]e0c27be2009-07-15 13:09:355317 const char kSOCKS5OkResponse[] =
5318 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5319
5320 MockWrite data_writes[] = {
5321 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5322 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5323 MockWrite("GET / HTTP/1.1\r\n"
5324 "Host: www.google.com\r\n"
5325 "Connection: keep-alive\r\n\r\n")
5326 };
5327
5328 MockRead data_reads[] = {
5329 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5330 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5331 MockRead("HTTP/1.0 200 OK\r\n"),
5332 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5333 MockRead("Payload"),
5334 MockRead(false, OK)
5335 };
5336
[email protected]31a2bfe2010-02-09 08:03:395337 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5338 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595339 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355340
5341 TestCompletionCallback callback;
5342
[email protected]5a1d7ca2010-04-28 20:12:275343 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355344 EXPECT_EQ(ERR_IO_PENDING, rv);
5345
5346 rv = callback.WaitForResult();
5347 EXPECT_EQ(OK, rv);
5348
5349 const HttpResponseInfo* response = trans->GetResponseInfo();
5350 EXPECT_FALSE(response == NULL);
5351
5352 std::string response_text;
5353 rv = ReadTransaction(trans.get(), &response_text);
5354 EXPECT_EQ(OK, rv);
5355 EXPECT_EQ("Payload", response_text);
5356}
5357
5358TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275359 HttpRequestInfo request;
5360 request.method = "GET";
5361 request.url = GURL("https://www.google.com/");
5362 request.load_flags = 0;
5363
[email protected]80d6524d2009-08-18 03:58:095364 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005365 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355366
5367 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435368 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355369
[email protected]e0c27be2009-07-15 13:09:355370 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5371 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375372 const unsigned char kSOCKS5OkRequest[] = {
5373 0x05, // Version
5374 0x01, // Command (CONNECT)
5375 0x00, // Reserved.
5376 0x03, // Address type (DOMAINNAME).
5377 0x0E, // Length of domain (14)
5378 // Domain string:
5379 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5380 0x01, 0xBB, // 16-bit port (443)
5381 };
5382
[email protected]e0c27be2009-07-15 13:09:355383 const char kSOCKS5OkResponse[] =
5384 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5385
5386 MockWrite data_writes[] = {
5387 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5388 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5389 arraysize(kSOCKS5OkRequest)),
5390 MockWrite("GET / HTTP/1.1\r\n"
5391 "Host: www.google.com\r\n"
5392 "Connection: keep-alive\r\n\r\n")
5393 };
5394
5395 MockRead data_reads[] = {
5396 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5397 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025398 MockRead("HTTP/1.0 200 OK\r\n"),
5399 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5400 MockRead("Payload"),
5401 MockRead(false, OK)
5402 };
5403
[email protected]31a2bfe2010-02-09 08:03:395404 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5405 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595406 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025407
[email protected]5ecc992a42009-11-11 01:41:595408 SSLSocketDataProvider ssl(true, OK);
5409 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025410
5411 TestCompletionCallback callback;
5412
[email protected]5a1d7ca2010-04-28 20:12:275413 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025414 EXPECT_EQ(ERR_IO_PENDING, rv);
5415
5416 rv = callback.WaitForResult();
5417 EXPECT_EQ(OK, rv);
5418
5419 const HttpResponseInfo* response = trans->GetResponseInfo();
5420 EXPECT_FALSE(response == NULL);
5421
5422 std::string response_text;
5423 rv = ReadTransaction(trans.get(), &response_text);
5424 EXPECT_EQ(OK, rv);
5425 EXPECT_EQ("Payload", response_text);
5426}
5427
[email protected]04e5be32009-06-26 20:00:315428// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065429
5430struct GroupNameTest {
5431 std::string proxy_server;
5432 std::string url;
5433 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185434 bool ssl;
[email protected]2d731a32010-04-29 01:04:065435};
5436
5437scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5438 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:005439 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:065440 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5441
5442 HttpAlternateProtocols* alternate_protocols =
5443 session->mutable_alternate_protocols();
5444 alternate_protocols->SetAlternateProtocolFor(
5445 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355446 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065447
5448 return session;
5449}
5450
5451int GroupNameTransactionHelper(
5452 const std::string& url,
5453 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065454 HttpRequestInfo request;
5455 request.method = "GET";
5456 request.url = GURL(url);
5457 request.load_flags = 0;
5458
[email protected]cb9bf6ca2011-01-28 13:15:275459 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5460
[email protected]2d731a32010-04-29 01:04:065461 TestCompletionCallback callback;
5462
5463 // We do not complete this request, the dtor will clean the transaction up.
5464 return trans->Start(&request, &callback, BoundNetLog());
5465}
5466
5467TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5468 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315469 {
[email protected]2d731a32010-04-29 01:04:065470 "", // unused
[email protected]04e5be32009-06-26 20:00:315471 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545472 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185473 false,
[email protected]2ff8b312010-04-26 22:20:545474 },
5475 {
[email protected]2d731a32010-04-29 01:04:065476 "", // unused
[email protected]2ff8b312010-04-26 22:20:545477 "http://[2001:1418:13:1::25]/direct",
5478 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185479 false,
[email protected]04e5be32009-06-26 20:00:315480 },
[email protected]04e5be32009-06-26 20:00:315481
5482 // SSL Tests
5483 {
[email protected]2d731a32010-04-29 01:04:065484 "", // unused
[email protected]04e5be32009-06-26 20:00:315485 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025486 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185487 true,
[email protected]04e5be32009-06-26 20:00:315488 },
5489 {
[email protected]2d731a32010-04-29 01:04:065490 "", // unused
5491 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025492 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185493 true,
[email protected]04e5be32009-06-26 20:00:315494 },
5495 {
[email protected]2d731a32010-04-29 01:04:065496 "", // unused
[email protected]2ff8b312010-04-26 22:20:545497 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025498 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185499 true,
[email protected]2ff8b312010-04-26 22:20:545500 },
[email protected]2d731a32010-04-29 01:04:065501 };
[email protected]2ff8b312010-04-26 22:20:545502
[email protected]8e6441ca2010-08-19 05:56:385503 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065504
5505 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5506 scoped_refptr<HttpNetworkSession> session(
5507 SetupSessionForGroupNameTests(tests[i].proxy_server));
5508
5509 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135510 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5511 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065512 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135513 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5514 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185515 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065516
5517 EXPECT_EQ(ERR_IO_PENDING,
5518 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185519 if (tests[i].ssl)
5520 EXPECT_EQ(tests[i].expected_group_name,
5521 ssl_conn_pool->last_group_name_received());
5522 else
5523 EXPECT_EQ(tests[i].expected_group_name,
5524 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065525 }
5526
[email protected]8e6441ca2010-08-19 05:56:385527 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065528}
5529
5530TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5531 const GroupNameTest tests[] = {
5532 {
5533 "http_proxy",
5534 "http://www.google.com/http_proxy_normal",
5535 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185536 false,
[email protected]2d731a32010-04-29 01:04:065537 },
5538
5539 // SSL Tests
5540 {
5541 "http_proxy",
5542 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025543 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185544 true,
[email protected]2d731a32010-04-29 01:04:065545 },
[email protected]af3490e2010-10-16 21:02:295546
[email protected]9faeded92010-04-29 20:03:055547 {
5548 "http_proxy",
5549 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025550 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185551 true,
[email protected]9faeded92010-04-29 20:03:055552 },
[email protected]2d731a32010-04-29 01:04:065553 };
5554
[email protected]8e6441ca2010-08-19 05:56:385555 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065556
5557 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5558 scoped_refptr<HttpNetworkSession> session(
5559 SetupSessionForGroupNameTests(tests[i].proxy_server));
5560
5561 HttpNetworkSessionPeer peer(session);
5562
[email protected]e60e47a2010-07-14 03:37:185563 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135564 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5565 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185566 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135567 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5568 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185569 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065570
5571 EXPECT_EQ(ERR_IO_PENDING,
5572 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185573 if (tests[i].ssl)
5574 EXPECT_EQ(tests[i].expected_group_name,
5575 ssl_conn_pool->last_group_name_received());
5576 else
5577 EXPECT_EQ(tests[i].expected_group_name,
5578 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065579 }
5580
[email protected]8e6441ca2010-08-19 05:56:385581 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065582}
5583
5584TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5585 const GroupNameTest tests[] = {
5586 {
5587 "socks4://socks_proxy:1080",
5588 "http://www.google.com/socks4_direct",
5589 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185590 false,
[email protected]2d731a32010-04-29 01:04:065591 },
5592 {
5593 "socks5://socks_proxy:1080",
5594 "http://www.google.com/socks5_direct",
5595 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185596 false,
[email protected]2d731a32010-04-29 01:04:065597 },
5598
5599 // SSL Tests
5600 {
5601 "socks4://socks_proxy:1080",
5602 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025603 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185604 true,
[email protected]2d731a32010-04-29 01:04:065605 },
5606 {
5607 "socks5://socks_proxy:1080",
5608 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025609 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185610 true,
[email protected]2d731a32010-04-29 01:04:065611 },
[email protected]af3490e2010-10-16 21:02:295612
[email protected]9faeded92010-04-29 20:03:055613 {
5614 "socks4://socks_proxy:1080",
5615 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025616 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185617 true,
[email protected]9faeded92010-04-29 20:03:055618 },
[email protected]04e5be32009-06-26 20:00:315619 };
5620
[email protected]8e6441ca2010-08-19 05:56:385621 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545622
[email protected]04e5be32009-06-26 20:00:315623 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065624 scoped_refptr<HttpNetworkSession> session(
5625 SetupSessionForGroupNameTests(tests[i].proxy_server));
5626 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315627
[email protected]e60e47a2010-07-14 03:37:185628 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135629 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5630 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185631 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135632 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5633 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185634 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315635
[email protected]5695b8c2009-09-30 21:36:435636 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315637
[email protected]2d731a32010-04-29 01:04:065638 EXPECT_EQ(ERR_IO_PENDING,
5639 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185640 if (tests[i].ssl)
5641 EXPECT_EQ(tests[i].expected_group_name,
5642 ssl_conn_pool->last_group_name_received());
5643 else
5644 EXPECT_EQ(tests[i].expected_group_name,
5645 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315646 }
[email protected]2ff8b312010-04-26 22:20:545647
[email protected]8e6441ca2010-08-19 05:56:385648 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315649}
5650
[email protected]9172a982009-06-06 00:30:255651TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275652 HttpRequestInfo request;
5653 request.method = "GET";
5654 request.url = GURL("http://www.google.com/");
5655
[email protected]5c6a17e2009-06-10 00:54:545656 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005657 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325658
[email protected]69719062010-01-05 20:09:215659 // This simulates failure resolving all hostnames; that means we will fail
5660 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325661 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5662
[email protected]9172a982009-06-06 00:30:255663 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435664 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255665
[email protected]9172a982009-06-06 00:30:255666 TestCompletionCallback callback;
5667
[email protected]5a1d7ca2010-04-28 20:12:275668 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255669 EXPECT_EQ(ERR_IO_PENDING, rv);
5670
[email protected]9172a982009-06-06 00:30:255671 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015672 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255673}
5674
[email protected]f3e6c1e2009-06-15 20:52:125675// Host resolution observer used by
5676// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5677// resovle requests are issued with a referrer of |expected_referrer|.
5678class ResolutionReferrerObserver : public HostResolver::Observer {
5679 public:
5680 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5681 : expected_referrer_(expected_referrer),
5682 called_start_with_referrer_(false),
5683 called_finish_with_referrer_(false) {
5684 }
5685
5686 virtual void OnStartResolution(int id,
5687 const HostResolver::RequestInfo& info) {
5688 if (info.referrer() == expected_referrer_)
5689 called_start_with_referrer_ = true;
5690 }
5691
5692 virtual void OnFinishResolutionWithStatus(
5693 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5694 if (info.referrer() == expected_referrer_)
5695 called_finish_with_referrer_ = true;
5696 }
5697
[email protected]eb255d32009-06-17 02:11:035698 virtual void OnCancelResolution(int id,
5699 const HostResolver::RequestInfo& info ) {
5700 FAIL() << "Should not be cancelling any requests!";
5701 }
5702
[email protected]f3e6c1e2009-06-15 20:52:125703 bool did_complete_with_expected_referrer() const {
5704 return called_start_with_referrer_ && called_finish_with_referrer_;
5705 }
5706
5707 private:
5708 GURL expected_referrer_;
5709 bool called_start_with_referrer_;
5710 bool called_finish_with_referrer_;
5711
5712 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5713};
5714
5715// Make sure that when HostResolver::Resolve() is invoked, it passes through
5716// the "referrer". This is depended on by the DNS prefetch observer.
5717TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5718 GURL referrer = GURL("http://expected-referrer/");
5719 EXPECT_TRUE(referrer.is_valid());
5720 ResolutionReferrerObserver resolution_observer(referrer);
5721
[email protected]cb9bf6ca2011-01-28 13:15:275722 // Issue a request, containing an HTTP referrer.
5723 HttpRequestInfo request;
5724 request.method = "GET";
5725 request.referrer = referrer;
5726 request.url = GURL("http://www.google.com/");
5727
[email protected]f3e6c1e2009-06-15 20:52:125728 SessionDependencies session_deps;
5729 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435730 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125731
5732 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145733 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125734
5735 // Connect up a mock socket which will fail when reading.
5736 MockRead data_reads[] = {
5737 MockRead(false, ERR_FAILED),
5738 };
[email protected]31a2bfe2010-02-09 08:03:395739 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595740 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125741
[email protected]f3e6c1e2009-06-15 20:52:125742 // Run the request until it fails reading from the socket.
5743 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275744 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125745 EXPECT_EQ(ERR_IO_PENDING, rv);
5746 rv = callback.WaitForResult();
5747 EXPECT_EQ(ERR_FAILED, rv);
5748
5749 // Check that the host resolution observer saw |referrer|.
5750 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5751}
5752
[email protected]685af592010-05-11 19:31:245753// Base test to make sure that when the load flags for a request specify to
5754// bypass the cache, the DNS cache is not used.
5755void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275756 // Issue a request, asking to bypass the cache(s).
5757 HttpRequestInfo request;
5758 request.method = "GET";
5759 request.load_flags = load_flags;
5760 request.url = GURL("http://www.google.com/");
5761
[email protected]3b9cca42009-06-16 01:08:285762 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325763
[email protected]a2c2fb92009-07-18 07:31:045764 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545765 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325766
[email protected]3b9cca42009-06-16 01:08:285767 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435768 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285769
5770 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5771 // a synchronous lookup.)
5772 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145773 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105774 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275775 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285776 EXPECT_EQ(OK, rv);
5777
5778 // Verify that it was added to host cache, by doing a subsequent async lookup
5779 // and confirming it completes synchronously.
5780 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465781 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105782 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275783 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325784 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285785
5786 // Inject a failure the next time that "www.google.com" is resolved. This way
5787 // we can tell if the next lookup hit the cache, or the "network".
5788 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325789 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285790
5791 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5792 // first read -- this won't be reached as the host resolution will fail first.
5793 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395794 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595795 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285796
[email protected]3b9cca42009-06-16 01:08:285797 // Run the request.
5798 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275799 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285800 ASSERT_EQ(ERR_IO_PENDING, rv);
5801 rv = callback.WaitForResult();
5802
5803 // If we bypassed the cache, we would have gotten a failure while resolving
5804 // "www.google.com".
5805 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5806}
5807
[email protected]685af592010-05-11 19:31:245808// There are multiple load flags that should trigger the host cache bypass.
5809// Test each in isolation:
5810TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5811 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5812}
5813
5814TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5815 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5816}
5817
5818TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5819 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5820}
5821
[email protected]0877e3d2009-10-17 22:29:575822// Make sure we can handle an error when writing the request.
5823TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5824 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275825 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575826
5827 HttpRequestInfo request;
5828 request.method = "GET";
5829 request.url = GURL("http://www.foo.com/");
5830 request.load_flags = 0;
5831
5832 MockWrite write_failure[] = {
5833 MockWrite(true, ERR_CONNECTION_RESET),
5834 };
[email protected]31a2bfe2010-02-09 08:03:395835 StaticSocketDataProvider data(NULL, 0,
5836 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595837 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575838
5839 TestCompletionCallback callback;
5840
5841 scoped_ptr<HttpTransaction> trans(
5842 new HttpNetworkTransaction(CreateSession(&session_deps)));
5843
[email protected]5a1d7ca2010-04-28 20:12:275844 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575845 EXPECT_EQ(ERR_IO_PENDING, rv);
5846
5847 rv = callback.WaitForResult();
5848 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5849}
5850
5851// Check that a connection closed after the start of the headers finishes ok.
5852TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5853 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275854 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575855
5856 HttpRequestInfo request;
5857 request.method = "GET";
5858 request.url = GURL("http://www.foo.com/");
5859 request.load_flags = 0;
5860
5861 MockRead data_reads[] = {
5862 MockRead("HTTP/1."),
5863 MockRead(false, OK),
5864 };
5865
[email protected]31a2bfe2010-02-09 08:03:395866 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595867 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575868
5869 TestCompletionCallback callback;
5870
5871 scoped_ptr<HttpTransaction> trans(
5872 new HttpNetworkTransaction(CreateSession(&session_deps)));
5873
[email protected]5a1d7ca2010-04-28 20:12:275874 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575875 EXPECT_EQ(ERR_IO_PENDING, rv);
5876
5877 rv = callback.WaitForResult();
5878 EXPECT_EQ(OK, rv);
5879
5880 const HttpResponseInfo* response = trans->GetResponseInfo();
5881 EXPECT_TRUE(response != NULL);
5882
5883 EXPECT_TRUE(response->headers != NULL);
5884 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5885
5886 std::string response_data;
5887 rv = ReadTransaction(trans.get(), &response_data);
5888 EXPECT_EQ(OK, rv);
5889 EXPECT_EQ("", response_data);
5890}
5891
5892// Make sure that a dropped connection while draining the body for auth
5893// restart does the right thing.
5894TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5895 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275896 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575897
5898 HttpRequestInfo request;
5899 request.method = "GET";
5900 request.url = GURL("http://www.google.com/");
5901 request.load_flags = 0;
5902
5903 MockWrite data_writes1[] = {
5904 MockWrite("GET / HTTP/1.1\r\n"
5905 "Host: www.google.com\r\n"
5906 "Connection: keep-alive\r\n\r\n"),
5907 };
5908
5909 MockRead data_reads1[] = {
5910 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5911 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5913 MockRead("Content-Length: 14\r\n\r\n"),
5914 MockRead("Unauth"),
5915 MockRead(true, ERR_CONNECTION_RESET),
5916 };
5917
[email protected]31a2bfe2010-02-09 08:03:395918 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5919 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595920 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575921
5922 // After calling trans->RestartWithAuth(), this is the request we should
5923 // be issuing -- the final header line contains the credentials.
5924 MockWrite data_writes2[] = {
5925 MockWrite("GET / HTTP/1.1\r\n"
5926 "Host: www.google.com\r\n"
5927 "Connection: keep-alive\r\n"
5928 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5929 };
5930
5931 // Lastly, the server responds with the actual content.
5932 MockRead data_reads2[] = {
5933 MockRead("HTTP/1.1 200 OK\r\n"),
5934 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5935 MockRead("Content-Length: 100\r\n\r\n"),
5936 MockRead(false, OK),
5937 };
5938
[email protected]31a2bfe2010-02-09 08:03:395939 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5940 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595941 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575942
5943 TestCompletionCallback callback1;
5944
[email protected]0b0bf032010-09-21 18:08:505945 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5946
[email protected]5a1d7ca2010-04-28 20:12:275947 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575948 EXPECT_EQ(ERR_IO_PENDING, rv);
5949
5950 rv = callback1.WaitForResult();
5951 EXPECT_EQ(OK, rv);
5952
5953 const HttpResponseInfo* response = trans->GetResponseInfo();
5954 EXPECT_FALSE(response == NULL);
5955
5956 // The password prompt info should have been set in response->auth_challenge.
5957 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5958
5959 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5960 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5961 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5962
5963 TestCompletionCallback callback2;
5964
[email protected]13c8a092010-07-29 06:15:445965 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575966 EXPECT_EQ(ERR_IO_PENDING, rv);
5967
5968 rv = callback2.WaitForResult();
5969 EXPECT_EQ(OK, rv);
5970
5971 response = trans->GetResponseInfo();
5972 EXPECT_FALSE(response == NULL);
5973 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5974 EXPECT_EQ(100, response->headers->GetContentLength());
5975}
5976
5977// Test HTTPS connections going through a proxy that sends extra data.
5978TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005979 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575980
5981 HttpRequestInfo request;
5982 request.method = "GET";
5983 request.url = GURL("https://www.google.com/");
5984 request.load_flags = 0;
5985
5986 MockRead proxy_reads[] = {
5987 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5988 MockRead(false, OK)
5989 };
5990
[email protected]31a2bfe2010-02-09 08:03:395991 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595992 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575993
[email protected]5ecc992a42009-11-11 01:41:595994 session_deps.socket_factory.AddSocketDataProvider(&data);
5995 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575996
5997 TestCompletionCallback callback;
5998
5999 session_deps.socket_factory.ResetNextMockIndexes();
6000
6001 scoped_ptr<HttpTransaction> trans(
6002 new HttpNetworkTransaction(CreateSession(&session_deps)));
6003
[email protected]5a1d7ca2010-04-28 20:12:276004 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576005 EXPECT_EQ(ERR_IO_PENDING, rv);
6006
6007 rv = callback.WaitForResult();
6008 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6009}
6010
[email protected]e22e1362009-11-23 21:31:126011TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466012 HttpRequestInfo request;
6013 request.method = "GET";
6014 request.url = GURL("http://www.google.com/");
6015 request.load_flags = 0;
6016
[email protected]cb9bf6ca2011-01-28 13:15:276017 SessionDependencies session_deps;
6018 scoped_ptr<HttpTransaction> trans(
6019 new HttpNetworkTransaction(CreateSession(&session_deps)));
6020
[email protected]e22e1362009-11-23 21:31:126021 MockRead data_reads[] = {
6022 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6023 MockRead(false, OK),
6024 };
[email protected]9492e4a2010-02-24 00:58:466025
6026 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6027 session_deps.socket_factory.AddSocketDataProvider(&data);
6028
6029 TestCompletionCallback callback;
6030
[email protected]5a1d7ca2010-04-28 20:12:276031 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466032 EXPECT_EQ(ERR_IO_PENDING, rv);
6033
6034 EXPECT_EQ(OK, callback.WaitForResult());
6035
6036 const HttpResponseInfo* response = trans->GetResponseInfo();
6037 EXPECT_TRUE(response != NULL);
6038
6039 EXPECT_TRUE(response->headers != NULL);
6040 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6041
6042 std::string response_data;
6043 rv = ReadTransaction(trans.get(), &response_data);
6044 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126045}
6046
[email protected]95d88ffe2010-02-04 21:25:336047TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336048 HttpRequestInfo request;
6049 request.method = "POST";
6050 request.url = GURL("http://www.google.com/upload");
6051 request.upload_data = new UploadData;
6052 request.load_flags = 0;
6053
[email protected]cb9bf6ca2011-01-28 13:15:276054 SessionDependencies session_deps;
6055 scoped_ptr<HttpTransaction> trans(
6056 new HttpNetworkTransaction(CreateSession(&session_deps)));
6057
[email protected]95d88ffe2010-02-04 21:25:336058 FilePath temp_file_path;
6059 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6060 const uint64 kFakeSize = 100000; // file is actually blank
6061
6062 std::vector<UploadData::Element> elements;
6063 UploadData::Element element;
6064 element.SetToFilePath(temp_file_path);
6065 element.SetContentLength(kFakeSize);
6066 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536067 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336068 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6069
6070 MockRead data_reads[] = {
6071 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6072 MockRead("hello world"),
6073 MockRead(false, OK),
6074 };
[email protected]31a2bfe2010-02-09 08:03:396075 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336076 session_deps.socket_factory.AddSocketDataProvider(&data);
6077
6078 TestCompletionCallback callback;
6079
[email protected]5a1d7ca2010-04-28 20:12:276080 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336081 EXPECT_EQ(ERR_IO_PENDING, rv);
6082
6083 rv = callback.WaitForResult();
6084 EXPECT_EQ(OK, rv);
6085
6086 const HttpResponseInfo* response = trans->GetResponseInfo();
6087 EXPECT_TRUE(response != NULL);
6088
6089 EXPECT_TRUE(response->headers != NULL);
6090 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6091
6092 std::string response_data;
6093 rv = ReadTransaction(trans.get(), &response_data);
6094 EXPECT_EQ(OK, rv);
6095 EXPECT_EQ("hello world", response_data);
6096
6097 file_util::Delete(temp_file_path, false);
6098}
6099
[email protected]6624b4622010-03-29 19:58:366100TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276101 HttpRequestInfo request;
6102 request.method = "POST";
6103 request.url = GURL("http://www.google.com/upload");
6104 request.upload_data = new UploadData;
6105 request.load_flags = 0;
6106
[email protected]6624b4622010-03-29 19:58:366107 // If we try to upload an unreadable file, the network stack should report
6108 // the file size as zero and upload zero bytes for that file.
6109 SessionDependencies session_deps;
6110 scoped_ptr<HttpTransaction> trans(
6111 new HttpNetworkTransaction(CreateSession(&session_deps)));
6112
6113 FilePath temp_file;
6114 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6115 std::string temp_file_content("Unreadable file.");
6116 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6117 temp_file_content.length()));
6118 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6119
[email protected]6624b4622010-03-29 19:58:366120 std::vector<UploadData::Element> elements;
6121 UploadData::Element element;
6122 element.SetToFilePath(temp_file);
6123 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536124 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366125
6126 MockRead data_reads[] = {
6127 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6128 MockRead(false, OK),
6129 };
6130 MockWrite data_writes[] = {
6131 MockWrite("POST /upload HTTP/1.1\r\n"
6132 "Host: www.google.com\r\n"
6133 "Connection: keep-alive\r\n"
6134 "Content-Length: 0\r\n\r\n"),
6135 MockWrite(false, OK),
6136 };
6137 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6138 arraysize(data_writes));
6139 session_deps.socket_factory.AddSocketDataProvider(&data);
6140
6141 TestCompletionCallback callback;
6142
[email protected]5a1d7ca2010-04-28 20:12:276143 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366144 EXPECT_EQ(ERR_IO_PENDING, rv);
6145
6146 rv = callback.WaitForResult();
6147 EXPECT_EQ(OK, rv);
6148
6149 const HttpResponseInfo* response = trans->GetResponseInfo();
6150 EXPECT_TRUE(response != NULL);
6151 EXPECT_TRUE(response->headers != NULL);
6152 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6153
6154 file_util::Delete(temp_file, false);
6155}
6156
6157TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276158 HttpRequestInfo request;
6159 request.method = "POST";
6160 request.url = GURL("http://www.google.com/upload");
6161 request.upload_data = new UploadData;
6162 request.load_flags = 0;
6163
[email protected]6624b4622010-03-29 19:58:366164 SessionDependencies session_deps;
6165 scoped_ptr<HttpTransaction> trans(
6166 new HttpNetworkTransaction(CreateSession(&session_deps)));
6167
6168 FilePath temp_file;
6169 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6170 std::string temp_file_contents("Unreadable file.");
6171 std::string unreadable_contents(temp_file_contents.length(), '\0');
6172 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6173 temp_file_contents.length()));
6174
[email protected]6624b4622010-03-29 19:58:366175 std::vector<UploadData::Element> elements;
6176 UploadData::Element element;
6177 element.SetToFilePath(temp_file);
6178 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536179 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366180
6181 MockRead data_reads[] = {
6182 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6183 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6184 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6185
6186 MockRead("HTTP/1.1 200 OK\r\n"),
6187 MockRead("Content-Length: 0\r\n\r\n"),
6188 MockRead(false, OK),
6189 };
6190 MockWrite data_writes[] = {
6191 MockWrite("POST /upload HTTP/1.1\r\n"
6192 "Host: www.google.com\r\n"
6193 "Connection: keep-alive\r\n"
6194 "Content-Length: 16\r\n\r\n"),
6195 MockWrite(false, temp_file_contents.c_str()),
6196
6197 MockWrite("POST /upload HTTP/1.1\r\n"
6198 "Host: www.google.com\r\n"
6199 "Connection: keep-alive\r\n"
6200 "Content-Length: 16\r\n"
6201 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6202 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6203 MockWrite(false, OK),
6204 };
6205 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6206 arraysize(data_writes));
6207 session_deps.socket_factory.AddSocketDataProvider(&data);
6208
6209 TestCompletionCallback callback1;
6210
[email protected]5a1d7ca2010-04-28 20:12:276211 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366212 EXPECT_EQ(ERR_IO_PENDING, rv);
6213
6214 rv = callback1.WaitForResult();
6215 EXPECT_EQ(OK, rv);
6216
6217 const HttpResponseInfo* response = trans->GetResponseInfo();
6218 EXPECT_TRUE(response != NULL);
6219 EXPECT_TRUE(response->headers != NULL);
6220 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6221
6222 // The password prompt info should have been set in response->auth_challenge.
6223 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6224 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6225 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6226 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6227
6228 // Now make the file unreadable and try again.
6229 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6230
6231 TestCompletionCallback callback2;
6232
[email protected]13c8a092010-07-29 06:15:446233 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366234 EXPECT_EQ(ERR_IO_PENDING, rv);
6235
6236 rv = callback2.WaitForResult();
6237 EXPECT_EQ(OK, rv);
6238
6239 response = trans->GetResponseInfo();
6240 EXPECT_TRUE(response != NULL);
6241 EXPECT_TRUE(response->headers != NULL);
6242 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6243 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6244
6245 file_util::Delete(temp_file, false);
6246}
6247
[email protected]aeefc9e82010-02-19 16:18:276248// Tests that changes to Auth realms are treated like auth rejections.
6249TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6250 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276251
6252 HttpRequestInfo request;
6253 request.method = "GET";
6254 request.url = GURL("http://www.google.com/");
6255 request.load_flags = 0;
6256
6257 // First transaction will request a resource and receive a Basic challenge
6258 // with realm="first_realm".
6259 MockWrite data_writes1[] = {
6260 MockWrite("GET / HTTP/1.1\r\n"
6261 "Host: www.google.com\r\n"
6262 "Connection: keep-alive\r\n"
6263 "\r\n"),
6264 };
6265 MockRead data_reads1[] = {
6266 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6267 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6268 "\r\n"),
6269 };
6270
6271 // After calling trans->RestartWithAuth(), provide an Authentication header
6272 // for first_realm. The server will reject and provide a challenge with
6273 // second_realm.
6274 MockWrite data_writes2[] = {
6275 MockWrite("GET / HTTP/1.1\r\n"
6276 "Host: www.google.com\r\n"
6277 "Connection: keep-alive\r\n"
6278 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6279 "\r\n"),
6280 };
6281 MockRead data_reads2[] = {
6282 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6283 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6284 "\r\n"),
6285 };
6286
6287 // This again fails, and goes back to first_realm. Make sure that the
6288 // entry is removed from cache.
6289 MockWrite data_writes3[] = {
6290 MockWrite("GET / HTTP/1.1\r\n"
6291 "Host: www.google.com\r\n"
6292 "Connection: keep-alive\r\n"
6293 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6294 "\r\n"),
6295 };
6296 MockRead data_reads3[] = {
6297 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6298 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6299 "\r\n"),
6300 };
6301
6302 // Try one last time (with the correct password) and get the resource.
6303 MockWrite data_writes4[] = {
6304 MockWrite("GET / HTTP/1.1\r\n"
6305 "Host: www.google.com\r\n"
6306 "Connection: keep-alive\r\n"
6307 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6308 "\r\n"),
6309 };
6310 MockRead data_reads4[] = {
6311 MockRead("HTTP/1.1 200 OK\r\n"
6312 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506313 "Content-Length: 5\r\n"
6314 "\r\n"
6315 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276316 };
6317
6318 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6319 data_writes1, arraysize(data_writes1));
6320 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6321 data_writes2, arraysize(data_writes2));
6322 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6323 data_writes3, arraysize(data_writes3));
6324 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6325 data_writes4, arraysize(data_writes4));
6326 session_deps.socket_factory.AddSocketDataProvider(&data1);
6327 session_deps.socket_factory.AddSocketDataProvider(&data2);
6328 session_deps.socket_factory.AddSocketDataProvider(&data3);
6329 session_deps.socket_factory.AddSocketDataProvider(&data4);
6330
6331 TestCompletionCallback callback1;
6332
[email protected]0b0bf032010-09-21 18:08:506333 scoped_ptr<HttpTransaction> trans(
6334 new HttpNetworkTransaction(CreateSession(&session_deps)));
6335
[email protected]aeefc9e82010-02-19 16:18:276336 // Issue the first request with Authorize headers. There should be a
6337 // password prompt for first_realm waiting to be filled in after the
6338 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276339 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276340 EXPECT_EQ(ERR_IO_PENDING, rv);
6341 rv = callback1.WaitForResult();
6342 EXPECT_EQ(OK, rv);
6343 const HttpResponseInfo* response = trans->GetResponseInfo();
6344 ASSERT_FALSE(response == NULL);
6345 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6346 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6347 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6348 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6349
6350 // Issue the second request with an incorrect password. There should be a
6351 // password prompt for second_realm waiting to be filled in after the
6352 // transaction completes.
6353 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446354 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276355 EXPECT_EQ(ERR_IO_PENDING, rv);
6356 rv = callback2.WaitForResult();
6357 EXPECT_EQ(OK, rv);
6358 response = trans->GetResponseInfo();
6359 ASSERT_FALSE(response == NULL);
6360 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6361 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6362 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6363 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6364
6365 // Issue the third request with another incorrect password. There should be
6366 // a password prompt for first_realm waiting to be filled in. If the password
6367 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6368 // first_realm was not correctly removed.
6369 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446370 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276371 EXPECT_EQ(ERR_IO_PENDING, rv);
6372 rv = callback3.WaitForResult();
6373 EXPECT_EQ(OK, rv);
6374 response = trans->GetResponseInfo();
6375 ASSERT_FALSE(response == NULL);
6376 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6377 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6378 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6379 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6380
6381 // Issue the fourth request with the correct password and username.
6382 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446383 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276384 EXPECT_EQ(ERR_IO_PENDING, rv);
6385 rv = callback4.WaitForResult();
6386 EXPECT_EQ(OK, rv);
6387 response = trans->GetResponseInfo();
6388 ASSERT_FALSE(response == NULL);
6389 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6390}
6391
[email protected]564b4912010-03-09 16:30:426392TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386393 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6394 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426395
[email protected]564b4912010-03-09 16:30:426396 SessionDependencies session_deps;
6397
6398 MockRead data_reads[] = {
6399 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356400 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426401 MockRead("hello world"),
6402 MockRead(false, OK),
6403 };
6404
6405 HttpRequestInfo request;
6406 request.method = "GET";
6407 request.url = GURL("http://www.google.com/");
6408 request.load_flags = 0;
6409
6410 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6411
6412 session_deps.socket_factory.AddSocketDataProvider(&data);
6413
6414 TestCompletionCallback callback;
6415
6416 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6417 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6418
[email protected]5a1d7ca2010-04-28 20:12:276419 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426420 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536421
[email protected]2fbaecf22010-07-22 22:20:356422 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426423 const HttpAlternateProtocols& alternate_protocols =
6424 session->alternate_protocols();
6425 EXPECT_FALSE(
6426 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6427
6428 EXPECT_EQ(OK, callback.WaitForResult());
6429
6430 const HttpResponseInfo* response = trans->GetResponseInfo();
6431 ASSERT_TRUE(response != NULL);
6432 ASSERT_TRUE(response->headers != NULL);
6433 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536434 EXPECT_FALSE(response->was_fetched_via_spdy);
6435 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576436 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:426437
6438 std::string response_data;
6439 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6440 EXPECT_EQ("hello world", response_data);
6441
6442 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6443 const HttpAlternateProtocols::PortProtocolPair alternate =
6444 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6445 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6446 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356447 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426448 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426449
[email protected]8e6441ca2010-08-19 05:56:386450 HttpStreamFactory::set_use_alternate_protocols(false);
6451 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426452}
6453
6454TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386455 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426456 SessionDependencies session_deps;
6457
6458 HttpRequestInfo request;
6459 request.method = "GET";
6460 request.url = GURL("http://www.google.com/");
6461 request.load_flags = 0;
6462
6463 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6464 StaticSocketDataProvider first_data;
6465 first_data.set_connect_data(mock_connect);
6466 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6467
6468 MockRead data_reads[] = {
6469 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6470 MockRead("hello world"),
6471 MockRead(true, OK),
6472 };
6473 StaticSocketDataProvider second_data(
6474 data_reads, arraysize(data_reads), NULL, 0);
6475 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6476
6477 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6478 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6479 // http://crbug.com/37454.
6480 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6481
6482 TestCompletionCallback callback;
6483
6484 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6485
[email protected]2fbaecf22010-07-22 22:20:356486 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426487 HttpAlternateProtocols* alternate_protocols =
6488 session->mutable_alternate_protocols();
6489 alternate_protocols->SetAlternateProtocolFor(
6490 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356491 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426492
6493 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6494
[email protected]5a1d7ca2010-04-28 20:12:276495 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426496 EXPECT_EQ(ERR_IO_PENDING, rv);
6497 EXPECT_EQ(OK, callback.WaitForResult());
6498
6499 const HttpResponseInfo* response = trans->GetResponseInfo();
6500 ASSERT_TRUE(response != NULL);
6501 ASSERT_TRUE(response->headers != NULL);
6502 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6503
6504 std::string response_data;
6505 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6506 EXPECT_EQ("hello world", response_data);
6507
6508 ASSERT_TRUE(
6509 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6510 const HttpAlternateProtocols::PortProtocolPair alternate =
6511 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6512 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386513 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426514}
6515
6516// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6517// says that it does SPDY, but it just does the TLS handshake, but the NPN
6518// response does not indicate SPDY, so we just do standard HTTPS over the port.
6519// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6520// on the original port.
[email protected]a2cb8122010-03-10 17:22:426521// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6522// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536523//
[email protected]a2cb8122010-03-10 17:22:426524// HttpRequestInfo request;
6525// request.method = "GET";
6526// request.url = GURL("http://www.google.com/");
6527// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536528//
[email protected]a2cb8122010-03-10 17:22:426529// MockRead data_reads[] = {
6530// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6531// MockRead("hello world"),
6532// MockRead(true, OK),
6533// };
6534// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6535// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536536//
[email protected]a2cb8122010-03-10 17:22:426537// SSLSocketDataProvider ssl(true, OK);
6538// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536539//
[email protected]a2cb8122010-03-10 17:22:426540// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536541//
[email protected]a2cb8122010-03-10 17:22:426542// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536543//
[email protected]a2cb8122010-03-10 17:22:426544// HostPortPair http_host_port_pair;
6545// http_host_port_pair.host = "www.google.com";
6546// http_host_port_pair.port = 80;
6547// HttpAlternateProtocols* alternate_protocols =
6548// session->mutable_alternate_protocols();
6549// alternate_protocols->SetAlternateProtocolFor(
6550// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066551// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536552//
[email protected]a2cb8122010-03-10 17:22:426553// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536554//
[email protected]5a1d7ca2010-04-28 20:12:276555// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426556// EXPECT_EQ(ERR_IO_PENDING, rv);
6557// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536558//
[email protected]a2cb8122010-03-10 17:22:426559// const HttpResponseInfo* response = trans->GetResponseInfo();
6560// ASSERT_TRUE(response != NULL);
6561// ASSERT_TRUE(response->headers != NULL);
6562// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536563//
[email protected]a2cb8122010-03-10 17:22:426564// std::string response_data;
6565// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6566// EXPECT_EQ("hello world", response_data);
6567// }
6568
6569TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386570 HttpStreamFactory::set_use_alternate_protocols(true);
6571 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426572 SessionDependencies session_deps;
6573
6574 HttpRequestInfo request;
6575 request.method = "GET";
6576 request.url = GURL("http://www.google.com/");
6577 request.load_flags = 0;
6578
[email protected]a2cb8122010-03-10 17:22:426579 StaticSocketDataProvider first_tcp_connect;
6580 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6581
6582 SSLSocketDataProvider ssl(true, OK);
6583 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6584
[email protected]564b4912010-03-09 16:30:426585 MockRead data_reads[] = {
6586 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6587 MockRead("hello world"),
6588 MockRead(true, OK),
6589 };
[email protected]a2cb8122010-03-10 17:22:426590 StaticSocketDataProvider fallback_data(
6591 data_reads, arraysize(data_reads), NULL, 0);
6592 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426593
6594 TestCompletionCallback callback;
6595
6596 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6597
[email protected]2fbaecf22010-07-22 22:20:356598 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426599 HttpAlternateProtocols* alternate_protocols =
6600 session->mutable_alternate_protocols();
6601 alternate_protocols->SetAlternateProtocolFor(
6602 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356603 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426604
6605 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6606
[email protected]5a1d7ca2010-04-28 20:12:276607 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426608 EXPECT_EQ(ERR_IO_PENDING, rv);
6609 EXPECT_EQ(OK, callback.WaitForResult());
6610
6611 const HttpResponseInfo* response = trans->GetResponseInfo();
6612 ASSERT_TRUE(response != NULL);
6613 ASSERT_TRUE(response->headers != NULL);
6614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6615
6616 std::string response_data;
6617 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6618 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386619 HttpStreamFactory::set_next_protos("");
6620 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546621}
6622
6623TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386624 HttpStreamFactory::set_use_alternate_protocols(true);
6625 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546626 SessionDependencies session_deps;
6627
6628 HttpRequestInfo request;
6629 request.method = "GET";
6630 request.url = GURL("http://www.google.com/");
6631 request.load_flags = 0;
6632
6633 MockRead data_reads[] = {
6634 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356635 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546636 MockRead("hello world"),
6637 MockRead(true, OK),
6638 };
6639
6640 StaticSocketDataProvider first_transaction(
6641 data_reads, arraysize(data_reads), NULL, 0);
6642 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6643
6644 SSLSocketDataProvider ssl(true, OK);
6645 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356646 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536647 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546648 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6649
[email protected]2bd93022010-07-17 00:58:446650 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136651 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546652
[email protected]2bd93022010-07-17 00:58:446653 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6654 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546655 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136656 CreateMockRead(*resp),
6657 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546658 MockRead(true, 0, 0),
6659 };
6660
6661 scoped_refptr<DelayedSocketData> spdy_data(
6662 new DelayedSocketData(
6663 1, // wait for one write to finish before reading.
6664 spdy_reads, arraysize(spdy_reads),
6665 spdy_writes, arraysize(spdy_writes)));
6666 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6667
6668 TestCompletionCallback callback;
6669
6670 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6671 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6672
[email protected]5a1d7ca2010-04-28 20:12:276673 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546674 EXPECT_EQ(ERR_IO_PENDING, rv);
6675 EXPECT_EQ(OK, callback.WaitForResult());
6676
6677 const HttpResponseInfo* response = trans->GetResponseInfo();
6678 ASSERT_TRUE(response != NULL);
6679 ASSERT_TRUE(response->headers != NULL);
6680 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6681
6682 std::string response_data;
6683 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6684 EXPECT_EQ("hello world", response_data);
6685
6686 trans.reset(new HttpNetworkTransaction(session));
6687
[email protected]5a1d7ca2010-04-28 20:12:276688 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546689 EXPECT_EQ(ERR_IO_PENDING, rv);
6690 EXPECT_EQ(OK, callback.WaitForResult());
6691
6692 response = trans->GetResponseInfo();
6693 ASSERT_TRUE(response != NULL);
6694 ASSERT_TRUE(response->headers != NULL);
6695 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536696 EXPECT_TRUE(response->was_fetched_via_spdy);
6697 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576698 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546699
6700 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6701 EXPECT_EQ("hello!", response_data);
6702
[email protected]8e6441ca2010-08-19 05:56:386703 HttpStreamFactory::set_next_protos("");
6704 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546705}
6706
[email protected]631f1322010-04-30 17:59:116707class CapturingProxyResolver : public ProxyResolver {
6708 public:
6709 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6710 virtual ~CapturingProxyResolver() {}
6711
6712 virtual int GetProxyForURL(const GURL& url,
6713 ProxyInfo* results,
6714 CompletionCallback* callback,
6715 RequestHandle* request,
6716 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406717 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6718 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426719 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116720 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426721 return OK;
[email protected]631f1322010-04-30 17:59:116722 }
6723
6724 virtual void CancelRequest(RequestHandle request) {
6725 NOTREACHED();
6726 }
6727
[email protected]1e605472010-12-16 21:41:406728 virtual void CancelSetPacScript() {
6729 NOTREACHED();
6730 }
6731
[email protected]24476402010-07-20 20:55:176732 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116733 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426734 return OK;
[email protected]631f1322010-04-30 17:59:116735 }
6736
[email protected]24476402010-07-20 20:55:176737 const std::vector<GURL>& resolved() const { return resolved_; }
6738
6739 private:
[email protected]631f1322010-04-30 17:59:116740 std::vector<GURL> resolved_;
6741
6742 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6743};
6744
[email protected]631f1322010-04-30 17:59:116745TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386746 HttpStreamFactory::set_use_alternate_protocols(true);
6747 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116748
6749 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426750 proxy_config.set_auto_detect(true);
6751 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116752
[email protected]631f1322010-04-30 17:59:116753 CapturingProxyResolver* capturing_proxy_resolver =
6754 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386755 SessionDependencies session_deps(new ProxyService(
6756 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6757 NULL));
[email protected]631f1322010-04-30 17:59:116758
6759 HttpRequestInfo request;
6760 request.method = "GET";
6761 request.url = GURL("http://www.google.com/");
6762 request.load_flags = 0;
6763
6764 MockRead data_reads[] = {
6765 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356766 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116767 MockRead("hello world"),
6768 MockRead(true, OK),
6769 };
6770
6771 StaticSocketDataProvider first_transaction(
6772 data_reads, arraysize(data_reads), NULL, 0);
6773 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6774
6775 SSLSocketDataProvider ssl(true, OK);
6776 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356777 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536778 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116779 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6780
[email protected]2bd93022010-07-17 00:58:446781 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116782 MockWrite spdy_writes[] = {
6783 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6784 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426785 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136786 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116787 };
6788
[email protected]d911f1b2010-05-05 22:39:426789 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6790
[email protected]2bd93022010-07-17 00:58:446791 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6792 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116793 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426794 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136795 CreateMockRead(*resp.get(), 4), // 2, 4
6796 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426797 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116798 };
6799
[email protected]d911f1b2010-05-05 22:39:426800 scoped_refptr<OrderedSocketData> spdy_data(
6801 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116802 spdy_reads, arraysize(spdy_reads),
6803 spdy_writes, arraysize(spdy_writes)));
6804 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6805
6806 TestCompletionCallback callback;
6807
6808 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6809 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6810
6811 int rv = trans->Start(&request, &callback, BoundNetLog());
6812 EXPECT_EQ(ERR_IO_PENDING, rv);
6813 EXPECT_EQ(OK, callback.WaitForResult());
6814
6815 const HttpResponseInfo* response = trans->GetResponseInfo();
6816 ASSERT_TRUE(response != NULL);
6817 ASSERT_TRUE(response->headers != NULL);
6818 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536819 EXPECT_FALSE(response->was_fetched_via_spdy);
6820 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116821
6822 std::string response_data;
6823 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6824 EXPECT_EQ("hello world", response_data);
6825
6826 trans.reset(new HttpNetworkTransaction(session));
6827
6828 rv = trans->Start(&request, &callback, BoundNetLog());
6829 EXPECT_EQ(ERR_IO_PENDING, rv);
6830 EXPECT_EQ(OK, callback.WaitForResult());
6831
6832 response = trans->GetResponseInfo();
6833 ASSERT_TRUE(response != NULL);
6834 ASSERT_TRUE(response->headers != NULL);
6835 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536836 EXPECT_TRUE(response->was_fetched_via_spdy);
6837 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116838
6839 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6840 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426841 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6842 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116843 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426844 EXPECT_EQ("https://www.google.com/",
6845 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116846
[email protected]8e6441ca2010-08-19 05:56:386847 HttpStreamFactory::set_next_protos("");
6848 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116849}
[email protected]631f1322010-04-30 17:59:116850
[email protected]2ff8b312010-04-26 22:20:546851TEST_F(HttpNetworkTransactionTest,
6852 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386853 HttpStreamFactory::set_use_alternate_protocols(true);
6854 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546855 SessionDependencies session_deps;
6856
6857 HttpRequestInfo request;
6858 request.method = "GET";
6859 request.url = GURL("http://www.google.com/");
6860 request.load_flags = 0;
6861
6862 MockRead data_reads[] = {
6863 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356864 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546865 MockRead("hello world"),
6866 MockRead(true, OK),
6867 };
6868
6869 StaticSocketDataProvider first_transaction(
6870 data_reads, arraysize(data_reads), NULL, 0);
6871 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6872
6873 SSLSocketDataProvider ssl(true, OK);
6874 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356875 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536876 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546877 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536878 // Make sure we use ssl for spdy here.
6879 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546880
[email protected]2bd93022010-07-17 00:58:446881 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136882 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546883
[email protected]2bd93022010-07-17 00:58:446884 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6885 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546886 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136887 CreateMockRead(*resp),
6888 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546889 MockRead(true, 0, 0),
6890 };
6891
6892 scoped_refptr<DelayedSocketData> spdy_data(
6893 new DelayedSocketData(
6894 1, // wait for one write to finish before reading.
6895 spdy_reads, arraysize(spdy_reads),
6896 spdy_writes, arraysize(spdy_writes)));
6897 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6898
6899 TestCompletionCallback callback;
6900
6901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6902
6903 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6904
[email protected]5a1d7ca2010-04-28 20:12:276905 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546906 EXPECT_EQ(ERR_IO_PENDING, rv);
6907 EXPECT_EQ(OK, callback.WaitForResult());
6908
6909 const HttpResponseInfo* response = trans->GetResponseInfo();
6910 ASSERT_TRUE(response != NULL);
6911 ASSERT_TRUE(response->headers != NULL);
6912 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6913
6914 std::string response_data;
6915 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6916 EXPECT_EQ("hello world", response_data);
6917
6918 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386919 HostPortPair host_port_pair("www.google.com", 443);
6920 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546921 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276922 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6923 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276924 scoped_refptr<TCPSocketParams> tcp_params(
6925 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386926
6927 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6928 EXPECT_EQ(ERR_IO_PENDING,
6929 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6930 &callback, session->tcp_socket_pool(),
6931 BoundNetLog()));
6932 EXPECT_EQ(OK, callback.WaitForResult());
6933
6934 SSLConfig ssl_config;
6935 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6936 ClientSocket* socket = connection->release_socket();
[email protected]7ab5bbd12010-10-19 13:33:216937 socket = session->socket_factory()->CreateSSLClientSocket(
[email protected]822581d2010-12-16 17:27:156938 socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */,
6939 session->cert_verifier());
[email protected]02b0c342010-09-25 21:09:386940 connection->set_socket(socket);
6941 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6942 EXPECT_EQ(OK, callback.WaitForResult());
6943
6944 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6945 true, OK));
6946
[email protected]2ff8b312010-04-26 22:20:546947 trans.reset(new HttpNetworkTransaction(session));
6948
[email protected]5a1d7ca2010-04-28 20:12:276949 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546950 EXPECT_EQ(ERR_IO_PENDING, rv);
6951 EXPECT_EQ(OK, callback.WaitForResult());
6952
6953 response = trans->GetResponseInfo();
6954 ASSERT_TRUE(response != NULL);
6955 ASSERT_TRUE(response->headers != NULL);
6956 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536957 EXPECT_TRUE(response->was_fetched_via_spdy);
6958 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576959 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546960
6961 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6962 EXPECT_EQ("hello!", response_data);
6963
[email protected]8e6441ca2010-08-19 05:56:386964 HttpStreamFactory::set_next_protos("");
6965 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426966}
6967
[email protected]044de0642010-06-17 10:42:156968// GenerateAuthToken is a mighty big test.
6969// It tests all permutation of GenerateAuthToken behavior:
6970// - Synchronous and Asynchronous completion.
6971// - OK or error on completion.
6972// - Direct connection, non-authenticating proxy, and authenticating proxy.
6973// - HTTP or HTTPS backend (to include proxy tunneling).
6974// - Non-authenticating and authenticating backend.
6975//
6976// In all, there are 44 reasonable permuations (for example, if there are
6977// problems generating an auth token for an authenticating proxy, we don't
6978// need to test all permutations of the backend server).
6979//
6980// The test proceeds by going over each of the configuration cases, and
6981// potentially running up to three rounds in each of the tests. The TestConfig
6982// specifies both the configuration for the test as well as the expectations
6983// for the results.
6984TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506985 static const char kServer[] = "http://www.example.com";
6986 static const char kSecureServer[] = "https://www.example.com";
6987 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156988 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6989
6990 enum AuthTiming {
6991 AUTH_NONE,
6992 AUTH_SYNC,
6993 AUTH_ASYNC,
6994 };
6995
6996 const MockWrite kGet(
6997 "GET / HTTP/1.1\r\n"
6998 "Host: www.example.com\r\n"
6999 "Connection: keep-alive\r\n\r\n");
7000 const MockWrite kGetProxy(
7001 "GET http://www.example.com/ HTTP/1.1\r\n"
7002 "Host: www.example.com\r\n"
7003 "Proxy-Connection: keep-alive\r\n\r\n");
7004 const MockWrite kGetAuth(
7005 "GET / HTTP/1.1\r\n"
7006 "Host: www.example.com\r\n"
7007 "Connection: keep-alive\r\n"
7008 "Authorization: auth_token\r\n\r\n");
7009 const MockWrite kGetProxyAuth(
7010 "GET http://www.example.com/ HTTP/1.1\r\n"
7011 "Host: www.example.com\r\n"
7012 "Proxy-Connection: keep-alive\r\n"
7013 "Proxy-Authorization: auth_token\r\n\r\n");
7014 const MockWrite kGetAuthThroughProxy(
7015 "GET http://www.example.com/ HTTP/1.1\r\n"
7016 "Host: www.example.com\r\n"
7017 "Proxy-Connection: keep-alive\r\n"
7018 "Authorization: auth_token\r\n\r\n");
7019 const MockWrite kGetAuthWithProxyAuth(
7020 "GET http://www.example.com/ HTTP/1.1\r\n"
7021 "Host: www.example.com\r\n"
7022 "Proxy-Connection: keep-alive\r\n"
7023 "Proxy-Authorization: auth_token\r\n"
7024 "Authorization: auth_token\r\n\r\n");
7025 const MockWrite kConnect(
7026 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7027 "Host: www.example.com\r\n"
7028 "Proxy-Connection: keep-alive\r\n\r\n");
7029 const MockWrite kConnectProxyAuth(
7030 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7031 "Host: www.example.com\r\n"
7032 "Proxy-Connection: keep-alive\r\n"
7033 "Proxy-Authorization: auth_token\r\n\r\n");
7034
7035 const MockRead kSuccess(
7036 "HTTP/1.1 200 OK\r\n"
7037 "Content-Type: text/html; charset=iso-8859-1\r\n"
7038 "Content-Length: 3\r\n\r\n"
7039 "Yes");
7040 const MockRead kFailure(
7041 "Should not be called.");
7042 const MockRead kServerChallenge(
7043 "HTTP/1.1 401 Unauthorized\r\n"
7044 "WWW-Authenticate: Mock realm=server\r\n"
7045 "Content-Type: text/html; charset=iso-8859-1\r\n"
7046 "Content-Length: 14\r\n\r\n"
7047 "Unauthorized\r\n");
7048 const MockRead kProxyChallenge(
7049 "HTTP/1.1 407 Unauthorized\r\n"
7050 "Proxy-Authenticate: Mock realm=proxy\r\n"
7051 "Proxy-Connection: close\r\n"
7052 "Content-Type: text/html; charset=iso-8859-1\r\n"
7053 "Content-Length: 14\r\n\r\n"
7054 "Unauthorized\r\n");
7055 const MockRead kProxyConnected(
7056 "HTTP/1.1 200 Connection Established\r\n\r\n");
7057
7058 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7059 // no constructors, but the C++ compiler on Windows warns about
7060 // unspecified data in compound literals. So, moved to using constructors,
7061 // and TestRound's created with the default constructor should not be used.
7062 struct TestRound {
7063 TestRound()
7064 : expected_rv(ERR_UNEXPECTED),
7065 extra_write(NULL),
7066 extra_read(NULL) {
7067 }
7068 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7069 int expected_rv_arg)
7070 : write(write_arg),
7071 read(read_arg),
7072 expected_rv(expected_rv_arg),
7073 extra_write(NULL),
7074 extra_read(NULL) {
7075 }
7076 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7077 int expected_rv_arg, const MockWrite* extra_write_arg,
7078 const MockWrite* extra_read_arg)
7079 : write(write_arg),
7080 read(read_arg),
7081 expected_rv(expected_rv_arg),
7082 extra_write(extra_write_arg),
7083 extra_read(extra_read_arg) {
7084 }
7085 MockWrite write;
7086 MockRead read;
7087 int expected_rv;
7088 const MockWrite* extra_write;
7089 const MockRead* extra_read;
7090 };
7091
7092 static const int kNoSSL = 500;
7093
7094 struct TestConfig {
7095 const char* proxy_url;
7096 AuthTiming proxy_auth_timing;
7097 int proxy_auth_rv;
7098 const char* server_url;
7099 AuthTiming server_auth_timing;
7100 int server_auth_rv;
7101 int num_auth_rounds;
7102 int first_ssl_round;
7103 TestRound rounds[3];
7104 } test_configs[] = {
7105 // Non-authenticating HTTP server with a direct connection.
7106 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7107 { TestRound(kGet, kSuccess, OK)}},
7108 // Authenticating HTTP server with a direct connection.
7109 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7110 { TestRound(kGet, kServerChallenge, OK),
7111 TestRound(kGetAuth, kSuccess, OK)}},
7112 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7113 { TestRound(kGet, kServerChallenge, OK),
7114 TestRound(kGetAuth, kFailure, kAuthErr)}},
7115 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7116 { TestRound(kGet, kServerChallenge, OK),
7117 TestRound(kGetAuth, kSuccess, OK)}},
7118 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7119 { TestRound(kGet, kServerChallenge, OK),
7120 TestRound(kGetAuth, kFailure, kAuthErr)}},
7121 // Non-authenticating HTTP server through a non-authenticating proxy.
7122 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7123 { TestRound(kGetProxy, kSuccess, OK)}},
7124 // Authenticating HTTP server through a non-authenticating proxy.
7125 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7126 { TestRound(kGetProxy, kServerChallenge, OK),
7127 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7128 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7129 { TestRound(kGetProxy, kServerChallenge, OK),
7130 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7131 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7132 { TestRound(kGetProxy, kServerChallenge, OK),
7133 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7134 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7135 { TestRound(kGetProxy, kServerChallenge, OK),
7136 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7137 // Non-authenticating HTTP server through an authenticating proxy.
7138 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7139 { TestRound(kGetProxy, kProxyChallenge, OK),
7140 TestRound(kGetProxyAuth, kSuccess, OK)}},
7141 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7142 { TestRound(kGetProxy, kProxyChallenge, OK),
7143 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7144 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7145 { TestRound(kGetProxy, kProxyChallenge, OK),
7146 TestRound(kGetProxyAuth, kSuccess, OK)}},
7147 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7148 { TestRound(kGetProxy, kProxyChallenge, OK),
7149 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7150 // Authenticating HTTP server through an authenticating proxy.
7151 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7152 { TestRound(kGetProxy, kProxyChallenge, OK),
7153 TestRound(kGetProxyAuth, kServerChallenge, OK),
7154 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7155 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7156 { TestRound(kGetProxy, kProxyChallenge, OK),
7157 TestRound(kGetProxyAuth, kServerChallenge, OK),
7158 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7159 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7160 { TestRound(kGetProxy, kProxyChallenge, OK),
7161 TestRound(kGetProxyAuth, kServerChallenge, OK),
7162 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7163 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7164 { TestRound(kGetProxy, kProxyChallenge, OK),
7165 TestRound(kGetProxyAuth, kServerChallenge, OK),
7166 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7167 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7168 { TestRound(kGetProxy, kProxyChallenge, OK),
7169 TestRound(kGetProxyAuth, kServerChallenge, OK),
7170 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7171 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7172 { TestRound(kGetProxy, kProxyChallenge, OK),
7173 TestRound(kGetProxyAuth, kServerChallenge, OK),
7174 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7175 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7176 { TestRound(kGetProxy, kProxyChallenge, OK),
7177 TestRound(kGetProxyAuth, kServerChallenge, OK),
7178 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7179 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7180 { TestRound(kGetProxy, kProxyChallenge, OK),
7181 TestRound(kGetProxyAuth, kServerChallenge, OK),
7182 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7183 // Non-authenticating HTTPS server with a direct connection.
7184 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7185 { TestRound(kGet, kSuccess, OK)}},
7186 // Authenticating HTTPS server with a direct connection.
7187 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7188 { TestRound(kGet, kServerChallenge, OK),
7189 TestRound(kGetAuth, kSuccess, OK)}},
7190 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7191 { TestRound(kGet, kServerChallenge, OK),
7192 TestRound(kGetAuth, kFailure, kAuthErr)}},
7193 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7194 { TestRound(kGet, kServerChallenge, OK),
7195 TestRound(kGetAuth, kSuccess, OK)}},
7196 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7197 { TestRound(kGet, kServerChallenge, OK),
7198 TestRound(kGetAuth, kFailure, kAuthErr)}},
7199 // Non-authenticating HTTPS server with a non-authenticating proxy.
7200 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7201 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7202 // Authenticating HTTPS server through a non-authenticating proxy.
7203 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7204 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7205 TestRound(kGetAuth, kSuccess, OK)}},
7206 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7207 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7208 TestRound(kGetAuth, kFailure, kAuthErr)}},
7209 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7210 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7211 TestRound(kGetAuth, kSuccess, OK)}},
7212 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7213 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7214 TestRound(kGetAuth, kFailure, kAuthErr)}},
7215 // Non-Authenticating HTTPS server through an authenticating proxy.
7216 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7217 { TestRound(kConnect, kProxyChallenge, OK),
7218 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7219 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7220 { TestRound(kConnect, kProxyChallenge, OK),
7221 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7222 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7223 { TestRound(kConnect, kProxyChallenge, OK),
7224 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7225 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7226 { TestRound(kConnect, kProxyChallenge, OK),
7227 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7228 // Authenticating HTTPS server through an authenticating proxy.
7229 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7230 { TestRound(kConnect, kProxyChallenge, OK),
7231 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7232 &kGet, &kServerChallenge),
7233 TestRound(kGetAuth, kSuccess, OK)}},
7234 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7235 { TestRound(kConnect, kProxyChallenge, OK),
7236 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7237 &kGet, &kServerChallenge),
7238 TestRound(kGetAuth, kFailure, kAuthErr)}},
7239 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7240 { TestRound(kConnect, kProxyChallenge, OK),
7241 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7242 &kGet, &kServerChallenge),
7243 TestRound(kGetAuth, kSuccess, OK)}},
7244 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7245 { TestRound(kConnect, kProxyChallenge, OK),
7246 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7247 &kGet, &kServerChallenge),
7248 TestRound(kGetAuth, kFailure, kAuthErr)}},
7249 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7250 { TestRound(kConnect, kProxyChallenge, OK),
7251 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7252 &kGet, &kServerChallenge),
7253 TestRound(kGetAuth, kSuccess, OK)}},
7254 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7255 { TestRound(kConnect, kProxyChallenge, OK),
7256 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7257 &kGet, &kServerChallenge),
7258 TestRound(kGetAuth, kFailure, kAuthErr)}},
7259 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7260 { TestRound(kConnect, kProxyChallenge, OK),
7261 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7262 &kGet, &kServerChallenge),
7263 TestRound(kGetAuth, kSuccess, OK)}},
7264 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7265 { TestRound(kConnect, kProxyChallenge, OK),
7266 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7267 &kGet, &kServerChallenge),
7268 TestRound(kGetAuth, kFailure, kAuthErr)}},
7269 };
7270
7271 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007272 HttpAuthHandlerMock::Factory* auth_factory(
7273 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157274 session_deps.http_auth_handler_factory.reset(auth_factory);
7275
7276 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7277 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267278
7279 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157280 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007281 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157282 std::string auth_challenge = "Mock realm=proxy";
7283 GURL origin(test_config.proxy_url);
7284 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7285 auth_challenge.end());
7286 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7287 origin, BoundNetLog());
7288 auth_handler->SetGenerateExpectation(
7289 test_config.proxy_auth_timing == AUTH_ASYNC,
7290 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157291 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7292 }
7293 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007294 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157295 std::string auth_challenge = "Mock realm=server";
7296 GURL origin(test_config.server_url);
7297 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7298 auth_challenge.end());
7299 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7300 origin, BoundNetLog());
7301 auth_handler->SetGenerateExpectation(
7302 test_config.server_auth_timing == AUTH_ASYNC,
7303 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157304 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7305 }
7306 if (test_config.proxy_url) {
7307 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:007308 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:157309 } else {
[email protected]ebeefff32010-09-15 05:10:027310 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:157311 }
7312
7313 HttpRequestInfo request;
7314 request.method = "GET";
7315 request.url = GURL(test_config.server_url);
7316 request.load_flags = 0;
7317
[email protected]0b0bf032010-09-21 18:08:507318 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7319 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157320
7321 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7322 const TestRound& read_write_round = test_config.rounds[round];
7323
7324 // Set up expected reads and writes.
7325 MockRead reads[2];
7326 reads[0] = read_write_round.read;
7327 size_t length_reads = 1;
7328 if (read_write_round.extra_read) {
7329 reads[1] = *read_write_round.extra_read;
7330 length_reads = 2;
7331 }
7332
7333 MockWrite writes[2];
7334 writes[0] = read_write_round.write;
7335 size_t length_writes = 1;
7336 if (read_write_round.extra_write) {
7337 writes[1] = *read_write_round.extra_write;
7338 length_writes = 2;
7339 }
7340 StaticSocketDataProvider data_provider(
7341 reads, length_reads, writes, length_writes);
7342 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7343
7344 // Add an SSL sequence if necessary.
7345 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7346 if (round >= test_config.first_ssl_round)
7347 session_deps.socket_factory.AddSSLSocketDataProvider(
7348 &ssl_socket_data_provider);
7349
7350 // Start or restart the transaction.
7351 TestCompletionCallback callback;
7352 int rv;
7353 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507354 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157355 } else {
[email protected]0b0bf032010-09-21 18:08:507356 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157357 }
7358 if (rv == ERR_IO_PENDING)
7359 rv = callback.WaitForResult();
7360
7361 // Compare results with expected data.
7362 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507363 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157364 if (read_write_round.expected_rv == OK) {
7365 EXPECT_FALSE(response == NULL);
7366 } else {
7367 EXPECT_TRUE(response == NULL);
7368 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7369 continue;
7370 }
7371 if (round + 1 < test_config.num_auth_rounds) {
7372 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7373 } else {
7374 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7375 }
7376 }
[email protected]e5ae96a2010-04-14 20:12:457377 }
7378}
7379
[email protected]c871bce92010-07-15 21:51:147380TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7381 // Do multi-round authentication and make sure it works correctly.
7382 SessionDependencies session_deps;
7383 HttpAuthHandlerMock::Factory* auth_factory(
7384 new HttpAuthHandlerMock::Factory());
7385 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:027386 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:147387 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7388 session_deps.host_resolver->set_synchronous_mode(true);
7389
7390 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7391 auth_handler->set_connection_based(true);
7392 std::string auth_challenge = "Mock realm=server";
7393 GURL origin("http://www.example.com");
7394 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7395 auth_challenge.end());
7396 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7397 origin, BoundNetLog());
7398 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7399
[email protected]c871bce92010-07-15 21:51:147400 int rv = OK;
7401 const HttpResponseInfo* response = NULL;
7402 HttpRequestInfo request;
7403 request.method = "GET";
7404 request.url = origin;
7405 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277406
7407 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7408 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147409 TestCompletionCallback callback;
7410
7411 const MockWrite kGet(
7412 "GET / HTTP/1.1\r\n"
7413 "Host: www.example.com\r\n"
7414 "Connection: keep-alive\r\n\r\n");
7415 const MockWrite kGetAuth(
7416 "GET / HTTP/1.1\r\n"
7417 "Host: www.example.com\r\n"
7418 "Connection: keep-alive\r\n"
7419 "Authorization: auth_token\r\n\r\n");
7420
7421 const MockRead kServerChallenge(
7422 "HTTP/1.1 401 Unauthorized\r\n"
7423 "WWW-Authenticate: Mock realm=server\r\n"
7424 "Content-Type: text/html; charset=iso-8859-1\r\n"
7425 "Content-Length: 14\r\n\r\n"
7426 "Unauthorized\r\n");
7427 const MockRead kSuccess(
7428 "HTTP/1.1 200 OK\r\n"
7429 "Content-Type: text/html; charset=iso-8859-1\r\n"
7430 "Content-Length: 3\r\n\r\n"
7431 "Yes");
7432
7433 MockWrite writes[] = {
7434 // First round
7435 kGet,
7436 // Second round
7437 kGetAuth,
7438 // Third round
7439 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307440 // Fourth round
7441 kGetAuth
[email protected]c871bce92010-07-15 21:51:147442 };
7443 MockRead reads[] = {
7444 // First round
7445 kServerChallenge,
7446 // Second round
7447 kServerChallenge,
7448 // Third round
[email protected]eca50e122010-09-11 14:03:307449 kServerChallenge,
7450 // Fourth round
[email protected]c871bce92010-07-15 21:51:147451 kSuccess,
7452 };
7453 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7454 writes, arraysize(writes));
7455 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7456
7457 // First round
7458 auth_handler->SetGenerateExpectation(false, OK);
7459 rv = trans->Start(&request, &callback, BoundNetLog());
7460 if (rv == ERR_IO_PENDING)
7461 rv = callback.WaitForResult();
7462 EXPECT_EQ(OK, rv);
7463 response = trans->GetResponseInfo();
7464 ASSERT_FALSE(response == NULL);
7465 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7466
7467 // Second round
7468 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447469 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147470 if (rv == ERR_IO_PENDING)
7471 rv = callback.WaitForResult();
7472 EXPECT_EQ(OK, rv);
7473 response = trans->GetResponseInfo();
7474 ASSERT_FALSE(response == NULL);
7475 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7476
7477 // Third round
7478 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447479 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147480 if (rv == ERR_IO_PENDING)
7481 rv = callback.WaitForResult();
7482 EXPECT_EQ(OK, rv);
7483 response = trans->GetResponseInfo();
7484 ASSERT_FALSE(response == NULL);
7485 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:307486
7487 // Fourth round
7488 auth_handler->SetGenerateExpectation(false, OK);
7489 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7490 if (rv == ERR_IO_PENDING)
7491 rv = callback.WaitForResult();
7492 EXPECT_EQ(OK, rv);
7493 response = trans->GetResponseInfo();
7494 ASSERT_FALSE(response == NULL);
7495 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:147496}
7497
[email protected]aeaca1f2010-04-20 22:05:217498class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7499 public:
[email protected]06650c52010-06-03 00:49:177500 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217501 : fail_all_(fail_all) {
7502 }
7503
7504 virtual MockRead GetNextRead() {
7505 if (fail_all_)
7506 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7507
7508 return MockRead(false /* async */,
7509 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7510 }
7511
7512 virtual MockWriteResult OnWrite(const std::string& data) {
7513 return MockWriteResult(false /* async */, data.size());
7514 }
7515
7516 void Reset() {
7517 }
7518
7519 private:
7520 const bool fail_all_;
7521};
7522
7523// Test that we restart a connection when we see a decompression failure from
7524// the peer during the handshake. (In the real world we'll restart with SSLv3
7525// and we won't offer DEFLATE in that case.)
7526TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7527 HttpRequestInfo request;
7528 request.method = "GET";
7529 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7530 request.load_flags = 0;
7531
7532 SessionDependencies session_deps;
7533 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7534 false /* fail all reads */);
7535 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7536 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117537 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217538 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7539 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7540 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7541 session_deps.socket_factory.AddSSLSocketDataProvider(
7542 &ssl_socket_data_provider1);
7543 session_deps.socket_factory.AddSSLSocketDataProvider(
7544 &ssl_socket_data_provider2);
7545
[email protected]e60e47a2010-07-14 03:37:187546 // Work around http://crbug.com/37454
7547 StaticSocketDataProvider bug37454_connection;
7548 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7549 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7550
[email protected]aeaca1f2010-04-20 22:05:217551 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7552 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7553 TestCompletionCallback callback;
7554
[email protected]5a1d7ca2010-04-28 20:12:277555 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217556 EXPECT_EQ(ERR_IO_PENDING, rv);
7557 EXPECT_EQ(OK, callback.WaitForResult());
7558
7559 const HttpResponseInfo* response = trans->GetResponseInfo();
7560 ASSERT_TRUE(response != NULL);
7561 ASSERT_TRUE(response->headers != NULL);
7562 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7563
7564 std::string response_data;
7565 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7566 EXPECT_EQ("ok.", response_data);
7567}
7568
7569// Test that we restart a connection if we get a decompression failure from the
7570// peer while reading the first bytes from the connection. This occurs when the
7571// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7572// in the handshake.
7573TEST_F(HttpNetworkTransactionTest,
7574 RestartAfterTLSDecompressionFailureWithFalseStart) {
7575 HttpRequestInfo request;
7576 request.method = "GET";
7577 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7578 request.load_flags = 0;
7579
7580 SessionDependencies session_deps;
7581 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7582 true /* fail all reads */);
7583 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7584 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7585 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7586 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7587 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7588 session_deps.socket_factory.AddSSLSocketDataProvider(
7589 &ssl_socket_data_provider1);
7590 session_deps.socket_factory.AddSSLSocketDataProvider(
7591 &ssl_socket_data_provider2);
7592
7593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7594 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7595 TestCompletionCallback callback;
7596
[email protected]5a1d7ca2010-04-28 20:12:277597 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217598 EXPECT_EQ(ERR_IO_PENDING, rv);
7599 EXPECT_EQ(OK, callback.WaitForResult());
7600
7601 const HttpResponseInfo* response = trans->GetResponseInfo();
7602 ASSERT_TRUE(response != NULL);
7603 ASSERT_TRUE(response->headers != NULL);
7604 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7605
7606 std::string response_data;
7607 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7608 EXPECT_EQ("ok.", response_data);
7609}
7610
[email protected]65041fa2010-05-21 06:56:537611// This tests the case that a request is issued via http instead of spdy after
7612// npn is negotiated.
7613TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387614 HttpStreamFactory::set_use_alternate_protocols(true);
7615 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537616 SessionDependencies session_deps;
7617 HttpRequestInfo request;
7618 request.method = "GET";
7619 request.url = GURL("https://www.google.com/");
7620 request.load_flags = 0;
7621
7622 MockWrite data_writes[] = {
7623 MockWrite("GET / HTTP/1.1\r\n"
7624 "Host: www.google.com\r\n"
7625 "Connection: keep-alive\r\n\r\n"),
7626 };
7627
7628 MockRead data_reads[] = {
7629 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357630 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537631 MockRead("hello world"),
7632 MockRead(false, OK),
7633 };
7634
7635 SSLSocketDataProvider ssl(true, OK);
7636 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7637 ssl.next_proto = "http/1.1";
7638
7639 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7640
7641 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7642 data_writes, arraysize(data_writes));
7643 session_deps.socket_factory.AddSocketDataProvider(&data);
7644
7645 TestCompletionCallback callback;
7646
7647 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7648 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7649
7650 int rv = trans->Start(&request, &callback, BoundNetLog());
7651
7652 EXPECT_EQ(ERR_IO_PENDING, rv);
7653 EXPECT_EQ(OK, callback.WaitForResult());
7654
7655 const HttpResponseInfo* response = trans->GetResponseInfo();
7656 ASSERT_TRUE(response != NULL);
7657 ASSERT_TRUE(response->headers != NULL);
7658 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7659
7660 std::string response_data;
7661 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7662 EXPECT_EQ("hello world", response_data);
7663
7664 EXPECT_FALSE(response->was_fetched_via_spdy);
7665 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577666 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537667
[email protected]8e6441ca2010-08-19 05:56:387668 HttpStreamFactory::set_next_protos("");
7669 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537670}
[email protected]26ef6582010-06-24 02:30:477671
7672TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7673 // Simulate the SSL handshake completing with an NPN negotiation
7674 // followed by an immediate server closing of the socket.
7675 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387676 HttpStreamFactory::set_use_alternate_protocols(true);
7677 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477678 SessionDependencies session_deps;
7679
7680 HttpRequestInfo request;
7681 request.method = "GET";
7682 request.url = GURL("https://www.google.com/");
7683 request.load_flags = 0;
7684
7685 SSLSocketDataProvider ssl(true, OK);
7686 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357687 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477688 ssl.was_npn_negotiated = true;
7689 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7690
[email protected]2bd93022010-07-17 00:58:447691 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137692 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477693
7694 MockRead spdy_reads[] = {
7695 MockRead(false, 0, 0) // Not async - return 0 immediately.
7696 };
7697
7698 scoped_refptr<DelayedSocketData> spdy_data(
7699 new DelayedSocketData(
7700 0, // don't wait in this case, immediate hangup.
7701 spdy_reads, arraysize(spdy_reads),
7702 spdy_writes, arraysize(spdy_writes)));
7703 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7704
7705 TestCompletionCallback callback;
7706
7707 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7708 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7709
7710 int rv = trans->Start(&request, &callback, BoundNetLog());
7711 EXPECT_EQ(ERR_IO_PENDING, rv);
7712 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7713
[email protected]8e6441ca2010-08-19 05:56:387714 HttpStreamFactory::set_next_protos("");
7715 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477716}
[email protected]65d34382010-07-01 18:12:267717
[email protected]f45c1ee2010-08-03 00:54:307718TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7719 // This test ensures that the URL passed into the proxy is upgraded
7720 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387721 HttpStreamFactory::set_use_alternate_protocols(true);
7722 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307723 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7724
[email protected]81cdfcd2010-10-16 00:49:007725 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307726 HttpAuthHandlerMock::Factory* auth_factory =
7727 new HttpAuthHandlerMock::Factory();
7728 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7729 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7730 auth_factory->set_do_init_from_challenge(true);
7731 session_deps.http_auth_handler_factory.reset(auth_factory);
7732
7733 HttpRequestInfo request;
7734 request.method = "GET";
7735 request.url = GURL("http://www.google.com");
7736 request.load_flags = 0;
7737
7738 // First round goes unauthenticated through the proxy.
7739 MockWrite data_writes_1[] = {
7740 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7741 "Host: www.google.com\r\n"
7742 "Proxy-Connection: keep-alive\r\n"
7743 "\r\n"),
7744 };
7745 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597746 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307747 MockRead("HTTP/1.1 200 OK\r\n"
7748 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7749 "Proxy-Connection: close\r\n"
7750 "\r\n"),
7751 };
7752 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7753 data_writes_1, arraysize(data_writes_1));
7754
7755 // Second round tries to tunnel to www.google.com due to the
7756 // Alternate-Protocol announcement in the first round. It fails due
7757 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597758 // After the failure, a tunnel is established to www.google.com using
7759 // Proxy-Authorization headers. There is then a SPDY request round.
7760 //
7761 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7762 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7763 // does a Disconnect and Connect on the same socket, rather than trying
7764 // to obtain a new one.
7765 //
7766 // NOTE: Originally, the proxy response to the second CONNECT request
7767 // simply returned another 407 so the unit test could skip the SSL connection
7768 // establishment and SPDY framing issues. Alas, the
7769 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307770 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597771
[email protected]f45c1ee2010-08-03 00:54:307772 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7773 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7774 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7775
[email protected]394816e92010-08-03 07:38:597776 MockWrite data_writes_2[] = {
7777 // First connection attempt without Proxy-Authorization.
7778 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7779 "Host: www.google.com\r\n"
7780 "Proxy-Connection: keep-alive\r\n"
7781 "\r\n"),
7782
7783 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307784 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7785 "Host: www.google.com\r\n"
7786 "Proxy-Connection: keep-alive\r\n"
7787 "Proxy-Authorization: auth_token\r\n"
7788 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307789
[email protected]394816e92010-08-03 07:38:597790 // SPDY request
7791 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307792 };
[email protected]394816e92010-08-03 07:38:597793 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7794 "Proxy-Authenticate: Mock\r\n"
7795 "Proxy-Connection: close\r\n"
7796 "\r\n");
7797 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7798 MockRead data_reads_2[] = {
7799 // First connection attempt fails
7800 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7801 MockRead(true, kRejectConnectResponse,
7802 arraysize(kRejectConnectResponse) - 1, 1),
7803
7804 // Second connection attempt passes
7805 MockRead(true, kAcceptConnectResponse,
7806 arraysize(kAcceptConnectResponse) -1, 4),
7807
7808 // SPDY response
7809 CreateMockRead(*resp.get(), 6),
7810 CreateMockRead(*data.get(), 6),
7811 MockRead(true, 0, 0, 6),
7812 };
7813 scoped_refptr<OrderedSocketData> data_2(
7814 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7815 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307816
7817 SSLSocketDataProvider ssl(true, OK);
7818 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7819 ssl.next_proto = "spdy/2";
7820 ssl.was_npn_negotiated = true;
7821
7822 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597823 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307824 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7825 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7826
7827 // First round should work and provide the Alternate-Protocol state.
7828 TestCompletionCallback callback_1;
7829 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7830 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7831 EXPECT_EQ(ERR_IO_PENDING, rv);
7832 EXPECT_EQ(OK, callback_1.WaitForResult());
7833
7834 // Second round should attempt a tunnel connect and get an auth challenge.
7835 TestCompletionCallback callback_2;
7836 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7837 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7838 EXPECT_EQ(ERR_IO_PENDING, rv);
7839 EXPECT_EQ(OK, callback_2.WaitForResult());
7840 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7841 ASSERT_FALSE(response == NULL);
7842 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7843
7844 // Restart with auth. Tunnel should work and response received.
7845 TestCompletionCallback callback_3;
7846 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7847 EXPECT_EQ(ERR_IO_PENDING, rv);
7848 EXPECT_EQ(OK, callback_3.WaitForResult());
7849
7850 // After all that work, these two lines (or actually, just the scheme) are
7851 // what this test is all about. Make sure it happens correctly.
7852 const GURL& request_url = auth_handler->request_url();
7853 EXPECT_EQ("https", request_url.scheme());
7854 EXPECT_EQ("www.google.com", request_url.host());
7855
[email protected]8e6441ca2010-08-19 05:56:387856 HttpStreamFactory::set_next_protos("");
7857 HttpStreamFactory::set_use_alternate_protocols(false);
7858}
7859
7860// Test that if we cancel the transaction as the connection is completing, that
7861// everything tears down correctly.
7862TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7863 // Setup everything about the connection to complete synchronously, so that
7864 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7865 // for is the callback from the HttpStreamRequest.
7866 // Then cancel the transaction.
7867 // Verify that we don't crash.
7868 MockConnect mock_connect(false, OK);
7869 MockRead data_reads[] = {
7870 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7871 MockRead(false, "hello world"),
7872 MockRead(false, OK),
7873 };
7874
[email protected]8e6441ca2010-08-19 05:56:387875 HttpRequestInfo request;
7876 request.method = "GET";
7877 request.url = GURL("http://www.google.com/");
7878 request.load_flags = 0;
7879
[email protected]cb9bf6ca2011-01-28 13:15:277880 SessionDependencies session_deps;
7881 session_deps.host_resolver->set_synchronous_mode(true);
7882 scoped_ptr<HttpTransaction> trans(
7883 new HttpNetworkTransaction(CreateSession(&session_deps)));
7884
[email protected]8e6441ca2010-08-19 05:56:387885 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7886 data.set_connect_data(mock_connect);
7887 session_deps.socket_factory.AddSocketDataProvider(&data);
7888
7889 TestCompletionCallback callback;
7890
7891 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7892 int rv = trans->Start(&request, &callback, log.bound());
7893 EXPECT_EQ(ERR_IO_PENDING, rv);
7894 trans.reset(); // Cancel the transaction here.
7895
7896 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307897}
7898
[email protected]76a505b2010-08-25 06:23:007899// Test a basic GET request through a proxy.
7900TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007901 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007902 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7903 session_deps.net_log = log.bound().net_log();
7904 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7905
[email protected]76a505b2010-08-25 06:23:007906 HttpRequestInfo request;
7907 request.method = "GET";
7908 request.url = GURL("http://www.google.com/");
7909
7910 MockWrite data_writes1[] = {
7911 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7912 "Host: www.google.com\r\n"
7913 "Proxy-Connection: keep-alive\r\n\r\n"),
7914 };
7915
7916 MockRead data_reads1[] = {
7917 MockRead("HTTP/1.1 200 OK\r\n"),
7918 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7919 MockRead("Content-Length: 100\r\n\r\n"),
7920 MockRead(false, OK),
7921 };
7922
7923 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7924 data_writes1, arraysize(data_writes1));
7925 session_deps.socket_factory.AddSocketDataProvider(&data1);
7926
7927 TestCompletionCallback callback1;
7928
[email protected]0b0bf032010-09-21 18:08:507929 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7930
[email protected]76a505b2010-08-25 06:23:007931 int rv = trans->Start(&request, &callback1, log.bound());
7932 EXPECT_EQ(ERR_IO_PENDING, rv);
7933
7934 rv = callback1.WaitForResult();
7935 EXPECT_EQ(OK, rv);
7936
7937 const HttpResponseInfo* response = trans->GetResponseInfo();
7938 ASSERT_FALSE(response == NULL);
7939
7940 EXPECT_TRUE(response->headers->IsKeepAlive());
7941 EXPECT_EQ(200, response->headers->response_code());
7942 EXPECT_EQ(100, response->headers->GetContentLength());
7943 EXPECT_TRUE(response->was_fetched_via_proxy);
7944 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7945}
7946
7947// Test a basic HTTPS GET request through a proxy.
7948TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007949 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007950 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7951 session_deps.net_log = log.bound().net_log();
7952 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7953
[email protected]76a505b2010-08-25 06:23:007954 HttpRequestInfo request;
7955 request.method = "GET";
7956 request.url = GURL("https://www.google.com/");
7957
7958 // Since we have proxy, should try to establish tunnel.
7959 MockWrite data_writes1[] = {
7960 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7961 "Host: www.google.com\r\n"
7962 "Proxy-Connection: keep-alive\r\n\r\n"),
7963
7964 MockWrite("GET / HTTP/1.1\r\n"
7965 "Host: www.google.com\r\n"
7966 "Connection: keep-alive\r\n\r\n"),
7967 };
7968
7969 MockRead data_reads1[] = {
7970 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7971
7972 MockRead("HTTP/1.1 200 OK\r\n"),
7973 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7974 MockRead("Content-Length: 100\r\n\r\n"),
7975 MockRead(false, OK),
7976 };
7977
7978 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7979 data_writes1, arraysize(data_writes1));
7980 session_deps.socket_factory.AddSocketDataProvider(&data1);
7981 SSLSocketDataProvider ssl(true, OK);
7982 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7983
7984 TestCompletionCallback callback1;
7985
[email protected]0b0bf032010-09-21 18:08:507986 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7987
[email protected]76a505b2010-08-25 06:23:007988 int rv = trans->Start(&request, &callback1, log.bound());
7989 EXPECT_EQ(ERR_IO_PENDING, rv);
7990
7991 rv = callback1.WaitForResult();
7992 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:407993 net::CapturingNetLog::EntryList entries;
7994 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:007995 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:407996 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:007997 NetLog::PHASE_NONE);
7998 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:407999 entries, pos,
[email protected]76a505b2010-08-25 06:23:008000 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8001 NetLog::PHASE_NONE);
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(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8010 EXPECT_TRUE(response->was_fetched_via_proxy);
8011}
8012
8013// Test a basic HTTPS GET request through a proxy, but the server hangs up
8014// while establishing the tunnel.
8015TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008016 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008017 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8018 session_deps.net_log = log.bound().net_log();
8019 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8020
[email protected]76a505b2010-08-25 06:23:008021 HttpRequestInfo request;
8022 request.method = "GET";
8023 request.url = GURL("https://www.google.com/");
8024
8025 // Since we have proxy, should try to establish tunnel.
8026 MockWrite data_writes1[] = {
8027 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8028 "Host: www.google.com\r\n"
8029 "Proxy-Connection: keep-alive\r\n\r\n"),
8030
8031 MockWrite("GET / HTTP/1.1\r\n"
8032 "Host: www.google.com\r\n"
8033 "Connection: keep-alive\r\n\r\n"),
8034 };
8035
8036 MockRead data_reads1[] = {
8037 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8038 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8039 MockRead(true, 0, 0), // EOF
8040 };
8041
8042 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8043 data_writes1, arraysize(data_writes1));
8044 session_deps.socket_factory.AddSocketDataProvider(&data1);
8045 SSLSocketDataProvider ssl(true, OK);
8046 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8047
8048 TestCompletionCallback callback1;
8049
[email protected]0b0bf032010-09-21 18:08:508050 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8051
[email protected]76a505b2010-08-25 06:23:008052 int rv = trans->Start(&request, &callback1, log.bound());
8053 EXPECT_EQ(ERR_IO_PENDING, rv);
8054
8055 rv = callback1.WaitForResult();
8056 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408057 net::CapturingNetLog::EntryList entries;
8058 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008059 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408060 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008061 NetLog::PHASE_NONE);
8062 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408063 entries, pos,
[email protected]76a505b2010-08-25 06:23:008064 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8065 NetLog::PHASE_NONE);
8066}
8067
[email protected]749eefa82010-09-13 22:14:038068// Test for crbug.com/55424.
8069TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8070 SessionDependencies session_deps;
8071
8072 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8073 "https://www.google.com", false, 1, LOWEST));
8074 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8075
8076 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8077 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8078 MockRead spdy_reads[] = {
8079 CreateMockRead(*resp),
8080 CreateMockRead(*data),
8081 MockRead(true, 0, 0),
8082 };
8083
8084 scoped_refptr<DelayedSocketData> spdy_data(
8085 new DelayedSocketData(
8086 1, // wait for one write to finish before reading.
8087 spdy_reads, arraysize(spdy_reads),
8088 spdy_writes, arraysize(spdy_writes)));
8089 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8090
8091 SSLSocketDataProvider ssl(true, OK);
8092 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8093 ssl.next_proto = "spdy/2";
8094 ssl.was_npn_negotiated = true;
8095 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8096
8097 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8098
8099 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388100 HostPortPair host_port_pair("www.google.com", 443);
8101 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038102 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:278103 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
8104 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:278105 scoped_refptr<TCPSocketParams> tcp_params(
8106 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:388107 TestCompletionCallback callback;
8108
8109 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8110 EXPECT_EQ(ERR_IO_PENDING,
8111 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
8112 &callback, session->tcp_socket_pool(),
8113 BoundNetLog()));
8114 EXPECT_EQ(OK, callback.WaitForResult());
8115 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038116
8117 HttpRequestInfo request;
8118 request.method = "GET";
8119 request.url = GURL("https://www.google.com/");
8120 request.load_flags = 0;
8121
8122 // This is the important line that marks this as a preconnect.
8123 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8124
8125 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8126
[email protected]749eefa82010-09-13 22:14:038127 int rv = trans->Start(&request, &callback, BoundNetLog());
8128 EXPECT_EQ(ERR_IO_PENDING, rv);
8129 EXPECT_EQ(OK, callback.WaitForResult());
8130}
8131
[email protected]73b8dd222010-11-11 19:55:248132// Given a net error, cause that error to be returned from the first Write()
8133// call and verify that the HttpTransaction fails with that error.
8134static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278135 net::HttpRequestInfo request_info;
8136 request_info.url = GURL("https://www.example.com/");
8137 request_info.method = "GET";
8138 request_info.load_flags = net::LOAD_NORMAL;
8139
[email protected]73b8dd222010-11-11 19:55:248140 SessionDependencies session_deps;
8141
8142 SSLSocketDataProvider ssl_data(async, OK);
8143 net::MockWrite data_writes[] = {
8144 net::MockWrite(async, error),
8145 };
8146 net::StaticSocketDataProvider data(NULL, 0,
8147 data_writes, arraysize(data_writes));
8148 session_deps.socket_factory.AddSocketDataProvider(&data);
8149 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8150
8151 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8152 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8153
[email protected]73b8dd222010-11-11 19:55:248154 TestCompletionCallback callback;
8155 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8156 if (rv == net::ERR_IO_PENDING)
8157 rv = callback.WaitForResult();
8158 ASSERT_EQ(error, rv);
8159}
8160
8161TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8162 // Just check a grab bag of cert errors.
8163 static const int kErrors[] = {
8164 ERR_CERT_COMMON_NAME_INVALID,
8165 ERR_CERT_AUTHORITY_INVALID,
8166 ERR_CERT_DATE_INVALID,
8167 };
8168 for (size_t i = 0; i < arraysize(kErrors); i++) {
8169 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8170 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8171 }
8172}
8173
8174// Test that the transaction is restarted in the event of an NPN misprediction.
8175TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
[email protected]cb9bf6ca2011-01-28 13:15:278176 net::HttpRequestInfo request_info;
8177 request_info.url = GURL("https://www.example.com/");
8178 request_info.method = "GET";
8179 request_info.load_flags = net::LOAD_NORMAL;
8180
[email protected]73b8dd222010-11-11 19:55:248181 SessionDependencies session_deps;
8182
8183 SSLSocketDataProvider ssl_data1(true /* async */, OK);
8184 SSLSocketDataProvider ssl_data2(true /* async */, OK);
8185
8186 net::MockWrite data1_writes[] = {
8187 net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION),
8188 };
8189 net::MockRead data2_reads[] = {
8190 net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8191 net::MockRead("hello world"),
8192 net::MockRead(false, net::OK),
8193 };
8194 net::MockWrite data2_writes[] = {
8195 net::MockWrite("GET / HTTP/1.1\r\n"
8196 "Host: www.example.com\r\n"
8197 "Connection: keep-alive\r\n\r\n"),
8198 };
8199 net::StaticSocketDataProvider data1(
8200 NULL, 0, data1_writes, arraysize(data1_writes));
8201 net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads),
8202 data2_writes, arraysize(data2_writes));
8203
8204 session_deps.socket_factory.AddSocketDataProvider(&data1);
8205 session_deps.socket_factory.AddSocketDataProvider(&data2);
8206 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8207 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8208
8209 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8210 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8211
[email protected]73b8dd222010-11-11 19:55:248212 TestCompletionCallback callback;
8213 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8214 if (rv == net::ERR_IO_PENDING)
8215 rv = callback.WaitForResult();
8216 ASSERT_EQ(OK, rv);
8217
8218 std::string contents;
8219 rv = ReadTransaction(trans.get(), &contents);
8220 EXPECT_EQ(net::OK, rv);
8221 EXPECT_EQ("hello world", contents);
8222}
8223
[email protected]bd0b6772011-01-11 19:59:308224// Ensure that a client certificate is removed from the SSL client auth
8225// cache when:
8226// 1) No proxy is involved.
8227// 2) TLS False Start is disabled.
8228// 3) The initial TLS handshake requests a client certificate.
8229// 4) The client supplies an invalid/unacceptable certificate.
8230TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278231 net::HttpRequestInfo request_info;
8232 request_info.url = GURL("https://www.example.com/");
8233 request_info.method = "GET";
8234 request_info.load_flags = net::LOAD_NORMAL;
8235
[email protected]bd0b6772011-01-11 19:59:308236 SessionDependencies session_deps;
8237
8238 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8239 cert_request->host_and_port = "www.example.com:443";
8240
8241 // [ssl_]data1 contains the data for the first SSL handshake. When a
8242 // CertificateRequest is received for the first time, the handshake will
8243 // be aborted to allow the caller to provide a certificate.
8244 SSLSocketDataProvider ssl_data1(true /* async */,
8245 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8246 ssl_data1.cert_request_info = cert_request.get();
8247 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8248 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8249 session_deps.socket_factory.AddSocketDataProvider(&data1);
8250
8251 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8252 // False Start is not being used, the result of the SSL handshake will be
8253 // returned as part of the SSLClientSocket::Connect() call. This test
8254 // matches the result of a server sending a handshake_failure alert,
8255 // rather than a Finished message, because it requires a client
8256 // certificate and none was supplied.
8257 SSLSocketDataProvider ssl_data2(true /* async */,
8258 net::ERR_SSL_PROTOCOL_ERROR);
8259 ssl_data2.cert_request_info = cert_request.get();
8260 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8261 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8262 session_deps.socket_factory.AddSocketDataProvider(&data2);
8263
8264 // [ssl_]data3 contains the data for the third SSL handshake. When a
8265 // connection to a server fails during an SSL handshake,
8266 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8267 // connection was attempted with TLSv1. This is transparent to the caller
8268 // of the HttpNetworkTransaction. Because this test failure is due to
8269 // requiring a client certificate, this fallback handshake should also
8270 // fail.
8271 SSLSocketDataProvider ssl_data3(true /* async */,
8272 net::ERR_SSL_PROTOCOL_ERROR);
8273 ssl_data3.cert_request_info = cert_request.get();
8274 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8275 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8276 session_deps.socket_factory.AddSocketDataProvider(&data3);
8277
8278 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8279 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8280
[email protected]bd0b6772011-01-11 19:59:308281 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8282 TestCompletionCallback callback;
8283 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8284 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8285
8286 // Complete the SSL handshake, which should abort due to requiring a
8287 // client certificate.
8288 rv = callback.WaitForResult();
8289 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8290
8291 // Indicate that no certificate should be supplied. From the perspective
8292 // of SSLClientCertCache, NULL is just as meaningful as a real
8293 // certificate, so this is the same as supply a
8294 // legitimate-but-unacceptable certificate.
8295 rv = trans->RestartWithCertificate(NULL, &callback);
8296 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8297
8298 // Ensure the certificate was added to the client auth cache before
8299 // allowing the connection to continue restarting.
8300 scoped_refptr<X509Certificate> client_cert;
8301 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8302 &client_cert));
8303 ASSERT_EQ(NULL, client_cert.get());
8304
8305 // Restart the handshake. This will consume ssl_data2, which fails, and
8306 // then consume ssl_data3, which should also fail. The result code is
8307 // checked against what ssl_data3 should return.
8308 rv = callback.WaitForResult();
8309 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8310
8311 // Ensure that the client certificate is removed from the cache on a
8312 // handshake failure.
8313 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8314 &client_cert));
8315}
8316
8317// Ensure that a client certificate is removed from the SSL client auth
8318// cache when:
8319// 1) No proxy is involved.
8320// 2) TLS False Start is enabled.
8321// 3) The initial TLS handshake requests a client certificate.
8322// 4) The client supplies an invalid/unacceptable certificate.
8323TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278324 net::HttpRequestInfo request_info;
8325 request_info.url = GURL("https://www.example.com/");
8326 request_info.method = "GET";
8327 request_info.load_flags = net::LOAD_NORMAL;
8328
[email protected]bd0b6772011-01-11 19:59:308329 SessionDependencies session_deps;
8330
8331 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8332 cert_request->host_and_port = "www.example.com:443";
8333
8334 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8335 // return successfully after reading up to the peer's Certificate message.
8336 // This is to allow the caller to call SSLClientSocket::Write(), which can
8337 // enqueue application data to be sent in the same packet as the
8338 // ChangeCipherSpec and Finished messages.
8339 // The actual handshake will be finished when SSLClientSocket::Read() is
8340 // called, which expects to process the peer's ChangeCipherSpec and
8341 // Finished messages. If there was an error negotiating with the peer,
8342 // such as due to the peer requiring a client certificate when none was
8343 // supplied, the alert sent by the peer won't be processed until Read() is
8344 // called.
8345
8346 // Like the non-False Start case, when a client certificate is requested by
8347 // the peer, the handshake is aborted during the Connect() call.
8348 // [ssl_]data1 represents the initial SSL handshake with the peer.
8349 SSLSocketDataProvider ssl_data1(true /* async */,
8350 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8351 ssl_data1.cert_request_info = cert_request.get();
8352 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8353 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8354 session_deps.socket_factory.AddSocketDataProvider(&data1);
8355
8356 // When a client certificate is supplied, Connect() will not be aborted
8357 // when the peer requests the certificate. Instead, the handshake will
8358 // artificially succeed, allowing the caller to write the HTTP request to
8359 // the socket. The handshake messages are not processed until Read() is
8360 // called, which then detects that the handshake was aborted, due to the
8361 // peer sending a handshake_failure because it requires a client
8362 // certificate.
8363 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8364 ssl_data2.cert_request_info = cert_request.get();
8365 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8366 net::MockRead data2_reads[] = {
8367 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8368 };
8369 net::StaticSocketDataProvider data2(
8370 data2_reads, arraysize(data2_reads), NULL, 0);
8371 session_deps.socket_factory.AddSocketDataProvider(&data2);
8372
8373 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8374 // the data for the SSL handshake once the TLSv1 connection falls back to
8375 // SSLv3. It has the same behaviour as [ssl_]data2.
8376 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8377 ssl_data3.cert_request_info = cert_request.get();
8378 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8379 net::StaticSocketDataProvider data3(
8380 data2_reads, arraysize(data2_reads), NULL, 0);
8381 session_deps.socket_factory.AddSocketDataProvider(&data3);
8382
8383 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8384 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8385
[email protected]bd0b6772011-01-11 19:59:308386 // Begin the initial SSL handshake.
8387 TestCompletionCallback callback;
8388 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8389 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8390
8391 // Complete the SSL handshake, which should abort due to requiring a
8392 // client certificate.
8393 rv = callback.WaitForResult();
8394 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8395
8396 // Indicate that no certificate should be supplied. From the perspective
8397 // of SSLClientCertCache, NULL is just as meaningful as a real
8398 // certificate, so this is the same as supply a
8399 // legitimate-but-unacceptable certificate.
8400 rv = trans->RestartWithCertificate(NULL, &callback);
8401 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8402
8403 // Ensure the certificate was added to the client auth cache before
8404 // allowing the connection to continue restarting.
8405 scoped_refptr<X509Certificate> client_cert;
8406 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8407 &client_cert));
8408 ASSERT_EQ(NULL, client_cert.get());
8409
8410
8411 // Restart the handshake. This will consume ssl_data2, which fails, and
8412 // then consume ssl_data3, which should also fail. The result code is
8413 // checked against what ssl_data3 should return.
8414 rv = callback.WaitForResult();
8415 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8416
8417 // Ensure that the client certificate is removed from the cache on a
8418 // handshake failure.
8419 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8420 &client_cert));
8421}
8422
[email protected]8c405132011-01-11 22:03:188423// Ensure that a client certificate is removed from the SSL client auth
8424// cache when:
8425// 1) An HTTPS proxy is involved.
8426// 3) The HTTPS proxy requests a client certificate.
8427// 4) The client supplies an invalid/unacceptable certificate for the
8428// proxy.
8429// The test is repeated twice, first for connecting to an HTTPS endpoint,
8430// then for connecting to an HTTP endpoint.
8431TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8432 SessionDependencies session_deps(
8433 ProxyService::CreateFixed("https://proxy:70"));
8434 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8435 session_deps.net_log = log.bound().net_log();
8436
8437 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8438 cert_request->host_and_port = "proxy:70";
8439
8440 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8441 // [ssl_]data[1-3]. Rather than represending the endpoint
8442 // (www.example.com:443), they represent failures with the HTTPS proxy
8443 // (proxy:70).
8444 SSLSocketDataProvider ssl_data1(true /* async */,
8445 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8446 ssl_data1.cert_request_info = cert_request.get();
8447 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8448 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8449 session_deps.socket_factory.AddSocketDataProvider(&data1);
8450
8451 SSLSocketDataProvider ssl_data2(true /* async */,
8452 net::ERR_SSL_PROTOCOL_ERROR);
8453 ssl_data2.cert_request_info = cert_request.get();
8454 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8455 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8456 session_deps.socket_factory.AddSocketDataProvider(&data2);
8457
8458 SSLSocketDataProvider ssl_data3(true /* async */,
8459 net::ERR_SSL_PROTOCOL_ERROR);
8460 ssl_data3.cert_request_info = cert_request.get();
8461 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8462 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8463 session_deps.socket_factory.AddSocketDataProvider(&data3);
8464
8465 net::HttpRequestInfo requests[2];
8466 requests[0].url = GURL("https://www.example.com/");
8467 requests[0].method = "GET";
8468 requests[0].load_flags = net::LOAD_NORMAL;
8469
8470 requests[1].url = GURL("http://www.example.com/");
8471 requests[1].method = "GET";
8472 requests[1].load_flags = net::LOAD_NORMAL;
8473
8474 for (size_t i = 0; i < arraysize(requests); ++i) {
8475 session_deps.socket_factory.ResetNextMockIndexes();
8476 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8477 scoped_ptr<HttpNetworkTransaction> trans(
8478 new HttpNetworkTransaction(session));
8479
8480 // Begin the SSL handshake with the proxy.
8481 TestCompletionCallback callback;
8482 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8483 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8484
8485 // Complete the SSL handshake, which should abort due to requiring a
8486 // client certificate.
8487 rv = callback.WaitForResult();
8488 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8489
8490 // Indicate that no certificate should be supplied. From the perspective
8491 // of SSLClientCertCache, NULL is just as meaningful as a real
8492 // certificate, so this is the same as supply a
8493 // legitimate-but-unacceptable certificate.
8494 rv = trans->RestartWithCertificate(NULL, &callback);
8495 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8496
8497 // Ensure the certificate was added to the client auth cache before
8498 // allowing the connection to continue restarting.
8499 scoped_refptr<X509Certificate> client_cert;
8500 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8501 &client_cert));
8502 ASSERT_EQ(NULL, client_cert.get());
8503 // Ensure the certificate was NOT cached for the endpoint. This only
8504 // applies to HTTPS requests, but is fine to check for HTTP requests.
8505 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8506 &client_cert));
8507
8508 // Restart the handshake. This will consume ssl_data2, which fails, and
8509 // then consume ssl_data3, which should also fail. The result code is
8510 // checked against what ssl_data3 should return.
8511 rv = callback.WaitForResult();
8512 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8513
8514 // Now that the new handshake has failed, ensure that the client
8515 // certificate was removed from the client auth cache.
8516 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8517 &client_cert));
8518 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8519 &client_cert));
8520 }
8521}
8522
[email protected]89ceba9a2009-03-21 03:46:068523} // namespace net