blob: 44b6759be57a0da0c5235aac8319eafbfe2745c3 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/scoped_ptr.h"
[email protected]5e6efa52011-06-27 17:26:4115#include "base/metrics/histogram.h"
[email protected]f36a8132011-09-02 18:36:3316#include "base/test/test_file_util.h"
[email protected]be1ce6a72010-08-03 14:35:2217#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3518#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1219#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3320#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3221#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1222#include "net/base/net_log.h"
23#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3124#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3025#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4226#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3327#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5228#include "net/base/test_completion_callback.h"
29#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1230#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0031#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2932#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5733#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4034#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5235#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5636#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5737#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3838#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5239#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5340#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1141#include "net/proxy/proxy_resolver.h"
42#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4443#include "net/socket/client_socket_factory.h"
44#include "net/socket/socket_test_util.h"
45#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5446#include "net/spdy/spdy_framer.h"
47#include "net/spdy/spdy_session.h"
48#include "net/spdy/spdy_session_pool.h"
49#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5250#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1551#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5252
53//-----------------------------------------------------------------------------
54
[email protected]13c8a092010-07-29 06:15:4455namespace {
56
57const string16 kBar(ASCIIToUTF16("bar"));
58const string16 kBar2(ASCIIToUTF16("bar2"));
59const string16 kBar3(ASCIIToUTF16("bar3"));
60const string16 kBaz(ASCIIToUTF16("baz"));
61const string16 kFirst(ASCIIToUTF16("first"));
62const string16 kFoo(ASCIIToUTF16("foo"));
63const string16 kFoo2(ASCIIToUTF16("foo2"));
64const string16 kFoo3(ASCIIToUTF16("foo3"));
65const string16 kFou(ASCIIToUTF16("fou"));
66const string16 kSecond(ASCIIToUTF16("second"));
67const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
68const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
69
70} // namespace
71
[email protected]89ceba9a2009-03-21 03:46:0672namespace net {
73
[email protected]e44de5d2009-06-05 20:12:4574// Helper to manage the lifetimes of the dependencies for a
75// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4476struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5977 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4278 SessionDependencies()
79 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1580 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:0281 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1082 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0883 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5484 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5485 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5986
87 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4588 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4289 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1590 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:4291 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1092 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0893 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5494 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5495 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5996
[email protected]73c45322010-10-01 23:57:5497 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:1598 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:1299 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42100 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59101 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50102 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:54103 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59104};
105
[email protected]228ff742009-06-05 01:19:59106HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34107 net::HttpNetworkSession::Params params;
108 params.client_socket_factory = &session_deps->socket_factory;
109 params.host_resolver = session_deps->host_resolver.get();
110 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12111 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34112 params.ssl_config_service = session_deps->ssl_config_service;
113 params.http_auth_handler_factory =
114 session_deps->http_auth_handler_factory.get();
115 params.net_log = session_deps->net_log;
116 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14117}
118
[email protected]89836e22008-09-25 20:33:42119class HttpNetworkTransactionTest : public PlatformTest {
[email protected]e3ceb682011-06-28 23:55:46120 protected:
121 struct SimpleGetHelperResult {
122 int rv;
123 std::string status_line;
124 std::string response_data;
125 };
126
[email protected]2ff8b312010-04-26 22:20:54127 virtual void SetUp() {
[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(false);
131 }
132
[email protected]0e75a732008-10-16 20:36:09133 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50134 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
135 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54136 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09137 // Empty the current queue.
138 MessageLoop::current()->RunAllPending();
139 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50140 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
141 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09142 }
143
[email protected]3d2a59b2008-09-26 19:44:25144 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]31a2bfe2010-02-09 08:03:39146 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
147 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15148 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52149
[email protected]ff007e162009-05-23 09:13:15150 HttpRequestInfo request;
151 request.method = "GET";
152 request.url = GURL("http://www.google.com/");
153 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52154
[email protected]cb9bf6ca2011-01-28 13:15:27155 SessionDependencies session_deps;
156 scoped_ptr<HttpTransaction> trans(
157 new HttpNetworkTransaction(CreateSession(&session_deps)));
158
[email protected]31a2bfe2010-02-09 08:03:39159 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59160 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52161
[email protected]ff007e162009-05-23 09:13:15162 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]169d0012010-05-10 23:20:12164 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40165 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12166 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15167 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52168
[email protected]ff007e162009-05-23 09:13:15169 out.rv = callback.WaitForResult();
170 if (out.rv != OK)
171 return out;
172
173 const HttpResponseInfo* response = trans->GetResponseInfo();
174 EXPECT_TRUE(response != NULL);
175
176 EXPECT_TRUE(response->headers != NULL);
177 out.status_line = response->headers->GetStatusLine();
178
[email protected]6d81b482011-02-22 19:47:19179 EXPECT_EQ("192.0.2.33", response->socket_address.host());
180 EXPECT_EQ(0, response->socket_address.port());
181
[email protected]ff007e162009-05-23 09:13:15182 rv = ReadTransaction(trans.get(), &out.response_data);
183 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40184
185 net::CapturingNetLog::EntryList entries;
186 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39187 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40188 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12189 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39190 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40191 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39192 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
193 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15194
[email protected]b2fcd0e2010-12-01 15:19:40195 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40196 NetLogHttpRequestParameter* request_params =
197 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
198 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
199 EXPECT_EQ("Host: www.google.com\r\n"
200 "Connection: keep-alive\r\n\r\n",
201 request_params->GetHeaders().ToString());
202
[email protected]aecfbf22008-10-16 02:02:47203 return out;
[email protected]ff007e162009-05-23 09:13:15204 }
initial.commit586acc5fe2008-07-26 22:42:52205
[email protected]ff007e162009-05-23 09:13:15206 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
207 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52208
[email protected]ff007e162009-05-23 09:13:15209 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15210};
[email protected]231d5a32008-09-13 00:45:27211
[email protected]15a5ccf82008-10-23 19:57:43212// Fill |str| with a long header list that consumes >= |size| bytes.
213void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19214 const char* row =
215 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
216 const int sizeof_row = strlen(row);
217 const int num_rows = static_cast<int>(
218 ceil(static_cast<float>(size) / sizeof_row));
219 const int sizeof_data = num_rows * sizeof_row;
220 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43221 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51222
[email protected]4ddaf2502008-10-23 18:26:19223 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43224 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19225}
226
[email protected]385a4672009-03-11 22:21:29227// Alternative functions that eliminate randomness and dependency on the local
228// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20229void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29230 static const uint8 bytes[] = {
231 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
232 };
233 static size_t current_byte = 0;
234 for (size_t i = 0; i < n; ++i) {
235 output[i] = bytes[current_byte++];
236 current_byte %= arraysize(bytes);
237 }
238}
239
[email protected]fe2bc6a2009-03-23 16:52:20240void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29241 static const uint8 bytes[] = {
242 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
243 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
244 };
245 static size_t current_byte = 0;
246 for (size_t i = 0; i < n; ++i) {
247 output[i] = bytes[current_byte++];
248 current_byte %= arraysize(bytes);
249 }
250}
251
[email protected]fe2bc6a2009-03-23 16:52:20252std::string MockGetHostName() {
253 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29254}
255
[email protected]e60e47a2010-07-14 03:37:18256template<typename ParentPool>
257class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31258 public:
[email protected]9e1bdd32011-02-03 21:48:34259 CaptureGroupNameSocketPool(HostResolver* host_resolver,
260 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18261
[email protected]d80a4322009-08-14 07:07:49262 const std::string last_group_name_received() const {
263 return last_group_name_;
264 }
265
[email protected]684970b2009-08-14 04:54:46266 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49267 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31268 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31269 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46270 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53271 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31272 last_group_name_ = group_name;
273 return ERR_IO_PENDING;
274 }
[email protected]04e5be32009-06-26 20:00:31275 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21276 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31277 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10278 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19279 int id) {}
[email protected]04e5be32009-06-26 20:00:31280 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31281 virtual int IdleSocketCount() const {
282 return 0;
283 }
284 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
285 return 0;
286 }
287 virtual LoadState GetLoadState(const std::string& group_name,
288 const ClientSocketHandle* handle) const {
289 return LOAD_STATE_IDLE;
290 }
[email protected]a796bcec2010-03-22 17:17:26291 virtual base::TimeDelta ConnectionTimeout() const {
292 return base::TimeDelta();
293 }
[email protected]d80a4322009-08-14 07:07:49294
295 private:
[email protected]04e5be32009-06-26 20:00:31296 std::string last_group_name_;
297};
298
[email protected]ab739042011-04-07 15:22:28299typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
300CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13301typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
302CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06303typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11304CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18305typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
306CaptureGroupNameSSLSocketPool;
307
308template<typename ParentPool>
309CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34310 HostResolver* host_resolver,
311 CertVerifier* /* cert_verifier */)
312 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18313
314template<>
[email protected]2df19bb2010-08-25 20:13:46315CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34316 HostResolver* host_resolver,
317 CertVerifier* /* cert_verifier */)
318 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46319
320template<>
[email protected]e60e47a2010-07-14 03:37:18321CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34322 HostResolver* host_resolver,
323 CertVerifier* cert_verifier)
324 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
[email protected]feb79bcd2011-07-21 16:55:17325 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11326
[email protected]231d5a32008-09-13 00:45:27327//-----------------------------------------------------------------------------
328
[email protected]dae22c52010-07-30 02:16:35329// This is the expected list of advertised protocols from the browser's NPN
330// list.
331static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
332
333// This is the expected return from a current server advertising SPDY.
334static const char kAlternateProtocolHttpHeader[] =
335 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
336
[email protected]231d5a32008-09-13 00:45:27337TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59338 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40339 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43340 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27341}
342
343TEST_F(HttpNetworkTransactionTest, SimpleGET) {
344 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35345 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
346 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42347 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27348 };
[email protected]31a2bfe2010-02-09 08:03:39349 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
350 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42351 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27352 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
353 EXPECT_EQ("hello world", out.response_data);
354}
355
356// Response with no status line.
357TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
358 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35359 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42360 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27361 };
[email protected]31a2bfe2010-02-09 08:03:39362 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
363 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42364 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27365 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
366 EXPECT_EQ("hello world", out.response_data);
367}
368
369// Allow up to 4 bytes of junk to precede status line.
370TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
371 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35372 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42373 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27374 };
[email protected]31a2bfe2010-02-09 08:03:39375 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
376 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42377 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27378 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
379 EXPECT_EQ("DATA", out.response_data);
380}
381
382// Allow up to 4 bytes of junk to precede status line.
383TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
384 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35385 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42386 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27387 };
[email protected]31a2bfe2010-02-09 08:03:39388 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
389 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42390 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27391 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
392 EXPECT_EQ("DATA", out.response_data);
393}
394
395// Beyond 4 bytes of slop and it should fail to find a status line.
396TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
397 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35398 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42399 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27400 };
[email protected]31a2bfe2010-02-09 08:03:39401 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
402 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42403 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25404 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
405 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27406}
407
408// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
409TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
410 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35411 MockRead("\n"),
412 MockRead("\n"),
413 MockRead("Q"),
414 MockRead("J"),
415 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42416 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27417 };
[email protected]31a2bfe2010-02-09 08:03:39418 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
419 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42420 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27421 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
422 EXPECT_EQ("DATA", out.response_data);
423}
424
425// Close the connection before enough bytes to have a status line.
426TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
427 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35428 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42429 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27430 };
[email protected]31a2bfe2010-02-09 08:03:39431 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
432 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42433 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27434 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
435 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52436}
437
[email protected]f9d44aa2008-09-23 23:57:17438// Simulate a 204 response, lacking a Content-Length header, sent over a
439// persistent connection. The response should still terminate since a 204
440// cannot have a response body.
441TEST_F(HttpNetworkTransactionTest, StopsReading204) {
442 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35443 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
444 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42445 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17446 };
[email protected]31a2bfe2010-02-09 08:03:39447 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
448 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42449 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17450 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
451 EXPECT_EQ("", out.response_data);
452}
453
[email protected]0877e3d2009-10-17 22:29:57454// A simple request using chunked encoding with some extra data after.
455// (Like might be seen in a pipelined response.)
456TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
457 MockRead data_reads[] = {
458 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
459 MockRead("5\r\nHello\r\n"),
460 MockRead("1\r\n"),
461 MockRead(" \r\n"),
462 MockRead("5\r\nworld\r\n"),
463 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
464 MockRead(false, OK),
465 };
[email protected]31a2bfe2010-02-09 08:03:39466 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
467 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57468 EXPECT_EQ(OK, out.rv);
469 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
470 EXPECT_EQ("Hello world", out.response_data);
471}
472
[email protected]9fe44f52010-09-23 18:36:00473// Next tests deal with http://crbug.com/56344.
474
475TEST_F(HttpNetworkTransactionTest,
476 MultipleContentLengthHeadersNoTransferEncoding) {
477 MockRead data_reads[] = {
478 MockRead("HTTP/1.1 200 OK\r\n"),
479 MockRead("Content-Length: 10\r\n"),
480 MockRead("Content-Length: 5\r\n\r\n"),
481 };
482 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
483 arraysize(data_reads));
484 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
485}
486
487TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04488 DuplicateContentLengthHeadersNoTransferEncoding) {
489 MockRead data_reads[] = {
490 MockRead("HTTP/1.1 200 OK\r\n"),
491 MockRead("Content-Length: 5\r\n"),
492 MockRead("Content-Length: 5\r\n\r\n"),
493 MockRead("Hello"),
494 };
495 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
496 arraysize(data_reads));
497 EXPECT_EQ(OK, out.rv);
498 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
499 EXPECT_EQ("Hello", out.response_data);
500}
501
502TEST_F(HttpNetworkTransactionTest,
503 ComplexContentLengthHeadersNoTransferEncoding) {
504 // More than 2 dupes.
505 {
506 MockRead data_reads[] = {
507 MockRead("HTTP/1.1 200 OK\r\n"),
508 MockRead("Content-Length: 5\r\n"),
509 MockRead("Content-Length: 5\r\n"),
510 MockRead("Content-Length: 5\r\n\r\n"),
511 MockRead("Hello"),
512 };
513 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
514 arraysize(data_reads));
515 EXPECT_EQ(OK, out.rv);
516 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
517 EXPECT_EQ("Hello", out.response_data);
518 }
519 // HTTP/1.0
520 {
521 MockRead data_reads[] = {
522 MockRead("HTTP/1.0 200 OK\r\n"),
523 MockRead("Content-Length: 5\r\n"),
524 MockRead("Content-Length: 5\r\n"),
525 MockRead("Content-Length: 5\r\n\r\n"),
526 MockRead("Hello"),
527 };
528 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
529 arraysize(data_reads));
530 EXPECT_EQ(OK, out.rv);
531 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
532 EXPECT_EQ("Hello", out.response_data);
533 }
534 // 2 dupes and one mismatched.
535 {
536 MockRead data_reads[] = {
537 MockRead("HTTP/1.1 200 OK\r\n"),
538 MockRead("Content-Length: 10\r\n"),
539 MockRead("Content-Length: 10\r\n"),
540 MockRead("Content-Length: 5\r\n\r\n"),
541 };
542 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
543 arraysize(data_reads));
544 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
545 }
546}
547
548TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00549 MultipleContentLengthHeadersTransferEncoding) {
550 MockRead data_reads[] = {
551 MockRead("HTTP/1.1 200 OK\r\n"),
552 MockRead("Content-Length: 666\r\n"),
553 MockRead("Content-Length: 1337\r\n"),
554 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
555 MockRead("5\r\nHello\r\n"),
556 MockRead("1\r\n"),
557 MockRead(" \r\n"),
558 MockRead("5\r\nworld\r\n"),
559 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
560 MockRead(false, OK),
561 };
562 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
563 arraysize(data_reads));
564 EXPECT_EQ(OK, out.rv);
565 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
566 EXPECT_EQ("Hello world", out.response_data);
567}
568
[email protected]ef0faf2e72009-03-05 23:27:23569// Do a request using the HEAD method. Verify that we don't try to read the
570// message body (since HEAD has none).
571TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42572 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23573 request.method = "HEAD";
574 request.url = GURL("http://www.google.com/");
575 request.load_flags = 0;
576
[email protected]cb9bf6ca2011-01-28 13:15:27577 SessionDependencies session_deps;
578 scoped_ptr<HttpTransaction> trans(
579 new HttpNetworkTransaction(CreateSession(&session_deps)));
580
[email protected]ef0faf2e72009-03-05 23:27:23581 MockWrite data_writes1[] = {
582 MockWrite("HEAD / HTTP/1.1\r\n"
583 "Host: www.google.com\r\n"
584 "Connection: keep-alive\r\n"
585 "Content-Length: 0\r\n\r\n"),
586 };
587 MockRead data_reads1[] = {
588 MockRead("HTTP/1.1 404 Not Found\r\n"),
589 MockRead("Server: Blah\r\n"),
590 MockRead("Content-Length: 1234\r\n\r\n"),
591
592 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42593 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23594 };
595
[email protected]31a2bfe2010-02-09 08:03:39596 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
597 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59598 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23599
600 TestCompletionCallback callback1;
601
[email protected]5a1d7ca2010-04-28 20:12:27602 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42603 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23604
605 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42606 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23607
[email protected]1c773ea12009-04-28 19:58:42608 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23609 EXPECT_FALSE(response == NULL);
610
611 // Check that the headers got parsed.
612 EXPECT_TRUE(response->headers != NULL);
613 EXPECT_EQ(1234, response->headers->GetContentLength());
614 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
615
616 std::string server_header;
617 void* iter = NULL;
618 bool has_server_header = response->headers->EnumerateHeader(
619 &iter, "Server", &server_header);
620 EXPECT_TRUE(has_server_header);
621 EXPECT_EQ("Blah", server_header);
622
623 // Reading should give EOF right away, since there is no message body
624 // (despite non-zero content-length).
625 std::string response_data;
626 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42627 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23628 EXPECT_EQ("", response_data);
629}
630
initial.commit586acc5fe2008-07-26 22:42:52631TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59632 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27633 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52634
635 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35636 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
637 MockRead("hello"),
638 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
639 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42640 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52641 };
[email protected]31a2bfe2010-02-09 08:03:39642 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59643 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52644
[email protected]0b0bf032010-09-21 18:08:50645 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52646 "hello", "world"
647 };
648
649 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42650 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52651 request.method = "GET";
652 request.url = GURL("http://www.google.com/");
653 request.load_flags = 0;
654
[email protected]cb9bf6ca2011-01-28 13:15:27655 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
656
initial.commit586acc5fe2008-07-26 22:42:52657 TestCompletionCallback callback;
658
[email protected]5a1d7ca2010-04-28 20:12:27659 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42660 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52661
662 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42663 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52664
[email protected]1c773ea12009-04-28 19:58:42665 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52666 EXPECT_TRUE(response != NULL);
667
668 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25669 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52670
671 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57672 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42673 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25674 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52675 }
676}
677
678TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42679 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52680 request.method = "POST";
681 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42682 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52683 request.upload_data->AppendBytes("foo", 3);
684 request.load_flags = 0;
685
[email protected]cb9bf6ca2011-01-28 13:15:27686 SessionDependencies session_deps;
687 scoped_ptr<HttpTransaction> trans(
688 new HttpNetworkTransaction(CreateSession(&session_deps)));
689
initial.commit586acc5fe2008-07-26 22:42:52690 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35691 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
692 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
693 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42694 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52695 };
[email protected]31a2bfe2010-02-09 08:03:39696 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59697 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52698
699 TestCompletionCallback callback;
700
[email protected]5a1d7ca2010-04-28 20:12:27701 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42702 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52703
704 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42705 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52706
[email protected]1c773ea12009-04-28 19:58:42707 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52708 EXPECT_TRUE(response != NULL);
709
710 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25711 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52712
713 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57714 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42715 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25716 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52717}
718
[email protected]3a2d3662009-03-27 03:49:14719// This test is almost the same as Ignores100 above, but the response contains
720// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57721// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14722TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42723 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14724 request.method = "GET";
725 request.url = GURL("http://www.foo.com/");
726 request.load_flags = 0;
727
[email protected]cb9bf6ca2011-01-28 13:15:27728 SessionDependencies session_deps;
729 scoped_ptr<HttpTransaction> trans(
730 new HttpNetworkTransaction(CreateSession(&session_deps)));
731
[email protected]3a2d3662009-03-27 03:49:14732 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57733 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
734 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14735 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42736 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14737 };
[email protected]31a2bfe2010-02-09 08:03:39738 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59739 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14740
741 TestCompletionCallback callback;
742
[email protected]5a1d7ca2010-04-28 20:12:27743 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14745
746 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42747 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14748
[email protected]1c773ea12009-04-28 19:58:42749 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14750 EXPECT_TRUE(response != NULL);
751
752 EXPECT_TRUE(response->headers != NULL);
753 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
754
755 std::string response_data;
756 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42757 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14758 EXPECT_EQ("hello world", response_data);
759}
760
[email protected]ee9410e72010-01-07 01:42:38761TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38762 HttpRequestInfo request;
763 request.method = "POST";
764 request.url = GURL("http://www.foo.com/");
765 request.load_flags = 0;
766
[email protected]cb9bf6ca2011-01-28 13:15:27767 SessionDependencies session_deps;
768 scoped_ptr<HttpTransaction> trans(
769 new HttpNetworkTransaction(CreateSession(&session_deps)));
770
[email protected]ee9410e72010-01-07 01:42:38771 MockRead data_reads[] = {
772 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
773 MockRead(true, 0),
774 };
[email protected]31a2bfe2010-02-09 08:03:39775 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38776 session_deps.socket_factory.AddSocketDataProvider(&data);
777
778 TestCompletionCallback callback;
779
[email protected]5a1d7ca2010-04-28 20:12:27780 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38781 EXPECT_EQ(ERR_IO_PENDING, rv);
782
783 rv = callback.WaitForResult();
784 EXPECT_EQ(OK, rv);
785
786 std::string response_data;
787 rv = ReadTransaction(trans.get(), &response_data);
788 EXPECT_EQ(OK, rv);
789 EXPECT_EQ("", response_data);
790}
791
792TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38793 HttpRequestInfo request;
794 request.method = "POST";
795 request.url = GURL("http://www.foo.com/");
796 request.load_flags = 0;
797
[email protected]cb9bf6ca2011-01-28 13:15:27798 SessionDependencies session_deps;
799 scoped_ptr<HttpTransaction> trans(
800 new HttpNetworkTransaction(CreateSession(&session_deps)));
801
[email protected]ee9410e72010-01-07 01:42:38802 MockRead data_reads[] = {
803 MockRead(true, 0),
804 };
[email protected]31a2bfe2010-02-09 08:03:39805 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38806 session_deps.socket_factory.AddSocketDataProvider(&data);
807
808 TestCompletionCallback callback;
809
[email protected]5a1d7ca2010-04-28 20:12:27810 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38811 EXPECT_EQ(ERR_IO_PENDING, rv);
812
813 rv = callback.WaitForResult();
814 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
815}
816
[email protected]3d2a59b2008-09-26 19:44:25817// read_failure specifies a read failure that should cause the network
818// transaction to resend the request.
819void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
820 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:42821 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52822 request.method = "GET";
823 request.url = GURL("http://www.foo.com/");
824 request.load_flags = 0;
825
[email protected]cb9bf6ca2011-01-28 13:15:27826 SessionDependencies session_deps;
827 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
828
initial.commit586acc5fe2008-07-26 22:42:52829 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35830 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
831 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25832 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52833 };
[email protected]31a2bfe2010-02-09 08:03:39834 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59835 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52836
837 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35838 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
839 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42840 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52841 };
[email protected]31a2bfe2010-02-09 08:03:39842 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59843 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52844
845 const char* kExpectedResponseData[] = {
846 "hello", "world"
847 };
848
849 for (int i = 0; i < 2; ++i) {
850 TestCompletionCallback callback;
851
[email protected]5695b8c2009-09-30 21:36:43852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52853
[email protected]5a1d7ca2010-04-28 20:12:27854 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42855 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52856
857 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42858 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52859
[email protected]1c773ea12009-04-28 19:58:42860 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52861 EXPECT_TRUE(response != NULL);
862
863 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25864 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52865
866 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57867 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42868 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25869 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52870 }
871}
[email protected]3d2a59b2008-09-26 19:44:25872
873TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42874 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25875 KeepAliveConnectionResendRequestTest(read_failure);
876}
877
878TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42879 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25880 KeepAliveConnectionResendRequestTest(read_failure);
881}
882
883TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42884 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25885 request.method = "GET";
886 request.url = GURL("http://www.google.com/");
887 request.load_flags = 0;
888
[email protected]cb9bf6ca2011-01-28 13:15:27889 SessionDependencies session_deps;
890 scoped_ptr<HttpTransaction> trans(
891 new HttpNetworkTransaction(CreateSession(&session_deps)));
892
[email protected]3d2a59b2008-09-26 19:44:25893 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42894 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35895 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
896 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42897 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25898 };
[email protected]31a2bfe2010-02-09 08:03:39899 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59900 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25901
902 TestCompletionCallback callback;
903
[email protected]5a1d7ca2010-04-28 20:12:27904 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25906
907 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42908 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25909
[email protected]1c773ea12009-04-28 19:58:42910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25911 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25912}
913
914// What do various browsers do when the server closes a non-keepalive
915// connection without sending any response header or body?
916//
917// IE7: error page
918// Safari 3.1.2 (Windows): error page
919// Firefox 3.0.1: blank page
920// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42921// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
922// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25923TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
924 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42925 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35926 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
927 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42928 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25929 };
[email protected]31a2bfe2010-02-09 08:03:39930 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
931 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42932 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25933}
[email protected]038e9a32008-10-08 22:40:16934
[email protected]0b0bf032010-09-21 18:08:50935// Test that we correctly reuse a keep-alive connection after not explicitly
936// reading the body.
937TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13938 HttpRequestInfo request;
939 request.method = "GET";
940 request.url = GURL("http://www.foo.com/");
941 request.load_flags = 0;
942
[email protected]cb9bf6ca2011-01-28 13:15:27943 SessionDependencies session_deps;
944 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
945
[email protected]0b0bf032010-09-21 18:08:50946 // Note that because all these reads happen in the same
947 // StaticSocketDataProvider, it shows that the same socket is being reused for
948 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13949 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50950 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
951 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13952 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50953 MockRead("HTTP/1.1 302 Found\r\n"
954 "Content-Length: 0\r\n\r\n"),
955 MockRead("HTTP/1.1 302 Found\r\n"
956 "Content-Length: 5\r\n\r\n"
957 "hello"),
958 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
959 "Content-Length: 0\r\n\r\n"),
960 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
961 "Content-Length: 5\r\n\r\n"
962 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13963 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
964 MockRead("hello"),
965 };
966 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
967 session_deps.socket_factory.AddSocketDataProvider(&data1);
968
969 MockRead data2_reads[] = {
970 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
971 };
972 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
973 session_deps.socket_factory.AddSocketDataProvider(&data2);
974
[email protected]0b0bf032010-09-21 18:08:50975 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
976 std::string response_lines[kNumUnreadBodies];
977
978 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13979 TestCompletionCallback callback;
980
981 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
982
983 int rv = trans->Start(&request, &callback, BoundNetLog());
984 EXPECT_EQ(ERR_IO_PENDING, rv);
985
986 rv = callback.WaitForResult();
987 EXPECT_EQ(OK, rv);
988
989 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50990 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13991
[email protected]0b0bf032010-09-21 18:08:50992 ASSERT_TRUE(response->headers != NULL);
993 response_lines[i] = response->headers->GetStatusLine();
994
995 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13996 }
[email protected]0b0bf032010-09-21 18:08:50997
998 const char* const kStatusLines[] = {
999 "HTTP/1.1 204 No Content",
1000 "HTTP/1.1 205 Reset Content",
1001 "HTTP/1.1 304 Not Modified",
1002 "HTTP/1.1 302 Found",
1003 "HTTP/1.1 302 Found",
1004 "HTTP/1.1 301 Moved Permanently",
1005 "HTTP/1.1 301 Moved Permanently",
1006 };
1007
1008 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1009 forgot_to_update_kStatusLines);
1010
1011 for (int i = 0; i < kNumUnreadBodies; ++i)
1012 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1013
1014 TestCompletionCallback callback;
1015 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1016 int rv = trans->Start(&request, &callback, BoundNetLog());
1017 EXPECT_EQ(ERR_IO_PENDING, rv);
1018 rv = callback.WaitForResult();
1019 EXPECT_EQ(OK, rv);
1020 const HttpResponseInfo* response = trans->GetResponseInfo();
1021 ASSERT_TRUE(response != NULL);
1022 ASSERT_TRUE(response->headers != NULL);
1023 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1024 std::string response_data;
1025 rv = ReadTransaction(trans.get(), &response_data);
1026 EXPECT_EQ(OK, rv);
1027 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131028}
1029
[email protected]038e9a32008-10-08 22:40:161030// Test the request-challenge-retry sequence for basic auth.
1031// (basic auth is the easiest to mock, because it has no randomness).
1032TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421033 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161034 request.method = "GET";
1035 request.url = GURL("http://www.google.com/");
1036 request.load_flags = 0;
1037
[email protected]cb9bf6ca2011-01-28 13:15:271038 SessionDependencies session_deps;
1039 scoped_ptr<HttpTransaction> trans(
1040 new HttpNetworkTransaction(CreateSession(&session_deps)));
1041
[email protected]f9ee6b52008-11-08 06:46:231042 MockWrite data_writes1[] = {
1043 MockWrite("GET / HTTP/1.1\r\n"
1044 "Host: www.google.com\r\n"
1045 "Connection: keep-alive\r\n\r\n"),
1046 };
1047
[email protected]038e9a32008-10-08 22:40:161048 MockRead data_reads1[] = {
1049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1050 // Give a couple authenticate options (only the middle one is actually
1051 // supported).
[email protected]22927ad2009-09-21 19:56:191052 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161053 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1054 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1055 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1056 // Large content-length -- won't matter, as connection will be reset.
1057 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421058 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161059 };
1060
1061 // After calling trans->RestartWithAuth(), this is the request we should
1062 // be issuing -- the final header line contains the credentials.
1063 MockWrite data_writes2[] = {
1064 MockWrite("GET / HTTP/1.1\r\n"
1065 "Host: www.google.com\r\n"
1066 "Connection: keep-alive\r\n"
1067 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1068 };
1069
1070 // Lastly, the server responds with the actual content.
1071 MockRead data_reads2[] = {
1072 MockRead("HTTP/1.0 200 OK\r\n"),
1073 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1074 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421075 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161076 };
1077
[email protected]31a2bfe2010-02-09 08:03:391078 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1079 data_writes1, arraysize(data_writes1));
1080 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1081 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591082 session_deps.socket_factory.AddSocketDataProvider(&data1);
1083 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161084
1085 TestCompletionCallback callback1;
1086
[email protected]5a1d7ca2010-04-28 20:12:271087 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421088 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161089
1090 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421091 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161092
[email protected]1c773ea12009-04-28 19:58:421093 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161094 EXPECT_FALSE(response == NULL);
1095
1096 // The password prompt info should have been set in response->auth_challenge.
1097 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1098
[email protected]71e4573a2009-05-21 22:03:001099 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161100 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1101 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1102
1103 TestCompletionCallback callback2;
1104
[email protected]13c8a092010-07-29 06:15:441105 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421106 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161107
1108 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421109 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161110
1111 response = trans->GetResponseInfo();
1112 EXPECT_FALSE(response == NULL);
1113 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1114 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161115}
1116
[email protected]861fcd52009-08-26 02:33:461117TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461118 HttpRequestInfo request;
1119 request.method = "GET";
1120 request.url = GURL("http://www.google.com/");
1121 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1122
[email protected]cb9bf6ca2011-01-28 13:15:271123 SessionDependencies session_deps;
1124 scoped_ptr<HttpTransaction> trans(
1125 new HttpNetworkTransaction(CreateSession(&session_deps)));
1126
[email protected]861fcd52009-08-26 02:33:461127 MockWrite data_writes[] = {
1128 MockWrite("GET / HTTP/1.1\r\n"
1129 "Host: www.google.com\r\n"
1130 "Connection: keep-alive\r\n\r\n"),
1131 };
1132
1133 MockRead data_reads[] = {
1134 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1135 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1136 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1137 // Large content-length -- won't matter, as connection will be reset.
1138 MockRead("Content-Length: 10000\r\n\r\n"),
1139 MockRead(false, ERR_FAILED),
1140 };
1141
[email protected]31a2bfe2010-02-09 08:03:391142 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1143 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591144 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461145 TestCompletionCallback callback;
1146
[email protected]5a1d7ca2010-04-28 20:12:271147 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461148 EXPECT_EQ(ERR_IO_PENDING, rv);
1149
1150 rv = callback.WaitForResult();
1151 EXPECT_EQ(0, rv);
1152
1153 const HttpResponseInfo* response = trans->GetResponseInfo();
1154 ASSERT_FALSE(response == NULL);
1155 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1156}
1157
[email protected]2d2697f92009-02-18 21:00:321158// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1159// connection.
1160TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421161 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321162 request.method = "GET";
1163 request.url = GURL("http://www.google.com/");
1164 request.load_flags = 0;
1165
[email protected]cb9bf6ca2011-01-28 13:15:271166 SessionDependencies session_deps;
1167 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1168
[email protected]2d2697f92009-02-18 21:00:321169 MockWrite data_writes1[] = {
1170 MockWrite("GET / HTTP/1.1\r\n"
1171 "Host: www.google.com\r\n"
1172 "Connection: keep-alive\r\n\r\n"),
1173
1174 // After calling trans->RestartWithAuth(), this is the request we should
1175 // be issuing -- the final header line contains the credentials.
1176 MockWrite("GET / HTTP/1.1\r\n"
1177 "Host: www.google.com\r\n"
1178 "Connection: keep-alive\r\n"
1179 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1180 };
1181
1182 MockRead data_reads1[] = {
1183 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1184 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1185 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1186 MockRead("Content-Length: 14\r\n\r\n"),
1187 MockRead("Unauthorized\r\n"),
1188
1189 // Lastly, the server responds with the actual content.
1190 MockRead("HTTP/1.1 200 OK\r\n"),
1191 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501192 MockRead("Content-Length: 5\r\n\r\n"),
1193 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321194 };
1195
[email protected]2d0a4f92011-05-05 16:38:461196 // If there is a regression where we disconnect a Keep-Alive
1197 // connection during an auth roundtrip, we'll end up reading this.
1198 MockRead data_reads2[] = {
1199 MockRead(false, ERR_FAILED),
1200 };
1201
[email protected]31a2bfe2010-02-09 08:03:391202 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1203 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461204 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1205 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591206 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461207 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321208
1209 TestCompletionCallback callback1;
1210
[email protected]0b0bf032010-09-21 18:08:501211 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271212 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421213 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321214
1215 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421216 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321217
[email protected]1c773ea12009-04-28 19:58:421218 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321219 EXPECT_FALSE(response == NULL);
1220
1221 // The password prompt info should have been set in response->auth_challenge.
1222 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1223
[email protected]71e4573a2009-05-21 22:03:001224 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321225 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1226 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1227
1228 TestCompletionCallback callback2;
1229
[email protected]13c8a092010-07-29 06:15:441230 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421231 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321232
1233 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421234 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321235
1236 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461237 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321238 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501239 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321240}
1241
1242// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1243// connection and with no response body to drain.
1244TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421245 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321246 request.method = "GET";
1247 request.url = GURL("http://www.google.com/");
1248 request.load_flags = 0;
1249
[email protected]cb9bf6ca2011-01-28 13:15:271250 SessionDependencies session_deps;
1251 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1252
[email protected]2d2697f92009-02-18 21:00:321253 MockWrite data_writes1[] = {
1254 MockWrite("GET / HTTP/1.1\r\n"
1255 "Host: www.google.com\r\n"
1256 "Connection: keep-alive\r\n\r\n"),
1257
1258 // After calling trans->RestartWithAuth(), this is the request we should
1259 // be issuing -- the final header line contains the credentials.
1260 MockWrite("GET / HTTP/1.1\r\n"
1261 "Host: www.google.com\r\n"
1262 "Connection: keep-alive\r\n"
1263 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1264 };
1265
[email protected]2d2697f92009-02-18 21:00:321266 MockRead data_reads1[] = {
1267 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1268 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311269 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321270
1271 // Lastly, the server responds with the actual content.
1272 MockRead("HTTP/1.1 200 OK\r\n"),
1273 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501274 MockRead("Content-Length: 5\r\n\r\n"),
1275 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321276 };
1277
[email protected]2d0a4f92011-05-05 16:38:461278 // An incorrect reconnect would cause this to be read.
1279 MockRead data_reads2[] = {
1280 MockRead(false, ERR_FAILED),
1281 };
1282
[email protected]31a2bfe2010-02-09 08:03:391283 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1284 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461285 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1286 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591287 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461288 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321289
1290 TestCompletionCallback callback1;
1291
[email protected]0b0bf032010-09-21 18:08:501292 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271293 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421294 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321295
1296 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421297 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321298
[email protected]1c773ea12009-04-28 19:58:421299 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321300 EXPECT_FALSE(response == NULL);
1301
1302 // The password prompt info should have been set in response->auth_challenge.
1303 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1304
[email protected]71e4573a2009-05-21 22:03:001305 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321306 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1307 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1308
1309 TestCompletionCallback callback2;
1310
[email protected]13c8a092010-07-29 06:15:441311 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421312 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321313
1314 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421315 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321316
1317 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461318 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321319 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501320 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321321}
1322
1323// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1324// connection and with a large response body to drain.
1325TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421326 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321327 request.method = "GET";
1328 request.url = GURL("http://www.google.com/");
1329 request.load_flags = 0;
1330
[email protected]cb9bf6ca2011-01-28 13:15:271331 SessionDependencies session_deps;
1332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1333
[email protected]2d2697f92009-02-18 21:00:321334 MockWrite data_writes1[] = {
1335 MockWrite("GET / HTTP/1.1\r\n"
1336 "Host: www.google.com\r\n"
1337 "Connection: keep-alive\r\n\r\n"),
1338
1339 // After calling trans->RestartWithAuth(), this is the request we should
1340 // be issuing -- the final header line contains the credentials.
1341 MockWrite("GET / HTTP/1.1\r\n"
1342 "Host: www.google.com\r\n"
1343 "Connection: keep-alive\r\n"
1344 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1345 };
1346
1347 // Respond with 5 kb of response body.
1348 std::string large_body_string("Unauthorized");
1349 large_body_string.append(5 * 1024, ' ');
1350 large_body_string.append("\r\n");
1351
1352 MockRead data_reads1[] = {
1353 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1354 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1356 // 5134 = 12 + 5 * 1024 + 2
1357 MockRead("Content-Length: 5134\r\n\r\n"),
1358 MockRead(true, large_body_string.data(), large_body_string.size()),
1359
1360 // Lastly, the server responds with the actual content.
1361 MockRead("HTTP/1.1 200 OK\r\n"),
1362 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501363 MockRead("Content-Length: 5\r\n\r\n"),
1364 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321365 };
1366
[email protected]2d0a4f92011-05-05 16:38:461367 // An incorrect reconnect would cause this to be read.
1368 MockRead data_reads2[] = {
1369 MockRead(false, ERR_FAILED),
1370 };
1371
[email protected]31a2bfe2010-02-09 08:03:391372 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1373 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461374 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1375 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591376 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461377 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321378
1379 TestCompletionCallback callback1;
1380
[email protected]0b0bf032010-09-21 18:08:501381 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271382 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421383 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321384
1385 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421386 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321387
[email protected]1c773ea12009-04-28 19:58:421388 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321389 EXPECT_FALSE(response == NULL);
1390
1391 // The password prompt info should have been set in response->auth_challenge.
1392 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1393
[email protected]71e4573a2009-05-21 22:03:001394 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321395 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1396 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1397
1398 TestCompletionCallback callback2;
1399
[email protected]13c8a092010-07-29 06:15:441400 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421401 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321402
1403 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421404 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321405
1406 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461407 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321408 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501409 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321410}
1411
1412// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311413// connection, but the server gets impatient and closes the connection.
1414TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311415 HttpRequestInfo request;
1416 request.method = "GET";
1417 request.url = GURL("http://www.google.com/");
1418 request.load_flags = 0;
1419
[email protected]cb9bf6ca2011-01-28 13:15:271420 SessionDependencies session_deps;
1421 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1422
[email protected]11203f012009-11-12 23:02:311423 MockWrite data_writes1[] = {
1424 MockWrite("GET / HTTP/1.1\r\n"
1425 "Host: www.google.com\r\n"
1426 "Connection: keep-alive\r\n\r\n"),
1427 // This simulates the seemingly successful write to a closed connection
1428 // if the bug is not fixed.
1429 MockWrite("GET / HTTP/1.1\r\n"
1430 "Host: www.google.com\r\n"
1431 "Connection: keep-alive\r\n"
1432 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1433 };
1434
1435 MockRead data_reads1[] = {
1436 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1437 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1438 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1439 MockRead("Content-Length: 14\r\n\r\n"),
1440 // Tell MockTCPClientSocket to simulate the server closing the connection.
1441 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1442 MockRead("Unauthorized\r\n"),
1443 MockRead(false, OK), // The server closes the connection.
1444 };
1445
1446 // After calling trans->RestartWithAuth(), this is the request we should
1447 // be issuing -- the final header line contains the credentials.
1448 MockWrite data_writes2[] = {
1449 MockWrite("GET / HTTP/1.1\r\n"
1450 "Host: www.google.com\r\n"
1451 "Connection: keep-alive\r\n"
1452 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1453 };
1454
1455 // Lastly, the server responds with the actual content.
1456 MockRead data_reads2[] = {
1457 MockRead("HTTP/1.1 200 OK\r\n"),
1458 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501459 MockRead("Content-Length: 5\r\n\r\n"),
1460 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311461 };
1462
[email protected]31a2bfe2010-02-09 08:03:391463 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1464 data_writes1, arraysize(data_writes1));
1465 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1466 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311467 session_deps.socket_factory.AddSocketDataProvider(&data1);
1468 session_deps.socket_factory.AddSocketDataProvider(&data2);
1469
1470 TestCompletionCallback callback1;
1471
[email protected]0b0bf032010-09-21 18:08:501472 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271473 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311474 EXPECT_EQ(ERR_IO_PENDING, rv);
1475
1476 rv = callback1.WaitForResult();
1477 EXPECT_EQ(OK, rv);
1478
1479 const HttpResponseInfo* response = trans->GetResponseInfo();
1480 EXPECT_FALSE(response == NULL);
1481
1482 // The password prompt info should have been set in response->auth_challenge.
1483 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1484
1485 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1486 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1487 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1488
1489 TestCompletionCallback callback2;
1490
[email protected]13c8a092010-07-29 06:15:441491 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311492 EXPECT_EQ(ERR_IO_PENDING, rv);
1493
1494 rv = callback2.WaitForResult();
1495 EXPECT_EQ(OK, rv);
1496
1497 response = trans->GetResponseInfo();
1498 ASSERT_FALSE(response == NULL);
1499 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501500 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311501}
1502
[email protected]394816e92010-08-03 07:38:591503// Test the request-challenge-retry sequence for basic auth, over a connection
1504// that requires a restart when setting up an SSL tunnel.
1505TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591506 HttpRequestInfo request;
1507 request.method = "GET";
1508 request.url = GURL("https://www.google.com/");
1509 // when the no authentication data flag is set.
1510 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1511
[email protected]cb9bf6ca2011-01-28 13:15:271512 // Configure against proxy server "myproxy:70".
1513 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1514 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1515 session_deps.net_log = log.bound().net_log();
1516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1517
[email protected]394816e92010-08-03 07:38:591518 // Since we have proxy, should try to establish tunnel.
1519 MockWrite data_writes1[] = {
1520 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1521 "Host: www.google.com\r\n"
1522 "Proxy-Connection: keep-alive\r\n\r\n"),
1523
1524 // After calling trans->RestartWithAuth(), this is the request we should
1525 // be issuing -- the final header line contains the credentials.
1526 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1527 "Host: www.google.com\r\n"
1528 "Proxy-Connection: keep-alive\r\n"
1529 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1530
1531 MockWrite("GET / HTTP/1.1\r\n"
1532 "Host: www.google.com\r\n"
1533 "Connection: keep-alive\r\n\r\n"),
1534 };
1535
1536 // The proxy responds to the connect with a 407, using a persistent
1537 // connection.
1538 MockRead data_reads1[] = {
1539 // No credentials.
1540 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1541 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1542 MockRead("Proxy-Connection: close\r\n\r\n"),
1543
1544 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1545
1546 MockRead("HTTP/1.1 200 OK\r\n"),
1547 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501548 MockRead("Content-Length: 5\r\n\r\n"),
1549 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591550 };
1551
1552 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1553 data_writes1, arraysize(data_writes1));
1554 session_deps.socket_factory.AddSocketDataProvider(&data1);
1555 SSLSocketDataProvider ssl(true, OK);
1556 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1557
1558 TestCompletionCallback callback1;
1559
[email protected]0b0bf032010-09-21 18:08:501560 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1561
[email protected]394816e92010-08-03 07:38:591562 int rv = trans->Start(&request, &callback1, log.bound());
1563 EXPECT_EQ(ERR_IO_PENDING, rv);
1564
1565 rv = callback1.WaitForResult();
1566 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401567 net::CapturingNetLog::EntryList entries;
1568 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591569 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401570 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591571 NetLog::PHASE_NONE);
1572 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401573 entries, pos,
[email protected]394816e92010-08-03 07:38:591574 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1575 NetLog::PHASE_NONE);
1576
1577 const HttpResponseInfo* response = trans->GetResponseInfo();
1578 ASSERT_FALSE(response == NULL);
1579
1580 EXPECT_EQ(407, response->headers->response_code());
1581 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1582
1583 // The password prompt info should have been set in response->auth_challenge.
1584 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1585
1586 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1587 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1588 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1589
1590 TestCompletionCallback callback2;
1591
1592 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1593 EXPECT_EQ(ERR_IO_PENDING, rv);
1594
1595 rv = callback2.WaitForResult();
1596 EXPECT_EQ(OK, rv);
1597
1598 response = trans->GetResponseInfo();
1599 ASSERT_FALSE(response == NULL);
1600
1601 EXPECT_TRUE(response->headers->IsKeepAlive());
1602 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501603 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591604 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1605
1606 // The password prompt info should not be set.
1607 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501608
1609 trans.reset();
[email protected]102e27c2011-02-23 01:01:311610 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591611}
1612
[email protected]11203f012009-11-12 23:02:311613// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321614// proxy connection, when setting up an SSL tunnel.
1615TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271616 HttpRequestInfo request;
1617 request.method = "GET";
1618 request.url = GURL("https://www.google.com/");
1619 // Ensure that proxy authentication is attempted even
1620 // when the no authentication data flag is set.
1621 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1622
[email protected]2d2697f92009-02-18 21:00:321623 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001624 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541625 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1626 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321628
[email protected]5695b8c2009-09-30 21:36:431629 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321630
[email protected]2d2697f92009-02-18 21:00:321631 // Since we have proxy, should try to establish tunnel.
1632 MockWrite data_writes1[] = {
1633 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451634 "Host: www.google.com\r\n"
1635 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321636
1637 // After calling trans->RestartWithAuth(), this is the request we should
1638 // be issuing -- the final header line contains the credentials.
1639 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1640 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451641 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321642 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1643 };
1644
1645 // The proxy responds to the connect with a 407, using a persistent
1646 // connection.
1647 MockRead data_reads1[] = {
1648 // No credentials.
1649 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1650 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1651 MockRead("Content-Length: 10\r\n\r\n"),
1652 MockRead("0123456789"),
1653
1654 // Wrong credentials (wrong password).
1655 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1656 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1657 MockRead("Content-Length: 10\r\n\r\n"),
1658 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421659 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321660 };
1661
[email protected]31a2bfe2010-02-09 08:03:391662 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1663 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591664 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321665
1666 TestCompletionCallback callback1;
1667
[email protected]dbb83db2010-05-11 18:13:391668 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421669 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321670
1671 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421672 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401673 net::CapturingNetLog::EntryList entries;
1674 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391675 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401676 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391677 NetLog::PHASE_NONE);
1678 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401679 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391680 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1681 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321682
[email protected]1c773ea12009-04-28 19:58:421683 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321684 EXPECT_FALSE(response == NULL);
1685
1686 EXPECT_TRUE(response->headers->IsKeepAlive());
1687 EXPECT_EQ(407, response->headers->response_code());
1688 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421689 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321690
1691 // The password prompt info should have been set in response->auth_challenge.
1692 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1693
[email protected]71e4573a2009-05-21 22:03:001694 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321695 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1696 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1697
1698 TestCompletionCallback callback2;
1699
1700 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441701 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421702 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321703
1704 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421705 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321706
1707 response = trans->GetResponseInfo();
1708 EXPECT_FALSE(response == NULL);
1709
1710 EXPECT_TRUE(response->headers->IsKeepAlive());
1711 EXPECT_EQ(407, response->headers->response_code());
1712 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421713 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321714
1715 // The password prompt info should have been set in response->auth_challenge.
1716 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1717
[email protected]71e4573a2009-05-21 22:03:001718 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321719 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1720 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131721
[email protected]e60e47a2010-07-14 03:37:181722 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1723 // out of scope.
[email protected]102e27c2011-02-23 01:01:311724 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321725}
1726
[email protected]a8e9b162009-03-12 00:06:441727// Test that we don't read the response body when we fail to establish a tunnel,
1728// even if the user cancels the proxy's auth attempt.
1729TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271730 HttpRequestInfo request;
1731 request.method = "GET";
1732 request.url = GURL("https://www.google.com/");
1733 request.load_flags = 0;
1734
[email protected]a8e9b162009-03-12 00:06:441735 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001736 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441737
[email protected]e44de5d2009-06-05 20:12:451738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441739
[email protected]5695b8c2009-09-30 21:36:431740 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441741
[email protected]a8e9b162009-03-12 00:06:441742 // Since we have proxy, should try to establish tunnel.
1743 MockWrite data_writes[] = {
1744 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451745 "Host: www.google.com\r\n"
1746 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441747 };
1748
1749 // The proxy responds to the connect with a 407.
1750 MockRead data_reads[] = {
1751 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1752 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1753 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421754 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441755 };
1756
[email protected]31a2bfe2010-02-09 08:03:391757 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1758 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591759 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441760
1761 TestCompletionCallback callback;
1762
[email protected]5a1d7ca2010-04-28 20:12:271763 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421764 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441765
1766 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421767 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441768
[email protected]1c773ea12009-04-28 19:58:421769 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441770 EXPECT_FALSE(response == NULL);
1771
1772 EXPECT_TRUE(response->headers->IsKeepAlive());
1773 EXPECT_EQ(407, response->headers->response_code());
1774 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421775 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441776
1777 std::string response_data;
1778 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421779 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181780
1781 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311782 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441783}
1784
[email protected]8fdbcd22010-05-05 02:54:521785// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1786// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1787TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521788 HttpRequestInfo request;
1789 request.method = "GET";
1790 request.url = GURL("http://www.google.com/");
1791 request.load_flags = 0;
1792
[email protected]cb9bf6ca2011-01-28 13:15:271793 // We are using a DIRECT connection (i.e. no proxy) for this session.
1794 SessionDependencies session_deps;
1795 scoped_ptr<HttpTransaction> trans(
1796 new HttpNetworkTransaction(CreateSession(&session_deps)));
1797
[email protected]8fdbcd22010-05-05 02:54:521798 MockWrite data_writes1[] = {
1799 MockWrite("GET / HTTP/1.1\r\n"
1800 "Host: www.google.com\r\n"
1801 "Connection: keep-alive\r\n\r\n"),
1802 };
1803
1804 MockRead data_reads1[] = {
1805 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1806 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1807 // Large content-length -- won't matter, as connection will be reset.
1808 MockRead("Content-Length: 10000\r\n\r\n"),
1809 MockRead(false, ERR_FAILED),
1810 };
1811
1812 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1813 data_writes1, arraysize(data_writes1));
1814 session_deps.socket_factory.AddSocketDataProvider(&data1);
1815
1816 TestCompletionCallback callback;
1817
1818 int rv = trans->Start(&request, &callback, BoundNetLog());
1819 EXPECT_EQ(ERR_IO_PENDING, rv);
1820
1821 rv = callback.WaitForResult();
1822 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1823}
1824
[email protected]7a67a8152010-11-05 18:31:101825// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1826// through a non-authenticating proxy. The request should fail with
1827// ERR_UNEXPECTED_PROXY_AUTH.
1828// Note that it is impossible to detect if an HTTP server returns a 407 through
1829// a non-authenticating proxy - there is nothing to indicate whether the
1830// response came from the proxy or the server, so it is treated as if the proxy
1831// issued the challenge.
1832TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271833 HttpRequestInfo request;
1834 request.method = "GET";
1835 request.url = GURL("https://www.google.com/");
1836
[email protected]7a67a8152010-11-05 18:31:101837 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1838 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1839 session_deps.net_log = log.bound().net_log();
1840 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1841
[email protected]7a67a8152010-11-05 18:31:101842 // Since we have proxy, should try to establish tunnel.
1843 MockWrite data_writes1[] = {
1844 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1845 "Host: www.google.com\r\n"
1846 "Proxy-Connection: keep-alive\r\n\r\n"),
1847
1848 MockWrite("GET / HTTP/1.1\r\n"
1849 "Host: www.google.com\r\n"
1850 "Connection: keep-alive\r\n\r\n"),
1851 };
1852
1853 MockRead data_reads1[] = {
1854 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1855
1856 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1857 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1858 MockRead("\r\n"),
1859 MockRead(false, OK),
1860 };
1861
1862 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1863 data_writes1, arraysize(data_writes1));
1864 session_deps.socket_factory.AddSocketDataProvider(&data1);
1865 SSLSocketDataProvider ssl(true, OK);
1866 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1867
1868 TestCompletionCallback callback1;
1869
1870 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1871
1872 int rv = trans->Start(&request, &callback1, log.bound());
1873 EXPECT_EQ(ERR_IO_PENDING, rv);
1874
1875 rv = callback1.WaitForResult();
1876 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401877 net::CapturingNetLog::EntryList entries;
1878 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101879 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401880 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101881 NetLog::PHASE_NONE);
1882 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401883 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101884 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1885 NetLog::PHASE_NONE);
1886}
[email protected]2df19bb2010-08-25 20:13:461887
1888// Test a simple get through an HTTPS Proxy.
1889TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271890 HttpRequestInfo request;
1891 request.method = "GET";
1892 request.url = GURL("http://www.google.com/");
1893
[email protected]2df19bb2010-08-25 20:13:461894 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001895 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461896 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1897 session_deps.net_log = log.bound().net_log();
1898 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1899
[email protected]2df19bb2010-08-25 20:13:461900 // Since we have proxy, should use full url
1901 MockWrite data_writes1[] = {
1902 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1903 "Host: www.google.com\r\n"
1904 "Proxy-Connection: keep-alive\r\n\r\n"),
1905 };
1906
1907 MockRead data_reads1[] = {
1908 MockRead("HTTP/1.1 200 OK\r\n"),
1909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1910 MockRead("Content-Length: 100\r\n\r\n"),
1911 MockRead(false, OK),
1912 };
1913
1914 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1915 data_writes1, arraysize(data_writes1));
1916 session_deps.socket_factory.AddSocketDataProvider(&data1);
1917 SSLSocketDataProvider ssl(true, OK);
1918 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1919
1920 TestCompletionCallback callback1;
1921
[email protected]0b0bf032010-09-21 18:08:501922 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1923
[email protected]2df19bb2010-08-25 20:13:461924 int rv = trans->Start(&request, &callback1, log.bound());
1925 EXPECT_EQ(ERR_IO_PENDING, rv);
1926
1927 rv = callback1.WaitForResult();
1928 EXPECT_EQ(OK, rv);
1929
1930 const HttpResponseInfo* response = trans->GetResponseInfo();
1931 ASSERT_FALSE(response == NULL);
1932
1933 EXPECT_TRUE(response->headers->IsKeepAlive());
1934 EXPECT_EQ(200, response->headers->response_code());
1935 EXPECT_EQ(100, response->headers->GetContentLength());
1936 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1937
1938 // The password prompt info should not be set.
1939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1940}
1941
[email protected]7642b5ae2010-09-01 20:55:171942// Test a SPDY get through an HTTPS Proxy.
1943TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271944 HttpRequestInfo request;
1945 request.method = "GET";
1946 request.url = GURL("http://www.google.com/");
1947 request.load_flags = 0;
1948
[email protected]7642b5ae2010-09-01 20:55:171949 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001950 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171951 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1952 session_deps.net_log = log.bound().net_log();
1953 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1954
[email protected]7642b5ae2010-09-01 20:55:171955 // fetch http://www.google.com/ via SPDY
1956 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1957 false));
1958 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1959
1960 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1961 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1962 MockRead spdy_reads[] = {
1963 CreateMockRead(*resp),
1964 CreateMockRead(*data),
1965 MockRead(true, 0, 0),
1966 };
1967
1968 scoped_refptr<DelayedSocketData> spdy_data(
1969 new DelayedSocketData(
1970 1, // wait for one write to finish before reading.
1971 spdy_reads, arraysize(spdy_reads),
1972 spdy_writes, arraysize(spdy_writes)));
1973 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1974
1975 SSLSocketDataProvider ssl(true, OK);
1976 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1977 ssl.next_proto = "spdy/2";
1978 ssl.was_npn_negotiated = true;
1979 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1980
1981 TestCompletionCallback callback1;
1982
[email protected]0b0bf032010-09-21 18:08:501983 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1984
[email protected]7642b5ae2010-09-01 20:55:171985 int rv = trans->Start(&request, &callback1, log.bound());
1986 EXPECT_EQ(ERR_IO_PENDING, rv);
1987
1988 rv = callback1.WaitForResult();
1989 EXPECT_EQ(OK, rv);
1990
1991 const HttpResponseInfo* response = trans->GetResponseInfo();
1992 ASSERT_TRUE(response != NULL);
1993 ASSERT_TRUE(response->headers != NULL);
1994 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1995
1996 std::string response_data;
1997 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1998 EXPECT_EQ(net::kUploadData, response_data);
1999}
2000
[email protected]dc7bd1c52010-11-12 00:01:132001// Test a SPDY get through an HTTPS Proxy.
2002TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272003 HttpRequestInfo request;
2004 request.method = "GET";
2005 request.url = GURL("http://www.google.com/");
2006 request.load_flags = 0;
2007
[email protected]dc7bd1c52010-11-12 00:01:132008 // Configure against https proxy server "proxy:70".
2009 SessionDependencies session_deps(
2010 ProxyService::CreateFixed("https://proxy:70"));
2011 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2012 session_deps.net_log = log.bound().net_log();
2013 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2014
[email protected]dc7bd1c52010-11-12 00:01:132015 // The first request will be a bare GET, the second request will be a
2016 // GET with a Proxy-Authorization header.
2017 scoped_ptr<spdy::SpdyFrame> req_get(
2018 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2019 const char* const kExtraAuthorizationHeaders[] = {
2020 "proxy-authorization",
2021 "Basic Zm9vOmJhcg==",
2022 };
2023 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2024 ConstructSpdyGet(
2025 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2026 false, 3, LOWEST, false));
2027 MockWrite spdy_writes[] = {
2028 CreateMockWrite(*req_get, 1),
2029 CreateMockWrite(*req_get_authorization, 4),
2030 };
2031
2032 // The first response is a 407 proxy authentication challenge, and the second
2033 // response will be a 200 response since the second request includes a valid
2034 // Authorization header.
2035 const char* const kExtraAuthenticationHeaders[] = {
2036 "Proxy-Authenticate",
2037 "Basic realm=\"MyRealm1\""
2038 };
2039 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2040 ConstructSpdySynReplyError(
2041 "407 Proxy Authentication Required",
2042 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2043 1));
2044 scoped_ptr<spdy::SpdyFrame> body_authentication(
2045 ConstructSpdyBodyFrame(1, true));
2046 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2047 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2048 MockRead spdy_reads[] = {
2049 CreateMockRead(*resp_authentication, 2),
2050 CreateMockRead(*body_authentication, 3),
2051 CreateMockRead(*resp_data, 5),
2052 CreateMockRead(*body_data, 6),
2053 MockRead(true, 0, 7),
2054 };
2055
2056 scoped_refptr<OrderedSocketData> data(
2057 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2058 spdy_writes, arraysize(spdy_writes)));
2059 session_deps.socket_factory.AddSocketDataProvider(data);
2060
2061 SSLSocketDataProvider ssl(true, OK);
2062 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2063 ssl.next_proto = "spdy/2";
2064 ssl.was_npn_negotiated = true;
2065 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2066
2067 TestCompletionCallback callback1;
2068
2069 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2070
2071 int rv = trans->Start(&request, &callback1, log.bound());
2072 EXPECT_EQ(ERR_IO_PENDING, rv);
2073
2074 rv = callback1.WaitForResult();
2075 EXPECT_EQ(OK, rv);
2076
2077 const HttpResponseInfo* const response = trans->GetResponseInfo();
2078
2079 ASSERT_TRUE(response != NULL);
2080 ASSERT_TRUE(response->headers != NULL);
2081 EXPECT_EQ(407, response->headers->response_code());
2082 EXPECT_TRUE(response->was_fetched_via_spdy);
2083
2084 // The password prompt info should have been set in response->auth_challenge.
2085 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2086 EXPECT_TRUE(response->auth_challenge->is_proxy);
2087 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2088 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2089 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2090
2091 TestCompletionCallback callback2;
2092
2093 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2094 EXPECT_EQ(ERR_IO_PENDING, rv);
2095
2096 rv = callback2.WaitForResult();
2097 EXPECT_EQ(OK, rv);
2098
2099 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2100
2101 ASSERT_TRUE(response_restart != NULL);
2102 ASSERT_TRUE(response_restart->headers != NULL);
2103 EXPECT_EQ(200, response_restart->headers->response_code());
2104 // The password prompt info should not be set.
2105 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2106}
2107
[email protected]d9da5fe2010-10-13 22:37:162108// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2109TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272110 HttpRequestInfo request;
2111 request.method = "GET";
2112 request.url = GURL("https://www.google.com/");
2113 request.load_flags = 0;
2114
[email protected]d9da5fe2010-10-13 22:37:162115 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002116 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162117 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2118 session_deps.net_log = log.bound().net_log();
2119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2120
2121 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2122
[email protected]d9da5fe2010-10-13 22:37:162123 // CONNECT to www.google.com:443 via SPDY
2124 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2125 // fetch https://www.google.com/ via HTTP
2126
2127 const char get[] = "GET / HTTP/1.1\r\n"
2128 "Host: www.google.com\r\n"
2129 "Connection: keep-alive\r\n\r\n";
2130 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2131 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2132 MockWrite spdy_writes[] = {
2133 CreateMockWrite(*connect, 1),
2134 CreateMockWrite(*wrapped_get, 3)
2135 };
2136
2137 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2138 const char resp[] = "HTTP/1.1 200 OK\r\n"
2139 "Content-Length: 10\r\n\r\n";
2140
2141 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2142 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2143 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2144 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2145 MockRead spdy_reads[] = {
2146 CreateMockRead(*conn_resp, 2, true),
2147 CreateMockRead(*wrapped_get_resp, 4, true),
2148 CreateMockRead(*wrapped_body, 5, true),
2149 CreateMockRead(*wrapped_body, 6, true),
2150 MockRead(true, 0, 7),
2151 };
2152
2153 scoped_refptr<OrderedSocketData> spdy_data(
2154 new OrderedSocketData(
2155 spdy_reads, arraysize(spdy_reads),
2156 spdy_writes, arraysize(spdy_writes)));
2157 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2158
2159 SSLSocketDataProvider ssl(true, OK);
2160 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2161 ssl.next_proto = "spdy/2";
2162 ssl.was_npn_negotiated = true;
2163 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2164 SSLSocketDataProvider ssl2(true, OK);
2165 ssl2.was_npn_negotiated = false;
2166 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2167
2168 TestCompletionCallback callback1;
2169
2170 int rv = trans->Start(&request, &callback1, log.bound());
2171 EXPECT_EQ(ERR_IO_PENDING, rv);
2172
2173 rv = callback1.WaitForResult();
2174 EXPECT_EQ(OK, rv);
2175
2176 const HttpResponseInfo* response = trans->GetResponseInfo();
2177 ASSERT_TRUE(response != NULL);
2178 ASSERT_TRUE(response->headers != NULL);
2179 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2180
2181 std::string response_data;
2182 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2183 EXPECT_EQ("1234567890", response_data);
2184}
2185
2186// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2187TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272188 HttpRequestInfo request;
2189 request.method = "GET";
2190 request.url = GURL("https://www.google.com/");
2191 request.load_flags = 0;
2192
[email protected]d9da5fe2010-10-13 22:37:162193 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002194 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162195 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2196 session_deps.net_log = log.bound().net_log();
2197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2198
2199 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2200
[email protected]d9da5fe2010-10-13 22:37:162201 // CONNECT to www.google.com:443 via SPDY
2202 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2203 // fetch https://www.google.com/ via SPDY
2204 const char* const kMyUrl = "https://www.google.com/";
2205 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2206 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2207 MockWrite spdy_writes[] = {
2208 CreateMockWrite(*connect, 1),
2209 CreateMockWrite(*wrapped_get, 3)
2210 };
2211
2212 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2213 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2214 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2215 ConstructWrappedSpdyFrame(get_resp, 1));
2216 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2217 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2218 MockRead spdy_reads[] = {
2219 CreateMockRead(*conn_resp, 2, true),
2220 CreateMockRead(*wrapped_get_resp, 4, true),
2221 CreateMockRead(*wrapped_body, 5, true),
2222 MockRead(true, 0, 1),
2223 };
2224
2225 scoped_refptr<OrderedSocketData> spdy_data(
2226 new OrderedSocketData(
2227 spdy_reads, arraysize(spdy_reads),
2228 spdy_writes, arraysize(spdy_writes)));
2229 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2230
2231 SSLSocketDataProvider ssl(true, OK);
2232 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2233 ssl.next_proto = "spdy/2";
2234 ssl.was_npn_negotiated = true;
2235 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2236 SSLSocketDataProvider ssl2(true, OK);
2237 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2238 ssl2.next_proto = "spdy/2";
2239 ssl2.was_npn_negotiated = true;
2240 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2241
2242 TestCompletionCallback callback1;
2243
2244 int rv = trans->Start(&request, &callback1, log.bound());
2245 EXPECT_EQ(ERR_IO_PENDING, rv);
2246
2247 rv = callback1.WaitForResult();
2248 EXPECT_EQ(OK, rv);
2249
2250 const HttpResponseInfo* response = trans->GetResponseInfo();
2251 ASSERT_TRUE(response != NULL);
2252 ASSERT_TRUE(response->headers != NULL);
2253 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2254
2255 std::string response_data;
2256 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2257 EXPECT_EQ(net::kUploadData, response_data);
2258}
2259
2260// Test a SPDY CONNECT failure through an HTTPS Proxy.
2261TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272262 HttpRequestInfo request;
2263 request.method = "GET";
2264 request.url = GURL("https://www.google.com/");
2265 request.load_flags = 0;
2266
[email protected]d9da5fe2010-10-13 22:37:162267 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002268 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162269 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2270 session_deps.net_log = log.bound().net_log();
2271 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2272
2273 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2274
[email protected]d9da5fe2010-10-13 22:37:162275 // CONNECT to www.google.com:443 via SPDY
2276 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2277 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2278
2279 MockWrite spdy_writes[] = {
2280 CreateMockWrite(*connect, 1),
2281 CreateMockWrite(*get, 3),
2282 };
2283
2284 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2285 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2286 MockRead spdy_reads[] = {
2287 CreateMockRead(*resp, 2, true),
2288 MockRead(true, 0, 4),
2289 };
2290
2291 scoped_refptr<OrderedSocketData> spdy_data(
2292 new OrderedSocketData(
2293 spdy_reads, arraysize(spdy_reads),
2294 spdy_writes, arraysize(spdy_writes)));
2295 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2296
2297 SSLSocketDataProvider ssl(true, OK);
2298 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2299 ssl.next_proto = "spdy/2";
2300 ssl.was_npn_negotiated = true;
2301 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2302 SSLSocketDataProvider ssl2(true, OK);
2303 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2304 ssl2.next_proto = "spdy/2";
2305 ssl2.was_npn_negotiated = true;
2306 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2307
2308 TestCompletionCallback callback1;
2309
2310 int rv = trans->Start(&request, &callback1, log.bound());
2311 EXPECT_EQ(ERR_IO_PENDING, rv);
2312
2313 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292314 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162315
2316 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292317 ASSERT_FALSE(response == NULL);
2318 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162319}
2320
[email protected]2df19bb2010-08-25 20:13:462321// Test the challenge-response-retry sequence through an HTTPS Proxy
2322TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462323 HttpRequestInfo request;
2324 request.method = "GET";
2325 request.url = GURL("http://www.google.com/");
2326 // when the no authentication data flag is set.
2327 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2328
[email protected]cb9bf6ca2011-01-28 13:15:272329 // Configure against https proxy server "proxy:70".
2330 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2331 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2332 session_deps.net_log = log.bound().net_log();
2333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2334
[email protected]2df19bb2010-08-25 20:13:462335 // Since we have proxy, should use full url
2336 MockWrite data_writes1[] = {
2337 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2338 "Host: www.google.com\r\n"
2339 "Proxy-Connection: keep-alive\r\n\r\n"),
2340
2341 // After calling trans->RestartWithAuth(), this is the request we should
2342 // be issuing -- the final header line contains the credentials.
2343 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2344 "Host: www.google.com\r\n"
2345 "Proxy-Connection: keep-alive\r\n"
2346 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2347 };
2348
2349 // The proxy responds to the GET with a 407, using a persistent
2350 // connection.
2351 MockRead data_reads1[] = {
2352 // No credentials.
2353 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2354 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2355 MockRead("Proxy-Connection: keep-alive\r\n"),
2356 MockRead("Content-Length: 0\r\n\r\n"),
2357
2358 MockRead("HTTP/1.1 200 OK\r\n"),
2359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2360 MockRead("Content-Length: 100\r\n\r\n"),
2361 MockRead(false, OK),
2362 };
2363
2364 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2365 data_writes1, arraysize(data_writes1));
2366 session_deps.socket_factory.AddSocketDataProvider(&data1);
2367 SSLSocketDataProvider ssl(true, OK);
2368 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2369
2370 TestCompletionCallback callback1;
2371
[email protected]0b0bf032010-09-21 18:08:502372 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2373
[email protected]2df19bb2010-08-25 20:13:462374 int rv = trans->Start(&request, &callback1, log.bound());
2375 EXPECT_EQ(ERR_IO_PENDING, rv);
2376
2377 rv = callback1.WaitForResult();
2378 EXPECT_EQ(OK, rv);
2379
2380 const HttpResponseInfo* response = trans->GetResponseInfo();
2381 ASSERT_FALSE(response == NULL);
2382
2383 EXPECT_EQ(407, response->headers->response_code());
2384 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2385
2386 // The password prompt info should have been set in response->auth_challenge.
2387 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2388
2389 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2390 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2391 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2392
2393 TestCompletionCallback callback2;
2394
2395 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2396 EXPECT_EQ(ERR_IO_PENDING, rv);
2397
2398 rv = callback2.WaitForResult();
2399 EXPECT_EQ(OK, rv);
2400
2401 response = trans->GetResponseInfo();
2402 ASSERT_FALSE(response == NULL);
2403
2404 EXPECT_TRUE(response->headers->IsKeepAlive());
2405 EXPECT_EQ(200, response->headers->response_code());
2406 EXPECT_EQ(100, response->headers->GetContentLength());
2407 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2408
2409 // The password prompt info should not be set.
2410 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2411}
2412
[email protected]ff007e162009-05-23 09:13:152413void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082414 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422415 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082416 request.method = "GET";
2417 request.url = GURL("https://www.google.com/");
2418 request.load_flags = 0;
2419
[email protected]cb9bf6ca2011-01-28 13:15:272420 // Configure against proxy server "myproxy:70".
2421 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2422
2423 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2424
[email protected]c744cf22009-02-27 07:28:082425 // Since we have proxy, should try to establish tunnel.
2426 MockWrite data_writes[] = {
2427 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452428 "Host: www.google.com\r\n"
2429 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082430 };
2431
2432 MockRead data_reads[] = {
2433 status,
2434 MockRead("Content-Length: 10\r\n\r\n"),
2435 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422436 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082437 };
2438
[email protected]31a2bfe2010-02-09 08:03:392439 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2440 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592441 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082442
2443 TestCompletionCallback callback;
2444
[email protected]0b0bf032010-09-21 18:08:502445 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2446
[email protected]5a1d7ca2010-04-28 20:12:272447 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422448 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082449
2450 rv = callback.WaitForResult();
2451 EXPECT_EQ(expected_status, rv);
2452}
2453
[email protected]ff007e162009-05-23 09:13:152454void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082455 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422456 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082457}
2458
2459TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2460 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2461}
2462
2463TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2464 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2465}
2466
2467TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2468 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2469}
2470
2471TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2472 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2473}
2474
2475TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2476 ConnectStatusHelper(
2477 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2478}
2479
2480TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2481 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2482}
2483
2484TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2485 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2486}
2487
2488TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2489 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2490}
2491
2492TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2493 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2494}
2495
2496TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2497 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2498}
2499
2500TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2501 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2502}
2503
2504TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2505 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2506}
2507
2508TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2509 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2510}
2511
2512TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2513 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2514}
2515
2516TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2517 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2518}
2519
2520TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2521 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2522}
2523
2524TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2525 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2526}
2527
2528TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2529 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2530}
2531
2532TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2533 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2534}
2535
2536TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2537 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2538}
2539
2540TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2541 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2542}
2543
2544TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2545 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2546}
2547
2548TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2549 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2550}
2551
2552TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2553 ConnectStatusHelperWithExpectedStatus(
2554 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542555 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082556}
2557
2558TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2559 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2560}
2561
2562TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2563 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2564}
2565
2566TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2567 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2568}
2569
2570TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2571 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2572}
2573
2574TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2575 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2576}
2577
2578TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2579 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2580}
2581
2582TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2583 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2584}
2585
2586TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2587 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2588}
2589
2590TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2591 ConnectStatusHelper(
2592 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2593}
2594
2595TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2596 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2597}
2598
2599TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2600 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2601}
2602
2603TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2604 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2605}
2606
2607TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2608 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2609}
2610
2611TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2612 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2613}
2614
2615TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2616 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2617}
2618
2619TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2620 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2621}
2622
[email protected]038e9a32008-10-08 22:40:162623// Test the flow when both the proxy server AND origin server require
2624// authentication. Again, this uses basic auth for both since that is
2625// the simplest to mock.
2626TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272627 HttpRequestInfo request;
2628 request.method = "GET";
2629 request.url = GURL("http://www.google.com/");
2630 request.load_flags = 0;
2631
[email protected]81cdfcd2010-10-16 00:49:002632 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012633
[email protected]038e9a32008-10-08 22:40:162634 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422635 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432636 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162637
[email protected]f9ee6b52008-11-08 06:46:232638 MockWrite data_writes1[] = {
2639 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2640 "Host: www.google.com\r\n"
2641 "Proxy-Connection: keep-alive\r\n\r\n"),
2642 };
2643
[email protected]038e9a32008-10-08 22:40:162644 MockRead data_reads1[] = {
2645 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2646 // Give a couple authenticate options (only the middle one is actually
2647 // supported).
[email protected]22927ad2009-09-21 19:56:192648 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162649 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2650 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2651 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2652 // Large content-length -- won't matter, as connection will be reset.
2653 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422654 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162655 };
2656
2657 // After calling trans->RestartWithAuth() the first time, this is the
2658 // request we should be issuing -- the final header line contains the
2659 // proxy's credentials.
2660 MockWrite data_writes2[] = {
2661 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2662 "Host: www.google.com\r\n"
2663 "Proxy-Connection: keep-alive\r\n"
2664 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2665 };
2666
2667 // Now the proxy server lets the request pass through to origin server.
2668 // The origin server responds with a 401.
2669 MockRead data_reads2[] = {
2670 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2671 // Note: We are using the same realm-name as the proxy server. This is
2672 // completely valid, as realms are unique across hosts.
2673 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2674 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2675 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422676 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162677 };
2678
2679 // After calling trans->RestartWithAuth() the second time, we should send
2680 // the credentials for both the proxy and origin server.
2681 MockWrite data_writes3[] = {
2682 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2683 "Host: www.google.com\r\n"
2684 "Proxy-Connection: keep-alive\r\n"
2685 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2686 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2687 };
2688
2689 // Lastly we get the desired content.
2690 MockRead data_reads3[] = {
2691 MockRead("HTTP/1.0 200 OK\r\n"),
2692 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2693 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422694 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162695 };
2696
[email protected]31a2bfe2010-02-09 08:03:392697 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2698 data_writes1, arraysize(data_writes1));
2699 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2700 data_writes2, arraysize(data_writes2));
2701 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2702 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592703 session_deps.socket_factory.AddSocketDataProvider(&data1);
2704 session_deps.socket_factory.AddSocketDataProvider(&data2);
2705 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162706
2707 TestCompletionCallback callback1;
2708
[email protected]5a1d7ca2010-04-28 20:12:272709 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162711
2712 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422713 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162714
[email protected]1c773ea12009-04-28 19:58:422715 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162716 EXPECT_FALSE(response == NULL);
2717
2718 // The password prompt info should have been set in response->auth_challenge.
2719 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2720
[email protected]71e4573a2009-05-21 22:03:002721 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162722 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2723 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2724
2725 TestCompletionCallback callback2;
2726
[email protected]13c8a092010-07-29 06:15:442727 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422728 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162729
2730 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422731 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162732
2733 response = trans->GetResponseInfo();
2734 EXPECT_FALSE(response == NULL);
2735 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2736
[email protected]71e4573a2009-05-21 22:03:002737 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162738 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2739 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2740
2741 TestCompletionCallback callback3;
2742
[email protected]13c8a092010-07-29 06:15:442743 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162745
2746 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422747 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162748
2749 response = trans->GetResponseInfo();
2750 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2751 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162752}
[email protected]4ddaf2502008-10-23 18:26:192753
[email protected]ea9dc9a2009-09-05 00:43:322754// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2755// can't hook into its internals to cause it to generate predictable NTLM
2756// authorization headers.
2757#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292758// The NTLM authentication unit tests were generated by capturing the HTTP
2759// requests and responses using Fiddler 2 and inspecting the generated random
2760// bytes in the debugger.
2761
2762// Enter the correct password and authenticate successfully.
2763TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422764 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242765 request.method = "GET";
2766 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2767 request.load_flags = 0;
2768
[email protected]cb9bf6ca2011-01-28 13:15:272769 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2770 MockGetHostName);
2771 SessionDependencies session_deps;
2772 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2773
[email protected]3f918782009-02-28 01:29:242774 MockWrite data_writes1[] = {
2775 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2776 "Host: 172.22.68.17\r\n"
2777 "Connection: keep-alive\r\n\r\n"),
2778 };
2779
2780 MockRead data_reads1[] = {
2781 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042782 // Negotiate and NTLM are often requested together. However, we only want
2783 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2784 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242785 MockRead("WWW-Authenticate: NTLM\r\n"),
2786 MockRead("Connection: close\r\n"),
2787 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362788 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242789 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422790 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242791 };
2792
2793 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222794 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242795 // request we should be issuing -- the final header line contains a Type
2796 // 1 message.
2797 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2798 "Host: 172.22.68.17\r\n"
2799 "Connection: keep-alive\r\n"
2800 "Authorization: NTLM "
2801 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2802
2803 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2804 // (the credentials for the origin server). The second request continues
2805 // on the same connection.
2806 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2807 "Host: 172.22.68.17\r\n"
2808 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292809 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2810 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2811 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2812 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2813 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242814 };
2815
2816 MockRead data_reads2[] = {
2817 // The origin server responds with a Type 2 message.
2818 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2819 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292820 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242821 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2822 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2823 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2824 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2825 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2826 "BtAAAAAAA=\r\n"),
2827 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362828 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242829 MockRead("You are not authorized to view this page\r\n"),
2830
2831 // Lastly we get the desired content.
2832 MockRead("HTTP/1.1 200 OK\r\n"),
2833 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2834 MockRead("Content-Length: 13\r\n\r\n"),
2835 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422836 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242837 };
2838
[email protected]31a2bfe2010-02-09 08:03:392839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2840 data_writes1, arraysize(data_writes1));
2841 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2842 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592843 session_deps.socket_factory.AddSocketDataProvider(&data1);
2844 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242845
2846 TestCompletionCallback callback1;
2847
[email protected]0b0bf032010-09-21 18:08:502848 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2849
[email protected]5a1d7ca2010-04-28 20:12:272850 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242852
2853 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422854 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242855
[email protected]0757e7702009-03-27 04:00:222856 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2857
[email protected]1c773ea12009-04-28 19:58:422858 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:252859 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:242860
[email protected]aef04272010-06-28 18:03:042861 // The password prompt info should have been set in
2862 // response->auth_challenge.
[email protected]10af5fe72011-01-31 16:17:252863 ASSERT_FALSE(response->auth_challenge.get() == NULL);
[email protected]3f918782009-02-28 01:29:242864
[email protected]71e4573a2009-05-21 22:03:002865 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242866 EXPECT_EQ(L"", response->auth_challenge->realm);
2867 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2868
[email protected]10af5fe72011-01-31 16:17:252869 TestCompletionCallback callback2;
2870
2871 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2872 EXPECT_EQ(ERR_IO_PENDING, rv);
2873
2874 rv = callback2.WaitForResult();
2875 EXPECT_EQ(OK, rv);
2876
2877 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2878
2879 response = trans->GetResponseInfo();
2880 ASSERT_TRUE(response != NULL);
2881
2882 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2883
[email protected]0757e7702009-03-27 04:00:222884 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242885
[email protected]10af5fe72011-01-31 16:17:252886 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422887 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242888
[email protected]0757e7702009-03-27 04:00:222889 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422890 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242891
2892 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042893 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242894 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2895 EXPECT_EQ(13, response->headers->GetContentLength());
2896}
2897
[email protected]385a4672009-03-11 22:21:292898// Enter a wrong password, and then the correct one.
2899TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422900 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292901 request.method = "GET";
2902 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2903 request.load_flags = 0;
2904
[email protected]cb9bf6ca2011-01-28 13:15:272905 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2906 MockGetHostName);
2907 SessionDependencies session_deps;
2908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2909
[email protected]385a4672009-03-11 22:21:292910 MockWrite data_writes1[] = {
2911 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2912 "Host: 172.22.68.17\r\n"
2913 "Connection: keep-alive\r\n\r\n"),
2914 };
2915
2916 MockRead data_reads1[] = {
2917 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042918 // Negotiate and NTLM are often requested together. However, we only want
2919 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2920 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292921 MockRead("WWW-Authenticate: NTLM\r\n"),
2922 MockRead("Connection: close\r\n"),
2923 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362924 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292925 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422926 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292927 };
2928
2929 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222930 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292931 // request we should be issuing -- the final header line contains a Type
2932 // 1 message.
2933 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2934 "Host: 172.22.68.17\r\n"
2935 "Connection: keep-alive\r\n"
2936 "Authorization: NTLM "
2937 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2938
2939 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2940 // (the credentials for the origin server). The second request continues
2941 // on the same connection.
2942 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2943 "Host: 172.22.68.17\r\n"
2944 "Connection: keep-alive\r\n"
2945 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2946 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2947 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2948 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2949 "4Ww7b7E=\r\n\r\n"),
2950 };
2951
2952 MockRead data_reads2[] = {
2953 // The origin server responds with a Type 2 message.
2954 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2955 MockRead("WWW-Authenticate: NTLM "
2956 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2957 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2958 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2959 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2960 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2961 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2962 "BtAAAAAAA=\r\n"),
2963 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362964 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292965 MockRead("You are not authorized to view this page\r\n"),
2966
2967 // Wrong password.
2968 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292969 MockRead("WWW-Authenticate: NTLM\r\n"),
2970 MockRead("Connection: close\r\n"),
2971 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362972 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292973 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422974 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292975 };
2976
2977 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222978 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292979 // request we should be issuing -- the final header line contains a Type
2980 // 1 message.
2981 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2982 "Host: 172.22.68.17\r\n"
2983 "Connection: keep-alive\r\n"
2984 "Authorization: NTLM "
2985 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2986
2987 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2988 // (the credentials for the origin server). The second request continues
2989 // on the same connection.
2990 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2991 "Host: 172.22.68.17\r\n"
2992 "Connection: keep-alive\r\n"
2993 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2994 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2995 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2996 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2997 "+4MUm7c=\r\n\r\n"),
2998 };
2999
3000 MockRead data_reads3[] = {
3001 // The origin server responds with a Type 2 message.
3002 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3003 MockRead("WWW-Authenticate: NTLM "
3004 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3005 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3006 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3007 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3008 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3009 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3010 "BtAAAAAAA=\r\n"),
3011 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363012 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293013 MockRead("You are not authorized to view this page\r\n"),
3014
3015 // Lastly we get the desired content.
3016 MockRead("HTTP/1.1 200 OK\r\n"),
3017 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3018 MockRead("Content-Length: 13\r\n\r\n"),
3019 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423020 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293021 };
3022
[email protected]31a2bfe2010-02-09 08:03:393023 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3024 data_writes1, arraysize(data_writes1));
3025 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3026 data_writes2, arraysize(data_writes2));
3027 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3028 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593029 session_deps.socket_factory.AddSocketDataProvider(&data1);
3030 session_deps.socket_factory.AddSocketDataProvider(&data2);
3031 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293032
3033 TestCompletionCallback callback1;
3034
[email protected]0b0bf032010-09-21 18:08:503035 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3036
[email protected]5a1d7ca2010-04-28 20:12:273037 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293039
3040 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423041 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293042
[email protected]0757e7702009-03-27 04:00:223043 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293044
[email protected]1c773ea12009-04-28 19:58:423045 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293046 EXPECT_FALSE(response == NULL);
3047
3048 // The password prompt info should have been set in response->auth_challenge.
3049 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3050
[email protected]71e4573a2009-05-21 22:03:003051 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293052 EXPECT_EQ(L"", response->auth_challenge->realm);
3053 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3054
[email protected]10af5fe72011-01-31 16:17:253055 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293056
[email protected]0757e7702009-03-27 04:00:223057 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253058 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423059 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293060
[email protected]10af5fe72011-01-31 16:17:253061 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423062 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293063
[email protected]0757e7702009-03-27 04:00:223064 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:253065 TestCompletionCallback callback3;
3066 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423067 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253068 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423069 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223070 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3071
3072 response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:253073 ASSERT_TRUE(response != NULL);
[email protected]0757e7702009-03-27 04:00:223074
3075 // The password prompt info should have been set in response->auth_challenge.
3076 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3077
[email protected]71e4573a2009-05-21 22:03:003078 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223079 EXPECT_EQ(L"", response->auth_challenge->realm);
3080 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3081
[email protected]10af5fe72011-01-31 16:17:253082 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223083
3084 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253085 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3086 EXPECT_EQ(ERR_IO_PENDING, rv);
3087
3088 rv = callback4.WaitForResult();
3089 EXPECT_EQ(OK, rv);
3090
3091 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3092
3093 TestCompletionCallback callback5;
3094
3095 // One more roundtrip
3096 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423097 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223098
3099 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423100 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223101
[email protected]385a4672009-03-11 22:21:293102 response = trans->GetResponseInfo();
3103 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3104 EXPECT_EQ(13, response->headers->GetContentLength());
3105}
[email protected]ea9dc9a2009-09-05 00:43:323106#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293107
[email protected]4ddaf2502008-10-23 18:26:193108// Test reading a server response which has only headers, and no body.
3109// After some maximum number of bytes is consumed, the transaction should
3110// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3111TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423112 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193113 request.method = "GET";
3114 request.url = GURL("http://www.google.com/");
3115 request.load_flags = 0;
3116
[email protected]cb9bf6ca2011-01-28 13:15:273117 SessionDependencies session_deps;
3118 scoped_ptr<HttpTransaction> trans(
3119 new HttpNetworkTransaction(CreateSession(&session_deps)));
3120
[email protected]b75b7b2f2009-10-06 00:54:533121 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433122 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533123 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193124
3125 MockRead data_reads[] = {
3126 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433127 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193128 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423129 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193130 };
[email protected]31a2bfe2010-02-09 08:03:393131 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593132 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193133
3134 TestCompletionCallback callback;
3135
[email protected]5a1d7ca2010-04-28 20:12:273136 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423137 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193138
3139 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423140 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193141
[email protected]1c773ea12009-04-28 19:58:423142 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193143 EXPECT_TRUE(response == NULL);
3144}
[email protected]f4e426b2008-11-05 00:24:493145
3146// Make sure that we don't try to reuse a TCPClientSocket when failing to
3147// establish tunnel.
3148// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283149TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273150 HttpRequestInfo request;
3151 request.method = "GET";
3152 request.url = GURL("https://www.google.com/");
3153 request.load_flags = 0;
3154
[email protected]f4e426b2008-11-05 00:24:493155 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003156 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013157
[email protected]228ff742009-06-05 01:19:593158 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493159
[email protected]5695b8c2009-09-30 21:36:433160 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493161
[email protected]f4e426b2008-11-05 00:24:493162 // Since we have proxy, should try to establish tunnel.
3163 MockWrite data_writes1[] = {
3164 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453165 "Host: www.google.com\r\n"
3166 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493167 };
3168
[email protected]77848d12008-11-14 00:00:223169 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493170 // connection. Usually a proxy would return 501 (not implemented),
3171 // or 200 (tunnel established).
3172 MockRead data_reads1[] = {
3173 MockRead("HTTP/1.1 404 Not Found\r\n"),
3174 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423175 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493176 };
3177
[email protected]31a2bfe2010-02-09 08:03:393178 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3179 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593180 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493181
3182 TestCompletionCallback callback1;
3183
[email protected]5a1d7ca2010-04-28 20:12:273184 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423185 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493186
3187 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423188 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493189
[email protected]1c773ea12009-04-28 19:58:423190 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083191 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493192
[email protected]b4404c02009-04-10 16:38:523193 // Empty the current queue. This is necessary because idle sockets are
3194 // added to the connection pool asynchronously with a PostTask.
3195 MessageLoop::current()->RunAllPending();
3196
[email protected]f4e426b2008-11-05 00:24:493197 // We now check to make sure the TCPClientSocket was not added back to
3198 // the pool.
[email protected]ab739042011-04-07 15:22:283199 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493200 trans.reset();
[email protected]b4404c02009-04-10 16:38:523201 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493202 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]ab739042011-04-07 15:22:283203 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493204}
[email protected]372d34a2008-11-05 21:30:513205
[email protected]1b157c02009-04-21 01:55:403206// Make sure that we recycle a socket after reading all of the response body.
3207TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423208 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403209 request.method = "GET";
3210 request.url = GURL("http://www.google.com/");
3211 request.load_flags = 0;
3212
[email protected]cb9bf6ca2011-01-28 13:15:273213 SessionDependencies session_deps;
3214 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3215
3216 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3217
[email protected]1b157c02009-04-21 01:55:403218 MockRead data_reads[] = {
3219 // A part of the response body is received with the response headers.
3220 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3221 // The rest of the response body is received in two parts.
3222 MockRead("lo"),
3223 MockRead(" world"),
3224 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423225 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403226 };
3227
[email protected]31a2bfe2010-02-09 08:03:393228 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593229 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403230
3231 TestCompletionCallback callback;
3232
[email protected]5a1d7ca2010-04-28 20:12:273233 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423234 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403235
3236 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423237 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403238
[email protected]1c773ea12009-04-28 19:58:423239 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403240 EXPECT_TRUE(response != NULL);
3241
3242 EXPECT_TRUE(response->headers != NULL);
3243 std::string status_line = response->headers->GetStatusLine();
3244 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3245
[email protected]ab739042011-04-07 15:22:283246 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403247
3248 std::string response_data;
3249 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423250 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403251 EXPECT_EQ("hello world", response_data);
3252
3253 // Empty the current queue. This is necessary because idle sockets are
3254 // added to the connection pool asynchronously with a PostTask.
3255 MessageLoop::current()->RunAllPending();
3256
3257 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283258 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403259}
3260
[email protected]76a505b2010-08-25 06:23:003261// Make sure that we recycle a SSL socket after reading all of the response
3262// body.
3263TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3264 SessionDependencies session_deps;
3265 HttpRequestInfo request;
3266 request.method = "GET";
3267 request.url = GURL("https://www.google.com/");
3268 request.load_flags = 0;
3269
3270 MockWrite data_writes[] = {
3271 MockWrite("GET / HTTP/1.1\r\n"
3272 "Host: www.google.com\r\n"
3273 "Connection: keep-alive\r\n\r\n"),
3274 };
3275
3276 MockRead data_reads[] = {
3277 MockRead("HTTP/1.1 200 OK\r\n"),
3278 MockRead("Content-Length: 11\r\n\r\n"),
3279 MockRead("hello world"),
3280 MockRead(false, OK),
3281 };
3282
3283 SSLSocketDataProvider ssl(true, OK);
3284 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3285
3286 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3287 data_writes, arraysize(data_writes));
3288 session_deps.socket_factory.AddSocketDataProvider(&data);
3289
3290 TestCompletionCallback callback;
3291
3292 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3293 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3294
3295 int rv = trans->Start(&request, &callback, BoundNetLog());
3296
3297 EXPECT_EQ(ERR_IO_PENDING, rv);
3298 EXPECT_EQ(OK, callback.WaitForResult());
3299
3300 const HttpResponseInfo* response = trans->GetResponseInfo();
3301 ASSERT_TRUE(response != NULL);
3302 ASSERT_TRUE(response->headers != NULL);
3303 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3304
[email protected]ab739042011-04-07 15:22:283305 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003306
3307 std::string response_data;
3308 rv = ReadTransaction(trans.get(), &response_data);
3309 EXPECT_EQ(OK, rv);
3310 EXPECT_EQ("hello world", response_data);
3311
3312 // Empty the current queue. This is necessary because idle sockets are
3313 // added to the connection pool asynchronously with a PostTask.
3314 MessageLoop::current()->RunAllPending();
3315
3316 // We now check to make sure the socket was added back to the pool.
3317 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3318}
3319
3320// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3321// from the pool and make sure that we recover okay.
3322TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3323 SessionDependencies session_deps;
3324 HttpRequestInfo request;
3325 request.method = "GET";
3326 request.url = GURL("https://www.google.com/");
3327 request.load_flags = 0;
3328
3329 MockWrite data_writes[] = {
3330 MockWrite("GET / HTTP/1.1\r\n"
3331 "Host: www.google.com\r\n"
3332 "Connection: keep-alive\r\n\r\n"),
3333 MockWrite("GET / HTTP/1.1\r\n"
3334 "Host: www.google.com\r\n"
3335 "Connection: keep-alive\r\n\r\n"),
3336 };
3337
3338 MockRead data_reads[] = {
3339 MockRead("HTTP/1.1 200 OK\r\n"),
3340 MockRead("Content-Length: 11\r\n\r\n"),
3341 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3342 MockRead("hello world"),
3343 MockRead(true, 0, 0) // EOF
3344 };
3345
3346 SSLSocketDataProvider ssl(true, OK);
3347 SSLSocketDataProvider ssl2(true, OK);
3348 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3349 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3350
3351 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3352 data_writes, arraysize(data_writes));
3353 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3354 data_writes, arraysize(data_writes));
3355 session_deps.socket_factory.AddSocketDataProvider(&data);
3356 session_deps.socket_factory.AddSocketDataProvider(&data2);
3357
3358 TestCompletionCallback callback;
3359
3360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3361 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3362
3363 int rv = trans->Start(&request, &callback, BoundNetLog());
3364
3365 EXPECT_EQ(ERR_IO_PENDING, rv);
3366 EXPECT_EQ(OK, callback.WaitForResult());
3367
3368 const HttpResponseInfo* response = trans->GetResponseInfo();
3369 ASSERT_TRUE(response != NULL);
3370 ASSERT_TRUE(response->headers != NULL);
3371 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3372
[email protected]ab739042011-04-07 15:22:283373 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003374
3375 std::string response_data;
3376 rv = ReadTransaction(trans.get(), &response_data);
3377 EXPECT_EQ(OK, rv);
3378 EXPECT_EQ("hello world", response_data);
3379
3380 // Empty the current queue. This is necessary because idle sockets are
3381 // added to the connection pool asynchronously with a PostTask.
3382 MessageLoop::current()->RunAllPending();
3383
3384 // We now check to make sure the socket was added back to the pool.
3385 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3386
3387 // Now start the second transaction, which should reuse the previous socket.
3388
3389 trans.reset(new HttpNetworkTransaction(session));
3390
3391 rv = trans->Start(&request, &callback, BoundNetLog());
3392
3393 EXPECT_EQ(ERR_IO_PENDING, rv);
3394 EXPECT_EQ(OK, callback.WaitForResult());
3395
3396 response = trans->GetResponseInfo();
3397 ASSERT_TRUE(response != NULL);
3398 ASSERT_TRUE(response->headers != NULL);
3399 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3400
[email protected]ab739042011-04-07 15:22:283401 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003402
3403 rv = ReadTransaction(trans.get(), &response_data);
3404 EXPECT_EQ(OK, rv);
3405 EXPECT_EQ("hello world", response_data);
3406
3407 // Empty the current queue. This is necessary because idle sockets are
3408 // added to the connection pool asynchronously with a PostTask.
3409 MessageLoop::current()->RunAllPending();
3410
3411 // We now check to make sure the socket was added back to the pool.
3412 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3413}
3414
[email protected]b4404c02009-04-10 16:38:523415// Make sure that we recycle a socket after a zero-length response.
3416// http://crbug.com/9880
3417TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423418 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523419 request.method = "GET";
3420 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3421 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3422 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3423 "rt=prt.2642,ol.2649,xjs.2951");
3424 request.load_flags = 0;
3425
[email protected]cb9bf6ca2011-01-28 13:15:273426 SessionDependencies session_deps;
3427 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3428
3429 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3430
[email protected]b4404c02009-04-10 16:38:523431 MockRead data_reads[] = {
3432 MockRead("HTTP/1.1 204 No Content\r\n"
3433 "Content-Length: 0\r\n"
3434 "Content-Type: text/html\r\n\r\n"),
3435 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423436 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523437 };
3438
[email protected]31a2bfe2010-02-09 08:03:393439 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593440 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523441
3442 TestCompletionCallback callback;
3443
[email protected]5a1d7ca2010-04-28 20:12:273444 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423445 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523446
3447 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423448 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523449
[email protected]1c773ea12009-04-28 19:58:423450 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523451 EXPECT_TRUE(response != NULL);
3452
3453 EXPECT_TRUE(response->headers != NULL);
3454 std::string status_line = response->headers->GetStatusLine();
3455 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3456
[email protected]ab739042011-04-07 15:22:283457 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523458
3459 std::string response_data;
3460 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423461 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523462 EXPECT_EQ("", response_data);
3463
3464 // Empty the current queue. This is necessary because idle sockets are
3465 // added to the connection pool asynchronously with a PostTask.
3466 MessageLoop::current()->RunAllPending();
3467
3468 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283469 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523470}
3471
[email protected]372d34a2008-11-05 21:30:513472TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423473 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513474 // Transaction 1: a GET request that succeeds. The socket is recycled
3475 // after use.
3476 request[0].method = "GET";
3477 request[0].url = GURL("http://www.google.com/");
3478 request[0].load_flags = 0;
3479 // Transaction 2: a POST request. Reuses the socket kept alive from
3480 // transaction 1. The first attempts fails when writing the POST data.
3481 // This causes the transaction to retry with a new socket. The second
3482 // attempt succeeds.
3483 request[1].method = "POST";
3484 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423485 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513486 request[1].upload_data->AppendBytes("foo", 3);
3487 request[1].load_flags = 0;
3488
[email protected]228ff742009-06-05 01:19:593489 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513491
3492 // The first socket is used for transaction 1 and the first attempt of
3493 // transaction 2.
3494
3495 // The response of transaction 1.
3496 MockRead data_reads1[] = {
3497 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3498 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423499 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513500 };
3501 // The mock write results of transaction 1 and the first attempt of
3502 // transaction 2.
3503 MockWrite data_writes1[] = {
3504 MockWrite(false, 64), // GET
3505 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423506 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513507 };
[email protected]31a2bfe2010-02-09 08:03:393508 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3509 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513510
3511 // The second socket is used for the second attempt of transaction 2.
3512
3513 // The response of transaction 2.
3514 MockRead data_reads2[] = {
3515 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3516 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423517 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513518 };
3519 // The mock write results of the second attempt of transaction 2.
3520 MockWrite data_writes2[] = {
3521 MockWrite(false, 93), // POST
3522 MockWrite(false, 3), // POST data
3523 };
[email protected]31a2bfe2010-02-09 08:03:393524 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3525 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513526
[email protected]5ecc992a42009-11-11 01:41:593527 session_deps.socket_factory.AddSocketDataProvider(&data1);
3528 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513529
3530 const char* kExpectedResponseData[] = {
3531 "hello world", "welcome"
3532 };
3533
3534 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423535 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433536 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513537
3538 TestCompletionCallback callback;
3539
[email protected]5a1d7ca2010-04-28 20:12:273540 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423541 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513542
3543 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423544 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513545
[email protected]1c773ea12009-04-28 19:58:423546 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513547 EXPECT_TRUE(response != NULL);
3548
3549 EXPECT_TRUE(response->headers != NULL);
3550 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3551
3552 std::string response_data;
3553 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423554 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513555 EXPECT_EQ(kExpectedResponseData[i], response_data);
3556 }
3557}
[email protected]f9ee6b52008-11-08 06:46:233558
3559// Test the request-challenge-retry sequence for basic auth when there is
3560// an identity in the URL. The request should be sent as normal, but when
3561// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323562TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423563 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233564 request.method = "GET";
3565 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293566 request.url = GURL("http://foo:b@[email protected]/");
3567
[email protected]cb9bf6ca2011-01-28 13:15:273568 SessionDependencies session_deps;
3569 scoped_ptr<HttpTransaction> trans(
3570 new HttpNetworkTransaction(CreateSession(&session_deps)));
3571
[email protected]a97cca42009-08-14 01:00:293572 // The password contains an escaped character -- for this test to pass it
3573 // will need to be unescaped by HttpNetworkTransaction.
3574 EXPECT_EQ("b%40r", request.url.password());
3575
[email protected]ea9dc9a2009-09-05 00:43:323576 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233577
3578 MockWrite data_writes1[] = {
3579 MockWrite("GET / HTTP/1.1\r\n"
3580 "Host: www.google.com\r\n"
3581 "Connection: keep-alive\r\n\r\n"),
3582 };
3583
3584 MockRead data_reads1[] = {
3585 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3586 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3587 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423588 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233589 };
3590
3591 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323592 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233593 MockWrite data_writes2[] = {
3594 MockWrite("GET / HTTP/1.1\r\n"
3595 "Host: www.google.com\r\n"
3596 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293597 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233598 };
3599
3600 MockRead data_reads2[] = {
3601 MockRead("HTTP/1.0 200 OK\r\n"),
3602 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423603 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233604 };
3605
[email protected]31a2bfe2010-02-09 08:03:393606 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3607 data_writes1, arraysize(data_writes1));
3608 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3609 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593610 session_deps.socket_factory.AddSocketDataProvider(&data1);
3611 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233612
3613 TestCompletionCallback callback1;
3614
[email protected]5a1d7ca2010-04-28 20:12:273615 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423616 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233617
3618 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423619 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233620
[email protected]0757e7702009-03-27 04:00:223621 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3622 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443623 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423624 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223625 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423626 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223627 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3628
[email protected]1c773ea12009-04-28 19:58:423629 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233630 EXPECT_FALSE(response == NULL);
3631
3632 // There is no challenge info, since the identity in URL worked.
3633 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3634
3635 EXPECT_EQ(100, response->headers->GetContentLength());
3636
3637 // Empty the current queue.
3638 MessageLoop::current()->RunAllPending();
3639}
3640
[email protected]ea9dc9a2009-09-05 00:43:323641// Test the request-challenge-retry sequence for basic auth when there is
3642// an incorrect identity in the URL. The identity from the URL should be used
3643// only once.
3644TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323645 HttpRequestInfo request;
3646 request.method = "GET";
3647 // Note: the URL has a username:password in it. The password "baz" is
3648 // wrong (should be "bar").
3649 request.url = GURL("http://foo:[email protected]/");
3650
3651 request.load_flags = LOAD_NORMAL;
3652
[email protected]cb9bf6ca2011-01-28 13:15:273653 SessionDependencies session_deps;
3654 scoped_ptr<HttpTransaction> trans(
3655 new HttpNetworkTransaction(CreateSession(&session_deps)));
3656
[email protected]ea9dc9a2009-09-05 00:43:323657 MockWrite data_writes1[] = {
3658 MockWrite("GET / HTTP/1.1\r\n"
3659 "Host: www.google.com\r\n"
3660 "Connection: keep-alive\r\n\r\n"),
3661 };
3662
3663 MockRead data_reads1[] = {
3664 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3665 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3666 MockRead("Content-Length: 10\r\n\r\n"),
3667 MockRead(false, ERR_FAILED),
3668 };
3669
3670 // After the challenge above, the transaction will be restarted using the
3671 // identity from the url (foo, baz) to answer the challenge.
3672 MockWrite data_writes2[] = {
3673 MockWrite("GET / HTTP/1.1\r\n"
3674 "Host: www.google.com\r\n"
3675 "Connection: keep-alive\r\n"
3676 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3677 };
3678
3679 MockRead data_reads2[] = {
3680 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3681 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3682 MockRead("Content-Length: 10\r\n\r\n"),
3683 MockRead(false, ERR_FAILED),
3684 };
3685
3686 // After the challenge above, the transaction will be restarted using the
3687 // identity supplied by the user (foo, bar) to answer the challenge.
3688 MockWrite data_writes3[] = {
3689 MockWrite("GET / HTTP/1.1\r\n"
3690 "Host: www.google.com\r\n"
3691 "Connection: keep-alive\r\n"
3692 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3693 };
3694
3695 MockRead data_reads3[] = {
3696 MockRead("HTTP/1.0 200 OK\r\n"),
3697 MockRead("Content-Length: 100\r\n\r\n"),
3698 MockRead(false, OK),
3699 };
3700
[email protected]31a2bfe2010-02-09 08:03:393701 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3702 data_writes1, arraysize(data_writes1));
3703 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3704 data_writes2, arraysize(data_writes2));
3705 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3706 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593707 session_deps.socket_factory.AddSocketDataProvider(&data1);
3708 session_deps.socket_factory.AddSocketDataProvider(&data2);
3709 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323710
3711 TestCompletionCallback callback1;
3712
[email protected]5a1d7ca2010-04-28 20:12:273713 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323714 EXPECT_EQ(ERR_IO_PENDING, rv);
3715
3716 rv = callback1.WaitForResult();
3717 EXPECT_EQ(OK, rv);
3718
3719 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3720 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443721 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323722 EXPECT_EQ(ERR_IO_PENDING, rv);
3723 rv = callback2.WaitForResult();
3724 EXPECT_EQ(OK, rv);
3725 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3726
3727 const HttpResponseInfo* response = trans->GetResponseInfo();
3728 EXPECT_FALSE(response == NULL);
3729 // The password prompt info should have been set in response->auth_challenge.
3730 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3731
3732 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3733 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3734 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3735
3736 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443737 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323738 EXPECT_EQ(ERR_IO_PENDING, rv);
3739 rv = callback3.WaitForResult();
3740 EXPECT_EQ(OK, rv);
3741 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3742
3743 response = trans->GetResponseInfo();
3744 EXPECT_FALSE(response == NULL);
3745
3746 // There is no challenge info, since the identity worked.
3747 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3748
3749 EXPECT_EQ(100, response->headers->GetContentLength());
3750
3751 // Empty the current queue.
3752 MessageLoop::current()->RunAllPending();
3753}
3754
[email protected]f9ee6b52008-11-08 06:46:233755// Test that previously tried username/passwords for a realm get re-used.
3756TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593757 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273758 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233759
3760 // Transaction 1: authenticate (foo, bar) on MyRealm1
3761 {
[email protected]1c773ea12009-04-28 19:58:423762 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233763 request.method = "GET";
3764 request.url = GURL("http://www.google.com/x/y/z");
3765 request.load_flags = 0;
3766
[email protected]cb9bf6ca2011-01-28 13:15:273767 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3768
[email protected]f9ee6b52008-11-08 06:46:233769 MockWrite data_writes1[] = {
3770 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3771 "Host: www.google.com\r\n"
3772 "Connection: keep-alive\r\n\r\n"),
3773 };
3774
3775 MockRead data_reads1[] = {
3776 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3777 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3778 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423779 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233780 };
3781
3782 // Resend with authorization (username=foo, password=bar)
3783 MockWrite data_writes2[] = {
3784 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3785 "Host: www.google.com\r\n"
3786 "Connection: keep-alive\r\n"
3787 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3788 };
3789
3790 // Sever accepts the authorization.
3791 MockRead data_reads2[] = {
3792 MockRead("HTTP/1.0 200 OK\r\n"),
3793 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423794 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233795 };
3796
[email protected]31a2bfe2010-02-09 08:03:393797 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3798 data_writes1, arraysize(data_writes1));
3799 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3800 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593801 session_deps.socket_factory.AddSocketDataProvider(&data1);
3802 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233803
3804 TestCompletionCallback callback1;
3805
[email protected]5a1d7ca2010-04-28 20:12:273806 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423807 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233808
3809 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423810 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233811
[email protected]1c773ea12009-04-28 19:58:423812 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233813 EXPECT_FALSE(response == NULL);
3814
3815 // The password prompt info should have been set in
3816 // response->auth_challenge.
3817 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3818
[email protected]71e4573a2009-05-21 22:03:003819 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233820 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3821 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3822
3823 TestCompletionCallback callback2;
3824
[email protected]13c8a092010-07-29 06:15:443825 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233827
3828 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423829 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233830
3831 response = trans->GetResponseInfo();
3832 EXPECT_FALSE(response == NULL);
3833 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3834 EXPECT_EQ(100, response->headers->GetContentLength());
3835 }
3836
3837 // ------------------------------------------------------------------------
3838
3839 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3840 {
[email protected]1c773ea12009-04-28 19:58:423841 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233842 request.method = "GET";
3843 // Note that Transaction 1 was at /x/y/z, so this is in the same
3844 // protection space as MyRealm1.
3845 request.url = GURL("http://www.google.com/x/y/a/b");
3846 request.load_flags = 0;
3847
[email protected]cb9bf6ca2011-01-28 13:15:273848 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3849
[email protected]f9ee6b52008-11-08 06:46:233850 MockWrite data_writes1[] = {
3851 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3852 "Host: www.google.com\r\n"
3853 "Connection: keep-alive\r\n"
3854 // Send preemptive authorization for MyRealm1
3855 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3856 };
3857
3858 // The server didn't like the preemptive authorization, and
3859 // challenges us for a different realm (MyRealm2).
3860 MockRead data_reads1[] = {
3861 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3862 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3863 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423864 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233865 };
3866
3867 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3868 MockWrite data_writes2[] = {
3869 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3870 "Host: www.google.com\r\n"
3871 "Connection: keep-alive\r\n"
3872 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3873 };
3874
3875 // Sever accepts the authorization.
3876 MockRead data_reads2[] = {
3877 MockRead("HTTP/1.0 200 OK\r\n"),
3878 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423879 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233880 };
3881
[email protected]31a2bfe2010-02-09 08:03:393882 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3883 data_writes1, arraysize(data_writes1));
3884 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3885 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593886 session_deps.socket_factory.AddSocketDataProvider(&data1);
3887 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233888
3889 TestCompletionCallback callback1;
3890
[email protected]5a1d7ca2010-04-28 20:12:273891 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423892 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233893
3894 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423895 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233896
[email protected]1c773ea12009-04-28 19:58:423897 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233898 EXPECT_FALSE(response == NULL);
3899
3900 // The password prompt info should have been set in
3901 // response->auth_challenge.
3902 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3903
[email protected]71e4573a2009-05-21 22:03:003904 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233905 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3906 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3907
3908 TestCompletionCallback callback2;
3909
[email protected]13c8a092010-07-29 06:15:443910 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233912
3913 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423914 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233915
3916 response = trans->GetResponseInfo();
3917 EXPECT_FALSE(response == NULL);
3918 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3919 EXPECT_EQ(100, response->headers->GetContentLength());
3920 }
3921
3922 // ------------------------------------------------------------------------
3923
3924 // Transaction 3: Resend a request in MyRealm's protection space --
3925 // succeed with preemptive authorization.
3926 {
[email protected]1c773ea12009-04-28 19:58:423927 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233928 request.method = "GET";
3929 request.url = GURL("http://www.google.com/x/y/z2");
3930 request.load_flags = 0;
3931
[email protected]cb9bf6ca2011-01-28 13:15:273932 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3933
[email protected]f9ee6b52008-11-08 06:46:233934 MockWrite data_writes1[] = {
3935 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3936 "Host: www.google.com\r\n"
3937 "Connection: keep-alive\r\n"
3938 // The authorization for MyRealm1 gets sent preemptively
3939 // (since the url is in the same protection space)
3940 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3941 };
3942
3943 // Sever accepts the preemptive authorization
3944 MockRead data_reads1[] = {
3945 MockRead("HTTP/1.0 200 OK\r\n"),
3946 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423947 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233948 };
3949
[email protected]31a2bfe2010-02-09 08:03:393950 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3951 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593952 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233953
3954 TestCompletionCallback callback1;
3955
[email protected]5a1d7ca2010-04-28 20:12:273956 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423957 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233958
3959 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423960 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233961
[email protected]1c773ea12009-04-28 19:58:423962 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233963 EXPECT_FALSE(response == NULL);
3964
3965 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3966 EXPECT_EQ(100, response->headers->GetContentLength());
3967 }
3968
3969 // ------------------------------------------------------------------------
3970
3971 // Transaction 4: request another URL in MyRealm (however the
3972 // url is not known to belong to the protection space, so no pre-auth).
3973 {
[email protected]1c773ea12009-04-28 19:58:423974 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233975 request.method = "GET";
3976 request.url = GURL("http://www.google.com/x/1");
3977 request.load_flags = 0;
3978
[email protected]cb9bf6ca2011-01-28 13:15:273979 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3980
[email protected]f9ee6b52008-11-08 06:46:233981 MockWrite data_writes1[] = {
3982 MockWrite("GET /x/1 HTTP/1.1\r\n"
3983 "Host: www.google.com\r\n"
3984 "Connection: keep-alive\r\n\r\n"),
3985 };
3986
3987 MockRead data_reads1[] = {
3988 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3989 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3990 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423991 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233992 };
3993
3994 // Resend with authorization from MyRealm's cache.
3995 MockWrite data_writes2[] = {
3996 MockWrite("GET /x/1 HTTP/1.1\r\n"
3997 "Host: www.google.com\r\n"
3998 "Connection: keep-alive\r\n"
3999 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4000 };
4001
4002 // Sever accepts the authorization.
4003 MockRead data_reads2[] = {
4004 MockRead("HTTP/1.0 200 OK\r\n"),
4005 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424006 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234007 };
4008
[email protected]31a2bfe2010-02-09 08:03:394009 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4010 data_writes1, arraysize(data_writes1));
4011 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4012 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594013 session_deps.socket_factory.AddSocketDataProvider(&data1);
4014 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234015
4016 TestCompletionCallback callback1;
4017
[email protected]5a1d7ca2010-04-28 20:12:274018 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424019 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234020
4021 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424022 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234023
[email protected]0757e7702009-03-27 04:00:224024 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4025 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444026 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224028 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424029 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224030 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4031
[email protected]1c773ea12009-04-28 19:58:424032 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234033 EXPECT_FALSE(response == NULL);
4034 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4035 EXPECT_EQ(100, response->headers->GetContentLength());
4036 }
4037
4038 // ------------------------------------------------------------------------
4039
4040 // Transaction 5: request a URL in MyRealm, but the server rejects the
4041 // cached identity. Should invalidate and re-prompt.
4042 {
[email protected]1c773ea12009-04-28 19:58:424043 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234044 request.method = "GET";
4045 request.url = GURL("http://www.google.com/p/q/t");
4046 request.load_flags = 0;
4047
[email protected]cb9bf6ca2011-01-28 13:15:274048 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4049
[email protected]f9ee6b52008-11-08 06:46:234050 MockWrite data_writes1[] = {
4051 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4052 "Host: www.google.com\r\n"
4053 "Connection: keep-alive\r\n\r\n"),
4054 };
4055
4056 MockRead data_reads1[] = {
4057 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4058 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4059 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424060 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234061 };
4062
4063 // Resend with authorization from cache for MyRealm.
4064 MockWrite data_writes2[] = {
4065 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4066 "Host: www.google.com\r\n"
4067 "Connection: keep-alive\r\n"
4068 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4069 };
4070
4071 // Sever rejects the authorization.
4072 MockRead data_reads2[] = {
4073 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4074 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4075 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424076 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234077 };
4078
4079 // At this point we should prompt for new credentials for MyRealm.
4080 // Restart with username=foo3, password=foo4.
4081 MockWrite data_writes3[] = {
4082 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4083 "Host: www.google.com\r\n"
4084 "Connection: keep-alive\r\n"
4085 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4086 };
4087
4088 // Sever accepts the authorization.
4089 MockRead data_reads3[] = {
4090 MockRead("HTTP/1.0 200 OK\r\n"),
4091 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424092 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234093 };
4094
[email protected]31a2bfe2010-02-09 08:03:394095 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4096 data_writes1, arraysize(data_writes1));
4097 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4098 data_writes2, arraysize(data_writes2));
4099 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4100 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594101 session_deps.socket_factory.AddSocketDataProvider(&data1);
4102 session_deps.socket_factory.AddSocketDataProvider(&data2);
4103 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234104
4105 TestCompletionCallback callback1;
4106
[email protected]5a1d7ca2010-04-28 20:12:274107 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234109
4110 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424111 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234112
[email protected]0757e7702009-03-27 04:00:224113 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4114 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444115 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424116 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224117 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424118 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224119 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4120
[email protected]1c773ea12009-04-28 19:58:424121 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234122 EXPECT_FALSE(response == NULL);
4123
4124 // The password prompt info should have been set in
4125 // response->auth_challenge.
4126 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4127
[email protected]71e4573a2009-05-21 22:03:004128 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234129 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4130 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4131
[email protected]0757e7702009-03-27 04:00:224132 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234133
[email protected]13c8a092010-07-29 06:15:444134 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424135 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234136
[email protected]0757e7702009-03-27 04:00:224137 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424138 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234139
4140 response = trans->GetResponseInfo();
4141 EXPECT_FALSE(response == NULL);
4142 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4143 EXPECT_EQ(100, response->headers->GetContentLength());
4144 }
4145}
[email protected]89ceba9a2009-03-21 03:46:064146
[email protected]3c32c5f2010-05-18 15:18:124147// Tests that nonce count increments when multiple auth attempts
4148// are started with the same nonce.
4149TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4150 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444151 HttpAuthHandlerDigest::Factory* digest_factory =
4152 new HttpAuthHandlerDigest::Factory();
4153 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4154 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4155 digest_factory->set_nonce_generator(nonce_generator);
4156 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274157 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124158
4159 // Transaction 1: authenticate (foo, bar) on MyRealm1
4160 {
[email protected]3c32c5f2010-05-18 15:18:124161 HttpRequestInfo request;
4162 request.method = "GET";
4163 request.url = GURL("http://www.google.com/x/y/z");
4164 request.load_flags = 0;
4165
[email protected]cb9bf6ca2011-01-28 13:15:274166 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4167
[email protected]3c32c5f2010-05-18 15:18:124168 MockWrite data_writes1[] = {
4169 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4170 "Host: www.google.com\r\n"
4171 "Connection: keep-alive\r\n\r\n"),
4172 };
4173
4174 MockRead data_reads1[] = {
4175 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4176 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4177 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4178 MockRead(false, OK),
4179 };
4180
4181 // Resend with authorization (username=foo, password=bar)
4182 MockWrite data_writes2[] = {
4183 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4184 "Host: www.google.com\r\n"
4185 "Connection: keep-alive\r\n"
4186 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4187 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4188 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4189 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4190 };
4191
4192 // Sever accepts the authorization.
4193 MockRead data_reads2[] = {
4194 MockRead("HTTP/1.0 200 OK\r\n"),
4195 MockRead(false, OK),
4196 };
4197
4198 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4199 data_writes1, arraysize(data_writes1));
4200 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4201 data_writes2, arraysize(data_writes2));
4202 session_deps.socket_factory.AddSocketDataProvider(&data1);
4203 session_deps.socket_factory.AddSocketDataProvider(&data2);
4204
4205 TestCompletionCallback callback1;
4206
4207 int rv = trans->Start(&request, &callback1, BoundNetLog());
4208 EXPECT_EQ(ERR_IO_PENDING, rv);
4209
4210 rv = callback1.WaitForResult();
4211 EXPECT_EQ(OK, rv);
4212
4213 const HttpResponseInfo* response = trans->GetResponseInfo();
4214 ASSERT_FALSE(response == NULL);
4215
4216 // The password prompt info should have been set in
4217 // response->auth_challenge.
4218 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4219
4220 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4221 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4222 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4223
4224 TestCompletionCallback callback2;
4225
[email protected]13c8a092010-07-29 06:15:444226 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124227 EXPECT_EQ(ERR_IO_PENDING, rv);
4228
4229 rv = callback2.WaitForResult();
4230 EXPECT_EQ(OK, rv);
4231
4232 response = trans->GetResponseInfo();
4233 ASSERT_FALSE(response == NULL);
4234 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4235 }
4236
4237 // ------------------------------------------------------------------------
4238
4239 // Transaction 2: Request another resource in digestive's protection space.
4240 // This will preemptively add an Authorization header which should have an
4241 // "nc" value of 2 (as compared to 1 in the first use.
4242 {
[email protected]3c32c5f2010-05-18 15:18:124243 HttpRequestInfo request;
4244 request.method = "GET";
4245 // Note that Transaction 1 was at /x/y/z, so this is in the same
4246 // protection space as digest.
4247 request.url = GURL("http://www.google.com/x/y/a/b");
4248 request.load_flags = 0;
4249
[email protected]cb9bf6ca2011-01-28 13:15:274250 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4251
[email protected]3c32c5f2010-05-18 15:18:124252 MockWrite data_writes1[] = {
4253 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4254 "Host: www.google.com\r\n"
4255 "Connection: keep-alive\r\n"
4256 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4257 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4258 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4259 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4260 };
4261
4262 // Sever accepts the authorization.
4263 MockRead data_reads1[] = {
4264 MockRead("HTTP/1.0 200 OK\r\n"),
4265 MockRead("Content-Length: 100\r\n\r\n"),
4266 MockRead(false, OK),
4267 };
4268
4269 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4270 data_writes1, arraysize(data_writes1));
4271 session_deps.socket_factory.AddSocketDataProvider(&data1);
4272
4273 TestCompletionCallback callback1;
4274
4275 int rv = trans->Start(&request, &callback1, BoundNetLog());
4276 EXPECT_EQ(ERR_IO_PENDING, rv);
4277
4278 rv = callback1.WaitForResult();
4279 EXPECT_EQ(OK, rv);
4280
4281 const HttpResponseInfo* response = trans->GetResponseInfo();
4282 ASSERT_FALSE(response == NULL);
4283 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4284 }
4285}
4286
[email protected]89ceba9a2009-03-21 03:46:064287// Test the ResetStateForRestart() private method.
4288TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4289 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594290 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404291 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434292 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064293
4294 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064295 trans->read_buf_ = new IOBuffer(15);
4296 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204297 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064298
4299 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144300 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574301 response->auth_challenge = new AuthChallengeInfo();
4302 response->ssl_info.cert_status = -15;
4303 response->response_time = base::Time::Now();
4304 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064305
4306 { // Setup state for response_.vary_data
4307 HttpRequestInfo request;
4308 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4309 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274310 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434311 request.extra_headers.SetHeader("Foo", "1");
4312 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574313 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064314 }
4315
4316 // Cause the above state to be reset.
4317 trans->ResetStateForRestart();
4318
4319 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074320 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064321 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204322 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574323 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4324 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044325 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574326 EXPECT_EQ(0, response->ssl_info.cert_status);
4327 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064328}
4329
[email protected]bacff652009-03-31 17:50:334330// Test HTTPS connections to a site with a bad certificate
4331TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334332 HttpRequestInfo request;
4333 request.method = "GET";
4334 request.url = GURL("https://www.google.com/");
4335 request.load_flags = 0;
4336
[email protected]cb9bf6ca2011-01-28 13:15:274337 SessionDependencies session_deps;
4338 scoped_ptr<HttpTransaction> trans(
4339 new HttpNetworkTransaction(CreateSession(&session_deps)));
4340
[email protected]bacff652009-03-31 17:50:334341 MockWrite data_writes[] = {
4342 MockWrite("GET / HTTP/1.1\r\n"
4343 "Host: www.google.com\r\n"
4344 "Connection: keep-alive\r\n\r\n"),
4345 };
4346
4347 MockRead data_reads[] = {
4348 MockRead("HTTP/1.0 200 OK\r\n"),
4349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4350 MockRead("Content-Length: 100\r\n\r\n"),
4351 MockRead(false, OK),
4352 };
4353
[email protected]5ecc992a42009-11-11 01:41:594354 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394355 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4356 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594357 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4358 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334359
[email protected]5ecc992a42009-11-11 01:41:594360 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4361 session_deps.socket_factory.AddSocketDataProvider(&data);
4362 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4363 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334364
4365 TestCompletionCallback callback;
4366
[email protected]5a1d7ca2010-04-28 20:12:274367 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334368 EXPECT_EQ(ERR_IO_PENDING, rv);
4369
4370 rv = callback.WaitForResult();
4371 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4372
4373 rv = trans->RestartIgnoringLastError(&callback);
4374 EXPECT_EQ(ERR_IO_PENDING, rv);
4375
4376 rv = callback.WaitForResult();
4377 EXPECT_EQ(OK, rv);
4378
4379 const HttpResponseInfo* response = trans->GetResponseInfo();
4380
4381 EXPECT_FALSE(response == NULL);
4382 EXPECT_EQ(100, response->headers->GetContentLength());
4383}
4384
4385// Test HTTPS connections to a site with a bad certificate, going through a
4386// proxy
4387TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004388 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334389
4390 HttpRequestInfo request;
4391 request.method = "GET";
4392 request.url = GURL("https://www.google.com/");
4393 request.load_flags = 0;
4394
4395 MockWrite proxy_writes[] = {
4396 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454397 "Host: www.google.com\r\n"
4398 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334399 };
4400
4401 MockRead proxy_reads[] = {
4402 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424403 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334404 };
4405
4406 MockWrite data_writes[] = {
4407 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454408 "Host: www.google.com\r\n"
4409 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334410 MockWrite("GET / HTTP/1.1\r\n"
4411 "Host: www.google.com\r\n"
4412 "Connection: keep-alive\r\n\r\n"),
4413 };
4414
4415 MockRead data_reads[] = {
4416 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4417 MockRead("HTTP/1.0 200 OK\r\n"),
4418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4419 MockRead("Content-Length: 100\r\n\r\n"),
4420 MockRead(false, OK),
4421 };
4422
[email protected]31a2bfe2010-02-09 08:03:394423 StaticSocketDataProvider ssl_bad_certificate(
4424 proxy_reads, arraysize(proxy_reads),
4425 proxy_writes, arraysize(proxy_writes));
4426 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4427 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594428 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4429 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334430
[email protected]5ecc992a42009-11-11 01:41:594431 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4432 session_deps.socket_factory.AddSocketDataProvider(&data);
4433 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334435
4436 TestCompletionCallback callback;
4437
4438 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594439 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334440
[email protected]d207a5f2009-06-04 05:28:404441 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434442 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334443
[email protected]5a1d7ca2010-04-28 20:12:274444 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334445 EXPECT_EQ(ERR_IO_PENDING, rv);
4446
4447 rv = callback.WaitForResult();
4448 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4449
4450 rv = trans->RestartIgnoringLastError(&callback);
4451 EXPECT_EQ(ERR_IO_PENDING, rv);
4452
4453 rv = callback.WaitForResult();
4454 EXPECT_EQ(OK, rv);
4455
4456 const HttpResponseInfo* response = trans->GetResponseInfo();
4457
4458 EXPECT_FALSE(response == NULL);
4459 EXPECT_EQ(100, response->headers->GetContentLength());
4460 }
4461}
4462
[email protected]2df19bb2010-08-25 20:13:464463
4464// Test HTTPS connections to a site, going through an HTTPS proxy
4465TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004466 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464467
4468 HttpRequestInfo request;
4469 request.method = "GET";
4470 request.url = GURL("https://www.google.com/");
4471 request.load_flags = 0;
4472
4473 MockWrite data_writes[] = {
4474 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4475 "Host: www.google.com\r\n"
4476 "Proxy-Connection: keep-alive\r\n\r\n"),
4477 MockWrite("GET / HTTP/1.1\r\n"
4478 "Host: www.google.com\r\n"
4479 "Connection: keep-alive\r\n\r\n"),
4480 };
4481
4482 MockRead data_reads[] = {
4483 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4484 MockRead("HTTP/1.1 200 OK\r\n"),
4485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4486 MockRead("Content-Length: 100\r\n\r\n"),
4487 MockRead(false, OK),
4488 };
4489
4490 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4491 data_writes, arraysize(data_writes));
4492 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4493 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4494
4495 session_deps.socket_factory.AddSocketDataProvider(&data);
4496 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4497 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4498
4499 TestCompletionCallback callback;
4500
4501 scoped_ptr<HttpTransaction> trans(
4502 new HttpNetworkTransaction(CreateSession(&session_deps)));
4503
4504 int rv = trans->Start(&request, &callback, BoundNetLog());
4505 EXPECT_EQ(ERR_IO_PENDING, rv);
4506
4507 rv = callback.WaitForResult();
4508 EXPECT_EQ(OK, rv);
4509 const HttpResponseInfo* response = trans->GetResponseInfo();
4510
4511 ASSERT_FALSE(response == NULL);
4512
4513 EXPECT_TRUE(response->headers->IsKeepAlive());
4514 EXPECT_EQ(200, response->headers->response_code());
4515 EXPECT_EQ(100, response->headers->GetContentLength());
4516 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4517}
4518
[email protected]511f6f52010-12-17 03:58:294519// Test an HTTPS Proxy's ability to redirect a CONNECT request
4520TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4521 SessionDependencies session_deps(
4522 ProxyService::CreateFixed("https://proxy:70"));
4523
4524 HttpRequestInfo request;
4525 request.method = "GET";
4526 request.url = GURL("https://www.google.com/");
4527 request.load_flags = 0;
4528
4529 MockWrite data_writes[] = {
4530 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4531 "Host: www.google.com\r\n"
4532 "Proxy-Connection: keep-alive\r\n\r\n"),
4533 };
4534
4535 MockRead data_reads[] = {
4536 MockRead("HTTP/1.1 302 Redirect\r\n"),
4537 MockRead("Location: http://login.example.com/\r\n"),
4538 MockRead("Content-Length: 0\r\n\r\n"),
4539 MockRead(false, OK),
4540 };
4541
4542 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4543 data_writes, arraysize(data_writes));
4544 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4545
4546 session_deps.socket_factory.AddSocketDataProvider(&data);
4547 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4548
4549 TestCompletionCallback callback;
4550
4551 scoped_ptr<HttpTransaction> trans(
4552 new HttpNetworkTransaction(CreateSession(&session_deps)));
4553
4554 int rv = trans->Start(&request, &callback, BoundNetLog());
4555 EXPECT_EQ(ERR_IO_PENDING, rv);
4556
4557 rv = callback.WaitForResult();
4558 EXPECT_EQ(OK, rv);
4559 const HttpResponseInfo* response = trans->GetResponseInfo();
4560
4561 ASSERT_FALSE(response == NULL);
4562
4563 EXPECT_EQ(302, response->headers->response_code());
4564 std::string url;
4565 EXPECT_TRUE(response->headers->IsRedirect(&url));
4566 EXPECT_EQ("http://login.example.com/", url);
4567}
4568
4569// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4570TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4571 SessionDependencies session_deps(
4572 ProxyService::CreateFixed("https://proxy:70"));
4573
4574 HttpRequestInfo request;
4575 request.method = "GET";
4576 request.url = GURL("https://www.google.com/");
4577 request.load_flags = 0;
4578
4579 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4580 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4581 MockWrite data_writes[] = {
4582 CreateMockWrite(*conn.get(), 0, false),
4583 };
4584
4585 static const char* const kExtraHeaders[] = {
4586 "location",
4587 "http://login.example.com/",
4588 };
4589 scoped_ptr<spdy::SpdyFrame> resp(
4590 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4591 arraysize(kExtraHeaders)/2, 1));
4592 MockRead data_reads[] = {
4593 CreateMockRead(*resp.get(), 1, false),
4594 MockRead(true, 0, 2), // EOF
4595 };
4596
4597 scoped_refptr<DelayedSocketData> data(
4598 new DelayedSocketData(
4599 1, // wait for one write to finish before reading.
4600 data_reads, arraysize(data_reads),
4601 data_writes, arraysize(data_writes)));
4602 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4603 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4604 proxy_ssl.next_proto = "spdy/2";
4605 proxy_ssl.was_npn_negotiated = true;
4606
4607 session_deps.socket_factory.AddSocketDataProvider(data.get());
4608 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4609
4610 TestCompletionCallback callback;
4611
4612 scoped_ptr<HttpTransaction> trans(
4613 new HttpNetworkTransaction(CreateSession(&session_deps)));
4614
4615 int rv = trans->Start(&request, &callback, BoundNetLog());
4616 EXPECT_EQ(ERR_IO_PENDING, rv);
4617
4618 rv = callback.WaitForResult();
4619 EXPECT_EQ(OK, rv);
4620 const HttpResponseInfo* response = trans->GetResponseInfo();
4621
4622 ASSERT_FALSE(response == NULL);
4623
4624 EXPECT_EQ(302, response->headers->response_code());
4625 std::string url;
4626 EXPECT_TRUE(response->headers->IsRedirect(&url));
4627 EXPECT_EQ("http://login.example.com/", url);
4628}
4629
4630// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4631TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4632 SessionDependencies session_deps(
4633 ProxyService::CreateFixed("https://proxy:70"));
4634
4635 HttpRequestInfo request;
4636 request.method = "GET";
4637 request.url = GURL("https://www.google.com/");
4638 request.load_flags = 0;
4639
4640 MockWrite data_writes[] = {
4641 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4642 "Host: www.google.com\r\n"
4643 "Proxy-Connection: keep-alive\r\n\r\n"),
4644 };
4645
4646 MockRead data_reads[] = {
4647 MockRead("HTTP/1.1 404 Not Found\r\n"),
4648 MockRead("Content-Length: 23\r\n\r\n"),
4649 MockRead("The host does not exist"),
4650 MockRead(false, OK),
4651 };
4652
4653 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4654 data_writes, arraysize(data_writes));
4655 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4656
4657 session_deps.socket_factory.AddSocketDataProvider(&data);
4658 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4659
4660 TestCompletionCallback callback;
4661
4662 scoped_ptr<HttpTransaction> trans(
4663 new HttpNetworkTransaction(CreateSession(&session_deps)));
4664
4665 int rv = trans->Start(&request, &callback, BoundNetLog());
4666 EXPECT_EQ(ERR_IO_PENDING, rv);
4667
4668 rv = callback.WaitForResult();
4669 EXPECT_EQ(OK, rv);
4670 const HttpResponseInfo* response = trans->GetResponseInfo();
4671
4672 ASSERT_FALSE(response == NULL);
4673
4674 EXPECT_EQ(404, response->headers->response_code());
4675 EXPECT_EQ(23, response->headers->GetContentLength());
4676 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4677 EXPECT_FALSE(response->ssl_info.is_valid());
4678
4679 std::string response_data;
4680 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4681 EXPECT_EQ("The host does not exist", response_data);
4682}
4683
4684// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4685// request
4686TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4687 SessionDependencies session_deps(
4688 ProxyService::CreateFixed("https://proxy:70"));
4689
4690 HttpRequestInfo request;
4691 request.method = "GET";
4692 request.url = GURL("https://www.google.com/");
4693 request.load_flags = 0;
4694
4695 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4696 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4697 MockWrite data_writes[] = {
4698 CreateMockWrite(*conn.get(), 0, false),
4699 };
4700
4701 static const char* const kExtraHeaders[] = {
4702 "location",
4703 "http://login.example.com/",
4704 };
4705 scoped_ptr<spdy::SpdyFrame> resp(
4706 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4707 arraysize(kExtraHeaders)/2, 1));
4708 scoped_ptr<spdy::SpdyFrame> body(
4709 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4710 MockRead data_reads[] = {
4711 CreateMockRead(*resp.get(), 1, false),
4712 CreateMockRead(*body.get(), 2, false),
4713 MockRead(true, 0, 3), // EOF
4714 };
4715
4716 scoped_refptr<DelayedSocketData> data(
4717 new DelayedSocketData(
4718 1, // wait for one write to finish before reading.
4719 data_reads, arraysize(data_reads),
4720 data_writes, arraysize(data_writes)));
4721 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4722 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4723 proxy_ssl.next_proto = "spdy/2";
4724 proxy_ssl.was_npn_negotiated = true;
4725
4726 session_deps.socket_factory.AddSocketDataProvider(data.get());
4727 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4728
4729 TestCompletionCallback callback;
4730
4731 scoped_ptr<HttpTransaction> trans(
4732 new HttpNetworkTransaction(CreateSession(&session_deps)));
4733
4734 int rv = trans->Start(&request, &callback, BoundNetLog());
4735 EXPECT_EQ(ERR_IO_PENDING, rv);
4736
4737 rv = callback.WaitForResult();
4738 EXPECT_EQ(OK, rv);
4739 const HttpResponseInfo* response = trans->GetResponseInfo();
4740
4741 ASSERT_FALSE(response == NULL);
4742
4743 EXPECT_EQ(404, response->headers->response_code());
4744 EXPECT_FALSE(response->ssl_info.is_valid());
4745
4746 std::string response_data;
4747 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4748 EXPECT_EQ("The host does not exist", response_data);
4749}
4750
[email protected]2df19bb2010-08-25 20:13:464751// Test HTTPS connections to a site with a bad certificate, going through an
4752// HTTPS proxy
4753TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004754 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464755
4756 HttpRequestInfo request;
4757 request.method = "GET";
4758 request.url = GURL("https://www.google.com/");
4759 request.load_flags = 0;
4760
4761 // Attempt to fetch the URL from a server with a bad cert
4762 MockWrite bad_cert_writes[] = {
4763 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4764 "Host: www.google.com\r\n"
4765 "Proxy-Connection: keep-alive\r\n\r\n"),
4766 };
4767
4768 MockRead bad_cert_reads[] = {
4769 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4770 MockRead(false, OK)
4771 };
4772
4773 // Attempt to fetch the URL with a good cert
4774 MockWrite good_data_writes[] = {
4775 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4776 "Host: www.google.com\r\n"
4777 "Proxy-Connection: keep-alive\r\n\r\n"),
4778 MockWrite("GET / HTTP/1.1\r\n"
4779 "Host: www.google.com\r\n"
4780 "Connection: keep-alive\r\n\r\n"),
4781 };
4782
4783 MockRead good_cert_reads[] = {
4784 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4785 MockRead("HTTP/1.0 200 OK\r\n"),
4786 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4787 MockRead("Content-Length: 100\r\n\r\n"),
4788 MockRead(false, OK),
4789 };
4790
4791 StaticSocketDataProvider ssl_bad_certificate(
4792 bad_cert_reads, arraysize(bad_cert_reads),
4793 bad_cert_writes, arraysize(bad_cert_writes));
4794 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4795 good_data_writes, arraysize(good_data_writes));
4796 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4797 SSLSocketDataProvider ssl(true, OK);
4798
4799 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4800 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4801 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4802 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4803
4804 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4805 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4806 session_deps.socket_factory.AddSocketDataProvider(&data);
4807 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4808
4809 TestCompletionCallback callback;
4810
4811 scoped_ptr<HttpTransaction> trans(
4812 new HttpNetworkTransaction(CreateSession(&session_deps)));
4813
4814 int rv = trans->Start(&request, &callback, BoundNetLog());
4815 EXPECT_EQ(ERR_IO_PENDING, rv);
4816
4817 rv = callback.WaitForResult();
4818 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4819
4820 rv = trans->RestartIgnoringLastError(&callback);
4821 EXPECT_EQ(ERR_IO_PENDING, rv);
4822
4823 rv = callback.WaitForResult();
4824 EXPECT_EQ(OK, rv);
4825
4826 const HttpResponseInfo* response = trans->GetResponseInfo();
4827
4828 EXPECT_FALSE(response == NULL);
4829 EXPECT_EQ(100, response->headers->GetContentLength());
4830}
4831
[email protected]1c773ea12009-04-28 19:58:424832TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424833 HttpRequestInfo request;
4834 request.method = "GET";
4835 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434836 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4837 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424838
[email protected]cb9bf6ca2011-01-28 13:15:274839 SessionDependencies session_deps;
4840 scoped_ptr<HttpTransaction> trans(
4841 new HttpNetworkTransaction(CreateSession(&session_deps)));
4842
[email protected]1c773ea12009-04-28 19:58:424843 MockWrite data_writes[] = {
4844 MockWrite("GET / HTTP/1.1\r\n"
4845 "Host: www.google.com\r\n"
4846 "Connection: keep-alive\r\n"
4847 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4848 };
4849
4850 // Lastly, the server responds with the actual content.
4851 MockRead data_reads[] = {
4852 MockRead("HTTP/1.0 200 OK\r\n"),
4853 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4854 MockRead("Content-Length: 100\r\n\r\n"),
4855 MockRead(false, OK),
4856 };
4857
[email protected]31a2bfe2010-02-09 08:03:394858 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4859 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594860 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424861
4862 TestCompletionCallback callback;
4863
[email protected]5a1d7ca2010-04-28 20:12:274864 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424865 EXPECT_EQ(ERR_IO_PENDING, rv);
4866
4867 rv = callback.WaitForResult();
4868 EXPECT_EQ(OK, rv);
4869}
4870
[email protected]da81f132010-08-18 23:39:294871TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294872 HttpRequestInfo request;
4873 request.method = "GET";
4874 request.url = GURL("https://www.google.com/");
4875 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4876 "Chromium Ultra Awesome X Edition");
4877
[email protected]cb9bf6ca2011-01-28 13:15:274878 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4879 scoped_ptr<HttpTransaction> trans(
4880 new HttpNetworkTransaction(CreateSession(&session_deps)));
4881
[email protected]da81f132010-08-18 23:39:294882 MockWrite data_writes[] = {
4883 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4884 "Host: www.google.com\r\n"
4885 "Proxy-Connection: keep-alive\r\n"
4886 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4887 };
4888 MockRead data_reads[] = {
4889 // Return an error, so the transaction stops here (this test isn't
4890 // interested in the rest).
4891 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4892 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4893 MockRead("Proxy-Connection: close\r\n\r\n"),
4894 };
4895
4896 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4897 data_writes, arraysize(data_writes));
4898 session_deps.socket_factory.AddSocketDataProvider(&data);
4899
4900 TestCompletionCallback callback;
4901
4902 int rv = trans->Start(&request, &callback, BoundNetLog());
4903 EXPECT_EQ(ERR_IO_PENDING, rv);
4904
4905 rv = callback.WaitForResult();
4906 EXPECT_EQ(OK, rv);
4907}
4908
[email protected]1c773ea12009-04-28 19:58:424909TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424910 HttpRequestInfo request;
4911 request.method = "GET";
4912 request.url = GURL("http://www.google.com/");
4913 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164914 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4915 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:424916
[email protected]cb9bf6ca2011-01-28 13:15:274917 SessionDependencies session_deps;
4918 scoped_ptr<HttpTransaction> trans(
4919 new HttpNetworkTransaction(CreateSession(&session_deps)));
4920
[email protected]1c773ea12009-04-28 19:58:424921 MockWrite data_writes[] = {
4922 MockWrite("GET / HTTP/1.1\r\n"
4923 "Host: www.google.com\r\n"
4924 "Connection: keep-alive\r\n"
4925 "Referer: http://the.previous.site.com/\r\n\r\n"),
4926 };
4927
4928 // Lastly, the server responds with the actual content.
4929 MockRead data_reads[] = {
4930 MockRead("HTTP/1.0 200 OK\r\n"),
4931 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4932 MockRead("Content-Length: 100\r\n\r\n"),
4933 MockRead(false, OK),
4934 };
4935
[email protected]31a2bfe2010-02-09 08:03:394936 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4937 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594938 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424939
4940 TestCompletionCallback callback;
4941
[email protected]5a1d7ca2010-04-28 20:12:274942 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424943 EXPECT_EQ(ERR_IO_PENDING, rv);
4944
4945 rv = callback.WaitForResult();
4946 EXPECT_EQ(OK, rv);
4947}
4948
4949TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424950 HttpRequestInfo request;
4951 request.method = "POST";
4952 request.url = GURL("http://www.google.com/");
4953
[email protected]cb9bf6ca2011-01-28 13:15:274954 SessionDependencies session_deps;
4955 scoped_ptr<HttpTransaction> trans(
4956 new HttpNetworkTransaction(CreateSession(&session_deps)));
4957
[email protected]1c773ea12009-04-28 19:58:424958 MockWrite data_writes[] = {
4959 MockWrite("POST / HTTP/1.1\r\n"
4960 "Host: www.google.com\r\n"
4961 "Connection: keep-alive\r\n"
4962 "Content-Length: 0\r\n\r\n"),
4963 };
4964
4965 // Lastly, the server responds with the actual content.
4966 MockRead data_reads[] = {
4967 MockRead("HTTP/1.0 200 OK\r\n"),
4968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4969 MockRead("Content-Length: 100\r\n\r\n"),
4970 MockRead(false, OK),
4971 };
4972
[email protected]31a2bfe2010-02-09 08:03:394973 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4974 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594975 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424976
4977 TestCompletionCallback callback;
4978
[email protected]5a1d7ca2010-04-28 20:12:274979 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424980 EXPECT_EQ(ERR_IO_PENDING, rv);
4981
4982 rv = callback.WaitForResult();
4983 EXPECT_EQ(OK, rv);
4984}
4985
4986TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424987 HttpRequestInfo request;
4988 request.method = "PUT";
4989 request.url = GURL("http://www.google.com/");
4990
[email protected]cb9bf6ca2011-01-28 13:15:274991 SessionDependencies session_deps;
4992 scoped_ptr<HttpTransaction> trans(
4993 new HttpNetworkTransaction(CreateSession(&session_deps)));
4994
[email protected]1c773ea12009-04-28 19:58:424995 MockWrite data_writes[] = {
4996 MockWrite("PUT / HTTP/1.1\r\n"
4997 "Host: www.google.com\r\n"
4998 "Connection: keep-alive\r\n"
4999 "Content-Length: 0\r\n\r\n"),
5000 };
5001
5002 // Lastly, the server responds with the actual content.
5003 MockRead data_reads[] = {
5004 MockRead("HTTP/1.0 200 OK\r\n"),
5005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5006 MockRead("Content-Length: 100\r\n\r\n"),
5007 MockRead(false, OK),
5008 };
5009
[email protected]31a2bfe2010-02-09 08:03:395010 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5011 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595012 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425013
5014 TestCompletionCallback callback;
5015
[email protected]5a1d7ca2010-04-28 20:12:275016 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425017 EXPECT_EQ(ERR_IO_PENDING, rv);
5018
5019 rv = callback.WaitForResult();
5020 EXPECT_EQ(OK, rv);
5021}
5022
5023TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425024 HttpRequestInfo request;
5025 request.method = "HEAD";
5026 request.url = GURL("http://www.google.com/");
5027
[email protected]cb9bf6ca2011-01-28 13:15:275028 SessionDependencies session_deps;
5029 scoped_ptr<HttpTransaction> trans(
5030 new HttpNetworkTransaction(CreateSession(&session_deps)));
5031
[email protected]1c773ea12009-04-28 19:58:425032 MockWrite data_writes[] = {
5033 MockWrite("HEAD / HTTP/1.1\r\n"
5034 "Host: www.google.com\r\n"
5035 "Connection: keep-alive\r\n"
5036 "Content-Length: 0\r\n\r\n"),
5037 };
5038
5039 // Lastly, the server responds with the actual content.
5040 MockRead data_reads[] = {
5041 MockRead("HTTP/1.0 200 OK\r\n"),
5042 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5043 MockRead("Content-Length: 100\r\n\r\n"),
5044 MockRead(false, OK),
5045 };
5046
[email protected]31a2bfe2010-02-09 08:03:395047 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5048 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595049 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425050
5051 TestCompletionCallback callback;
5052
[email protected]5a1d7ca2010-04-28 20:12:275053 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425054 EXPECT_EQ(ERR_IO_PENDING, rv);
5055
5056 rv = callback.WaitForResult();
5057 EXPECT_EQ(OK, rv);
5058}
5059
5060TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425061 HttpRequestInfo request;
5062 request.method = "GET";
5063 request.url = GURL("http://www.google.com/");
5064 request.load_flags = LOAD_BYPASS_CACHE;
5065
[email protected]cb9bf6ca2011-01-28 13:15:275066 SessionDependencies session_deps;
5067 scoped_ptr<HttpTransaction> trans(
5068 new HttpNetworkTransaction(CreateSession(&session_deps)));
5069
[email protected]1c773ea12009-04-28 19:58:425070 MockWrite data_writes[] = {
5071 MockWrite("GET / HTTP/1.1\r\n"
5072 "Host: www.google.com\r\n"
5073 "Connection: keep-alive\r\n"
5074 "Pragma: no-cache\r\n"
5075 "Cache-Control: no-cache\r\n\r\n"),
5076 };
5077
5078 // Lastly, the server responds with the actual content.
5079 MockRead data_reads[] = {
5080 MockRead("HTTP/1.0 200 OK\r\n"),
5081 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5082 MockRead("Content-Length: 100\r\n\r\n"),
5083 MockRead(false, OK),
5084 };
5085
[email protected]31a2bfe2010-02-09 08:03:395086 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5087 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595088 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425089
5090 TestCompletionCallback callback;
5091
[email protected]5a1d7ca2010-04-28 20:12:275092 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425093 EXPECT_EQ(ERR_IO_PENDING, rv);
5094
5095 rv = callback.WaitForResult();
5096 EXPECT_EQ(OK, rv);
5097}
5098
5099TEST_F(HttpNetworkTransactionTest,
5100 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425101 HttpRequestInfo request;
5102 request.method = "GET";
5103 request.url = GURL("http://www.google.com/");
5104 request.load_flags = LOAD_VALIDATE_CACHE;
5105
[email protected]cb9bf6ca2011-01-28 13:15:275106 SessionDependencies session_deps;
5107 scoped_ptr<HttpTransaction> trans(
5108 new HttpNetworkTransaction(CreateSession(&session_deps)));
5109
[email protected]1c773ea12009-04-28 19:58:425110 MockWrite data_writes[] = {
5111 MockWrite("GET / HTTP/1.1\r\n"
5112 "Host: www.google.com\r\n"
5113 "Connection: keep-alive\r\n"
5114 "Cache-Control: max-age=0\r\n\r\n"),
5115 };
5116
5117 // Lastly, the server responds with the actual content.
5118 MockRead data_reads[] = {
5119 MockRead("HTTP/1.0 200 OK\r\n"),
5120 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5121 MockRead("Content-Length: 100\r\n\r\n"),
5122 MockRead(false, OK),
5123 };
5124
[email protected]31a2bfe2010-02-09 08:03:395125 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5126 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595127 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425128
5129 TestCompletionCallback callback;
5130
[email protected]5a1d7ca2010-04-28 20:12:275131 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425132 EXPECT_EQ(ERR_IO_PENDING, rv);
5133
5134 rv = callback.WaitForResult();
5135 EXPECT_EQ(OK, rv);
5136}
5137
5138TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425139 HttpRequestInfo request;
5140 request.method = "GET";
5141 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435142 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425143
[email protected]cb9bf6ca2011-01-28 13:15:275144 SessionDependencies session_deps;
5145 scoped_ptr<HttpTransaction> trans(
5146 new HttpNetworkTransaction(CreateSession(&session_deps)));
5147
[email protected]1c773ea12009-04-28 19:58:425148 MockWrite data_writes[] = {
5149 MockWrite("GET / HTTP/1.1\r\n"
5150 "Host: www.google.com\r\n"
5151 "Connection: keep-alive\r\n"
5152 "FooHeader: Bar\r\n\r\n"),
5153 };
5154
5155 // Lastly, the server responds with the actual content.
5156 MockRead data_reads[] = {
5157 MockRead("HTTP/1.0 200 OK\r\n"),
5158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5159 MockRead("Content-Length: 100\r\n\r\n"),
5160 MockRead(false, OK),
5161 };
5162
[email protected]31a2bfe2010-02-09 08:03:395163 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5164 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595165 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425166
5167 TestCompletionCallback callback;
5168
[email protected]5a1d7ca2010-04-28 20:12:275169 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425170 EXPECT_EQ(ERR_IO_PENDING, rv);
5171
5172 rv = callback.WaitForResult();
5173 EXPECT_EQ(OK, rv);
5174}
5175
[email protected]270c6412010-03-29 22:02:475176TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475177 HttpRequestInfo request;
5178 request.method = "GET";
5179 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435180 request.extra_headers.SetHeader("referer", "www.foo.com");
5181 request.extra_headers.SetHeader("hEllo", "Kitty");
5182 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475183
[email protected]cb9bf6ca2011-01-28 13:15:275184 SessionDependencies session_deps;
5185 scoped_ptr<HttpTransaction> trans(
5186 new HttpNetworkTransaction(CreateSession(&session_deps)));
5187
[email protected]270c6412010-03-29 22:02:475188 MockWrite data_writes[] = {
5189 MockWrite("GET / HTTP/1.1\r\n"
5190 "Host: www.google.com\r\n"
5191 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165192 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475193 "hEllo: Kitty\r\n"
5194 "FoO: bar\r\n\r\n"),
5195 };
5196
5197 // Lastly, the server responds with the actual content.
5198 MockRead data_reads[] = {
5199 MockRead("HTTP/1.0 200 OK\r\n"),
5200 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5201 MockRead("Content-Length: 100\r\n\r\n"),
5202 MockRead(false, OK),
5203 };
5204
5205 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5206 data_writes, arraysize(data_writes));
5207 session_deps.socket_factory.AddSocketDataProvider(&data);
5208
5209 TestCompletionCallback callback;
5210
[email protected]5a1d7ca2010-04-28 20:12:275211 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475212 EXPECT_EQ(ERR_IO_PENDING, rv);
5213
5214 rv = callback.WaitForResult();
5215 EXPECT_EQ(OK, rv);
5216}
5217
[email protected]3cd17242009-06-23 02:59:025218TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275219 HttpRequestInfo request;
5220 request.method = "GET";
5221 request.url = GURL("http://www.google.com/");
5222 request.load_flags = 0;
5223
[email protected]80d6524d2009-08-18 03:58:095224 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005225 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025226
5227 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435228 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025229
[email protected]3cd17242009-06-23 02:59:025230 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5231 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5232
5233 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355234 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025235 MockWrite("GET / HTTP/1.1\r\n"
5236 "Host: www.google.com\r\n"
5237 "Connection: keep-alive\r\n\r\n")
5238 };
5239
5240 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595241 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025242 MockRead("HTTP/1.0 200 OK\r\n"),
5243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5244 MockRead("Payload"),
5245 MockRead(false, OK)
5246 };
5247
[email protected]31a2bfe2010-02-09 08:03:395248 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5249 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595250 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025251
5252 TestCompletionCallback callback;
5253
[email protected]5a1d7ca2010-04-28 20:12:275254 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025255 EXPECT_EQ(ERR_IO_PENDING, rv);
5256
5257 rv = callback.WaitForResult();
5258 EXPECT_EQ(OK, rv);
5259
5260 const HttpResponseInfo* response = trans->GetResponseInfo();
5261 EXPECT_FALSE(response == NULL);
5262
5263 std::string response_text;
5264 rv = ReadTransaction(trans.get(), &response_text);
5265 EXPECT_EQ(OK, rv);
5266 EXPECT_EQ("Payload", response_text);
5267}
5268
5269TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275270 HttpRequestInfo request;
5271 request.method = "GET";
5272 request.url = GURL("https://www.google.com/");
5273 request.load_flags = 0;
5274
[email protected]80d6524d2009-08-18 03:58:095275 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005276 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025277
5278 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435279 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025280
[email protected]3cd17242009-06-23 02:59:025281 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5282 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5283
5284 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355285 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5286 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025287 MockWrite("GET / HTTP/1.1\r\n"
5288 "Host: www.google.com\r\n"
5289 "Connection: keep-alive\r\n\r\n")
5290 };
5291
5292 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355293 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5294 arraysize(read_buffer)),
5295 MockRead("HTTP/1.0 200 OK\r\n"),
5296 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5297 MockRead("Payload"),
5298 MockRead(false, OK)
5299 };
5300
[email protected]31a2bfe2010-02-09 08:03:395301 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5302 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595303 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355304
[email protected]5ecc992a42009-11-11 01:41:595305 SSLSocketDataProvider ssl(true, OK);
5306 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355307
5308 TestCompletionCallback callback;
5309
[email protected]5a1d7ca2010-04-28 20:12:275310 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355311 EXPECT_EQ(ERR_IO_PENDING, rv);
5312
5313 rv = callback.WaitForResult();
5314 EXPECT_EQ(OK, rv);
5315
5316 const HttpResponseInfo* response = trans->GetResponseInfo();
5317 EXPECT_FALSE(response == NULL);
5318
5319 std::string response_text;
5320 rv = ReadTransaction(trans.get(), &response_text);
5321 EXPECT_EQ(OK, rv);
5322 EXPECT_EQ("Payload", response_text);
5323}
5324
5325TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275326 HttpRequestInfo request;
5327 request.method = "GET";
5328 request.url = GURL("http://www.google.com/");
5329 request.load_flags = 0;
5330
[email protected]80d6524d2009-08-18 03:58:095331 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005332 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355333
5334 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435335 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355336
[email protected]e0c27be2009-07-15 13:09:355337 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5338 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375339 const char kSOCKS5OkRequest[] = {
5340 0x05, // Version
5341 0x01, // Command (CONNECT)
5342 0x00, // Reserved.
5343 0x03, // Address type (DOMAINNAME).
5344 0x0E, // Length of domain (14)
5345 // Domain string:
5346 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5347 0x00, 0x50, // 16-bit port (80)
5348 };
[email protected]e0c27be2009-07-15 13:09:355349 const char kSOCKS5OkResponse[] =
5350 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5351
5352 MockWrite data_writes[] = {
5353 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5354 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5355 MockWrite("GET / HTTP/1.1\r\n"
5356 "Host: www.google.com\r\n"
5357 "Connection: keep-alive\r\n\r\n")
5358 };
5359
5360 MockRead data_reads[] = {
5361 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5362 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5363 MockRead("HTTP/1.0 200 OK\r\n"),
5364 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5365 MockRead("Payload"),
5366 MockRead(false, OK)
5367 };
5368
[email protected]31a2bfe2010-02-09 08:03:395369 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5370 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595371 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355372
5373 TestCompletionCallback callback;
5374
[email protected]5a1d7ca2010-04-28 20:12:275375 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355376 EXPECT_EQ(ERR_IO_PENDING, rv);
5377
5378 rv = callback.WaitForResult();
5379 EXPECT_EQ(OK, rv);
5380
5381 const HttpResponseInfo* response = trans->GetResponseInfo();
5382 EXPECT_FALSE(response == NULL);
5383
5384 std::string response_text;
5385 rv = ReadTransaction(trans.get(), &response_text);
5386 EXPECT_EQ(OK, rv);
5387 EXPECT_EQ("Payload", response_text);
5388}
5389
5390TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275391 HttpRequestInfo request;
5392 request.method = "GET";
5393 request.url = GURL("https://www.google.com/");
5394 request.load_flags = 0;
5395
[email protected]80d6524d2009-08-18 03:58:095396 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005397 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355398
5399 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435400 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355401
[email protected]e0c27be2009-07-15 13:09:355402 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5403 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375404 const unsigned char kSOCKS5OkRequest[] = {
5405 0x05, // Version
5406 0x01, // Command (CONNECT)
5407 0x00, // Reserved.
5408 0x03, // Address type (DOMAINNAME).
5409 0x0E, // Length of domain (14)
5410 // Domain string:
5411 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5412 0x01, 0xBB, // 16-bit port (443)
5413 };
5414
[email protected]e0c27be2009-07-15 13:09:355415 const char kSOCKS5OkResponse[] =
5416 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5417
5418 MockWrite data_writes[] = {
5419 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5420 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5421 arraysize(kSOCKS5OkRequest)),
5422 MockWrite("GET / HTTP/1.1\r\n"
5423 "Host: www.google.com\r\n"
5424 "Connection: keep-alive\r\n\r\n")
5425 };
5426
5427 MockRead data_reads[] = {
5428 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5429 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025430 MockRead("HTTP/1.0 200 OK\r\n"),
5431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5432 MockRead("Payload"),
5433 MockRead(false, OK)
5434 };
5435
[email protected]31a2bfe2010-02-09 08:03:395436 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5437 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595438 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025439
[email protected]5ecc992a42009-11-11 01:41:595440 SSLSocketDataProvider ssl(true, OK);
5441 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025442
5443 TestCompletionCallback callback;
5444
[email protected]5a1d7ca2010-04-28 20:12:275445 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025446 EXPECT_EQ(ERR_IO_PENDING, rv);
5447
5448 rv = callback.WaitForResult();
5449 EXPECT_EQ(OK, rv);
5450
5451 const HttpResponseInfo* response = trans->GetResponseInfo();
5452 EXPECT_FALSE(response == NULL);
5453
5454 std::string response_text;
5455 rv = ReadTransaction(trans.get(), &response_text);
5456 EXPECT_EQ(OK, rv);
5457 EXPECT_EQ("Payload", response_text);
5458}
5459
[email protected]04e5be32009-06-26 20:00:315460// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065461
5462struct GroupNameTest {
5463 std::string proxy_server;
5464 std::string url;
5465 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185466 bool ssl;
[email protected]2d731a32010-04-29 01:04:065467};
5468
5469scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025470 SessionDependencies* session_deps) {
5471 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065472
5473 HttpAlternateProtocols* alternate_protocols =
5474 session->mutable_alternate_protocols();
5475 alternate_protocols->SetAlternateProtocolFor(
5476 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355477 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065478
5479 return session;
5480}
5481
5482int GroupNameTransactionHelper(
5483 const std::string& url,
5484 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065485 HttpRequestInfo request;
5486 request.method = "GET";
5487 request.url = GURL(url);
5488 request.load_flags = 0;
5489
[email protected]cb9bf6ca2011-01-28 13:15:275490 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5491
[email protected]2d731a32010-04-29 01:04:065492 TestCompletionCallback callback;
5493
5494 // We do not complete this request, the dtor will clean the transaction up.
5495 return trans->Start(&request, &callback, BoundNetLog());
5496}
5497
5498TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5499 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315500 {
[email protected]2d731a32010-04-29 01:04:065501 "", // unused
[email protected]04e5be32009-06-26 20:00:315502 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545503 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185504 false,
[email protected]2ff8b312010-04-26 22:20:545505 },
5506 {
[email protected]2d731a32010-04-29 01:04:065507 "", // unused
[email protected]2ff8b312010-04-26 22:20:545508 "http://[2001:1418:13:1::25]/direct",
5509 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185510 false,
[email protected]04e5be32009-06-26 20:00:315511 },
[email protected]04e5be32009-06-26 20:00:315512
5513 // SSL Tests
5514 {
[email protected]2d731a32010-04-29 01:04:065515 "", // unused
[email protected]04e5be32009-06-26 20:00:315516 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025517 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185518 true,
[email protected]04e5be32009-06-26 20:00:315519 },
5520 {
[email protected]2d731a32010-04-29 01:04:065521 "", // unused
5522 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025523 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185524 true,
[email protected]04e5be32009-06-26 20:00:315525 },
5526 {
[email protected]2d731a32010-04-29 01:04:065527 "", // unused
[email protected]2ff8b312010-04-26 22:20:545528 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025529 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185530 true,
[email protected]2ff8b312010-04-26 22:20:545531 },
[email protected]2d731a32010-04-29 01:04:065532 };
[email protected]2ff8b312010-04-26 22:20:545533
[email protected]8e6441ca2010-08-19 05:56:385534 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065535
5536 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025537 SessionDependencies session_deps(
5538 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065539 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025540 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065541
5542 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285543 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5544 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5545 peer.SetTransportSocketPool(transport_conn_pool);
[email protected]2431756e2010-09-29 20:26:135546 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345547 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185548 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065549
5550 EXPECT_EQ(ERR_IO_PENDING,
5551 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185552 if (tests[i].ssl)
5553 EXPECT_EQ(tests[i].expected_group_name,
5554 ssl_conn_pool->last_group_name_received());
5555 else
5556 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285557 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065558 }
5559
[email protected]8e6441ca2010-08-19 05:56:385560 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065561}
5562
5563TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5564 const GroupNameTest tests[] = {
5565 {
5566 "http_proxy",
5567 "http://www.google.com/http_proxy_normal",
5568 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185569 false,
[email protected]2d731a32010-04-29 01:04:065570 },
5571
5572 // SSL Tests
5573 {
5574 "http_proxy",
5575 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025576 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185577 true,
[email protected]2d731a32010-04-29 01:04:065578 },
[email protected]af3490e2010-10-16 21:02:295579
[email protected]9faeded92010-04-29 20:03:055580 {
5581 "http_proxy",
5582 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025583 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185584 true,
[email protected]9faeded92010-04-29 20:03:055585 },
[email protected]2d731a32010-04-29 01:04:065586 };
5587
[email protected]8e6441ca2010-08-19 05:56:385588 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065589
5590 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025591 SessionDependencies session_deps(
5592 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065593 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025594 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065595
5596 HttpNetworkSessionPeer peer(session);
5597
[email protected]e60e47a2010-07-14 03:37:185598 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135599 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345600 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185601 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135602 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345603 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185604 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065605
5606 EXPECT_EQ(ERR_IO_PENDING,
5607 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185608 if (tests[i].ssl)
5609 EXPECT_EQ(tests[i].expected_group_name,
5610 ssl_conn_pool->last_group_name_received());
5611 else
5612 EXPECT_EQ(tests[i].expected_group_name,
5613 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065614 }
5615
[email protected]8e6441ca2010-08-19 05:56:385616 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065617}
5618
5619TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5620 const GroupNameTest tests[] = {
5621 {
5622 "socks4://socks_proxy:1080",
5623 "http://www.google.com/socks4_direct",
5624 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185625 false,
[email protected]2d731a32010-04-29 01:04:065626 },
5627 {
5628 "socks5://socks_proxy:1080",
5629 "http://www.google.com/socks5_direct",
5630 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185631 false,
[email protected]2d731a32010-04-29 01:04:065632 },
5633
5634 // SSL Tests
5635 {
5636 "socks4://socks_proxy:1080",
5637 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025638 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185639 true,
[email protected]2d731a32010-04-29 01:04:065640 },
5641 {
5642 "socks5://socks_proxy:1080",
5643 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025644 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185645 true,
[email protected]2d731a32010-04-29 01:04:065646 },
[email protected]af3490e2010-10-16 21:02:295647
[email protected]9faeded92010-04-29 20:03:055648 {
5649 "socks4://socks_proxy:1080",
5650 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025651 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185652 true,
[email protected]9faeded92010-04-29 20:03:055653 },
[email protected]04e5be32009-06-26 20:00:315654 };
5655
[email protected]8e6441ca2010-08-19 05:56:385656 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545657
[email protected]04e5be32009-06-26 20:00:315658 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025659 SessionDependencies session_deps(
5660 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065661 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025662 SetupSessionForGroupNameTests(&session_deps));
5663
[email protected]2d731a32010-04-29 01:04:065664 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315665
[email protected]e60e47a2010-07-14 03:37:185666 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135667 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345668 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185669 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135670 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345671 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185672 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315673
[email protected]5695b8c2009-09-30 21:36:435674 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315675
[email protected]2d731a32010-04-29 01:04:065676 EXPECT_EQ(ERR_IO_PENDING,
5677 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185678 if (tests[i].ssl)
5679 EXPECT_EQ(tests[i].expected_group_name,
5680 ssl_conn_pool->last_group_name_received());
5681 else
5682 EXPECT_EQ(tests[i].expected_group_name,
5683 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315684 }
[email protected]2ff8b312010-04-26 22:20:545685
[email protected]8e6441ca2010-08-19 05:56:385686 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315687}
5688
[email protected]9172a982009-06-06 00:30:255689TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275690 HttpRequestInfo request;
5691 request.method = "GET";
5692 request.url = GURL("http://www.google.com/");
5693
[email protected]5c6a17e2009-06-10 00:54:545694 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005695 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325696
[email protected]69719062010-01-05 20:09:215697 // This simulates failure resolving all hostnames; that means we will fail
5698 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325699 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5700
[email protected]9172a982009-06-06 00:30:255701 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435702 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255703
[email protected]9172a982009-06-06 00:30:255704 TestCompletionCallback callback;
5705
[email protected]5a1d7ca2010-04-28 20:12:275706 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255707 EXPECT_EQ(ERR_IO_PENDING, rv);
5708
[email protected]9172a982009-06-06 00:30:255709 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015710 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255711}
5712
[email protected]f3e6c1e2009-06-15 20:52:125713// Host resolution observer used by
5714// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5715// resovle requests are issued with a referrer of |expected_referrer|.
5716class ResolutionReferrerObserver : public HostResolver::Observer {
5717 public:
5718 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5719 : expected_referrer_(expected_referrer),
5720 called_start_with_referrer_(false),
5721 called_finish_with_referrer_(false) {
5722 }
5723
5724 virtual void OnStartResolution(int id,
5725 const HostResolver::RequestInfo& info) {
5726 if (info.referrer() == expected_referrer_)
5727 called_start_with_referrer_ = true;
5728 }
5729
5730 virtual void OnFinishResolutionWithStatus(
5731 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5732 if (info.referrer() == expected_referrer_)
5733 called_finish_with_referrer_ = true;
5734 }
5735
[email protected]eb255d32009-06-17 02:11:035736 virtual void OnCancelResolution(int id,
5737 const HostResolver::RequestInfo& info ) {
5738 FAIL() << "Should not be cancelling any requests!";
5739 }
5740
[email protected]f3e6c1e2009-06-15 20:52:125741 bool did_complete_with_expected_referrer() const {
5742 return called_start_with_referrer_ && called_finish_with_referrer_;
5743 }
5744
5745 private:
5746 GURL expected_referrer_;
5747 bool called_start_with_referrer_;
5748 bool called_finish_with_referrer_;
5749
5750 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5751};
5752
5753// Make sure that when HostResolver::Resolve() is invoked, it passes through
5754// the "referrer". This is depended on by the DNS prefetch observer.
5755TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5756 GURL referrer = GURL("http://expected-referrer/");
5757 EXPECT_TRUE(referrer.is_valid());
5758 ResolutionReferrerObserver resolution_observer(referrer);
5759
[email protected]cb9bf6ca2011-01-28 13:15:275760 // Issue a request, containing an HTTP referrer.
5761 HttpRequestInfo request;
5762 request.method = "GET";
[email protected]cb9bf6ca2011-01-28 13:15:275763 request.url = GURL("http://www.google.com/");
[email protected]c10450102011-06-27 09:06:165764 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5765 referrer.spec());
[email protected]cb9bf6ca2011-01-28 13:15:275766
[email protected]f3e6c1e2009-06-15 20:52:125767 SessionDependencies session_deps;
5768 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435769 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125770
5771 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145772 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125773
5774 // Connect up a mock socket which will fail when reading.
5775 MockRead data_reads[] = {
5776 MockRead(false, ERR_FAILED),
5777 };
[email protected]31a2bfe2010-02-09 08:03:395778 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595779 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125780
[email protected]f3e6c1e2009-06-15 20:52:125781 // Run the request until it fails reading from the socket.
5782 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275783 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125784 EXPECT_EQ(ERR_IO_PENDING, rv);
5785 rv = callback.WaitForResult();
5786 EXPECT_EQ(ERR_FAILED, rv);
5787
5788 // Check that the host resolution observer saw |referrer|.
5789 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5790}
5791
[email protected]685af592010-05-11 19:31:245792// Base test to make sure that when the load flags for a request specify to
5793// bypass the cache, the DNS cache is not used.
5794void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275795 // Issue a request, asking to bypass the cache(s).
5796 HttpRequestInfo request;
5797 request.method = "GET";
5798 request.load_flags = load_flags;
5799 request.url = GURL("http://www.google.com/");
5800
[email protected]3b9cca42009-06-16 01:08:285801 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325802
[email protected]a2c2fb92009-07-18 07:31:045803 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545804 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325805
[email protected]3b9cca42009-06-16 01:08:285806 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435807 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285808
[email protected]6e78dfb2011-07-28 21:34:475809 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285810 AddressList addrlist;
[email protected]6e78dfb2011-07-28 21:34:475811 TestCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145812 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105813 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]6e78dfb2011-07-28 21:34:475814 &callback, NULL, BoundNetLog());
5815 EXPECT_EQ(ERR_IO_PENDING, rv);
5816 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285817 EXPECT_EQ(OK, rv);
5818
5819 // Verify that it was added to host cache, by doing a subsequent async lookup
5820 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465821 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105822 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]6e78dfb2011-07-28 21:34:475823 &callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325824 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285825
5826 // Inject a failure the next time that "www.google.com" is resolved. This way
5827 // we can tell if the next lookup hit the cache, or the "network".
5828 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325829 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285830
5831 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5832 // first read -- this won't be reached as the host resolution will fail first.
5833 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595835 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285836
[email protected]3b9cca42009-06-16 01:08:285837 // Run the request.
[email protected]5a1d7ca2010-04-28 20:12:275838 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285839 ASSERT_EQ(ERR_IO_PENDING, rv);
5840 rv = callback.WaitForResult();
5841
5842 // If we bypassed the cache, we would have gotten a failure while resolving
5843 // "www.google.com".
5844 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5845}
5846
[email protected]685af592010-05-11 19:31:245847// There are multiple load flags that should trigger the host cache bypass.
5848// Test each in isolation:
5849TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5850 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5851}
5852
5853TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5854 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5855}
5856
5857TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5858 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5859}
5860
[email protected]0877e3d2009-10-17 22:29:575861// Make sure we can handle an error when writing the request.
5862TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5863 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275864 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575865
5866 HttpRequestInfo request;
5867 request.method = "GET";
5868 request.url = GURL("http://www.foo.com/");
5869 request.load_flags = 0;
5870
5871 MockWrite write_failure[] = {
5872 MockWrite(true, ERR_CONNECTION_RESET),
5873 };
[email protected]31a2bfe2010-02-09 08:03:395874 StaticSocketDataProvider data(NULL, 0,
5875 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595876 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575877
5878 TestCompletionCallback callback;
5879
5880 scoped_ptr<HttpTransaction> trans(
5881 new HttpNetworkTransaction(CreateSession(&session_deps)));
5882
[email protected]5a1d7ca2010-04-28 20:12:275883 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575884 EXPECT_EQ(ERR_IO_PENDING, rv);
5885
5886 rv = callback.WaitForResult();
5887 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5888}
5889
5890// Check that a connection closed after the start of the headers finishes ok.
5891TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5892 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275893 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575894
5895 HttpRequestInfo request;
5896 request.method = "GET";
5897 request.url = GURL("http://www.foo.com/");
5898 request.load_flags = 0;
5899
5900 MockRead data_reads[] = {
5901 MockRead("HTTP/1."),
5902 MockRead(false, OK),
5903 };
5904
[email protected]31a2bfe2010-02-09 08:03:395905 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595906 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575907
5908 TestCompletionCallback callback;
5909
5910 scoped_ptr<HttpTransaction> trans(
5911 new HttpNetworkTransaction(CreateSession(&session_deps)));
5912
[email protected]5a1d7ca2010-04-28 20:12:275913 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575914 EXPECT_EQ(ERR_IO_PENDING, rv);
5915
5916 rv = callback.WaitForResult();
5917 EXPECT_EQ(OK, rv);
5918
5919 const HttpResponseInfo* response = trans->GetResponseInfo();
5920 EXPECT_TRUE(response != NULL);
5921
5922 EXPECT_TRUE(response->headers != NULL);
5923 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5924
5925 std::string response_data;
5926 rv = ReadTransaction(trans.get(), &response_data);
5927 EXPECT_EQ(OK, rv);
5928 EXPECT_EQ("", response_data);
5929}
5930
5931// Make sure that a dropped connection while draining the body for auth
5932// restart does the right thing.
5933TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5934 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275935 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575936
5937 HttpRequestInfo request;
5938 request.method = "GET";
5939 request.url = GURL("http://www.google.com/");
5940 request.load_flags = 0;
5941
5942 MockWrite data_writes1[] = {
5943 MockWrite("GET / HTTP/1.1\r\n"
5944 "Host: www.google.com\r\n"
5945 "Connection: keep-alive\r\n\r\n"),
5946 };
5947
5948 MockRead data_reads1[] = {
5949 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5950 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5951 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5952 MockRead("Content-Length: 14\r\n\r\n"),
5953 MockRead("Unauth"),
5954 MockRead(true, ERR_CONNECTION_RESET),
5955 };
5956
[email protected]31a2bfe2010-02-09 08:03:395957 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5958 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595959 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575960
5961 // After calling trans->RestartWithAuth(), this is the request we should
5962 // be issuing -- the final header line contains the credentials.
5963 MockWrite data_writes2[] = {
5964 MockWrite("GET / HTTP/1.1\r\n"
5965 "Host: www.google.com\r\n"
5966 "Connection: keep-alive\r\n"
5967 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5968 };
5969
5970 // Lastly, the server responds with the actual content.
5971 MockRead data_reads2[] = {
5972 MockRead("HTTP/1.1 200 OK\r\n"),
5973 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5974 MockRead("Content-Length: 100\r\n\r\n"),
5975 MockRead(false, OK),
5976 };
5977
[email protected]31a2bfe2010-02-09 08:03:395978 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5979 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595980 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575981
5982 TestCompletionCallback callback1;
5983
[email protected]0b0bf032010-09-21 18:08:505984 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5985
[email protected]5a1d7ca2010-04-28 20:12:275986 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575987 EXPECT_EQ(ERR_IO_PENDING, rv);
5988
5989 rv = callback1.WaitForResult();
5990 EXPECT_EQ(OK, rv);
5991
5992 const HttpResponseInfo* response = trans->GetResponseInfo();
5993 EXPECT_FALSE(response == NULL);
5994
5995 // The password prompt info should have been set in response->auth_challenge.
5996 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5997
5998 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5999 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6000 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6001
6002 TestCompletionCallback callback2;
6003
[email protected]13c8a092010-07-29 06:15:446004 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:576005 EXPECT_EQ(ERR_IO_PENDING, rv);
6006
6007 rv = callback2.WaitForResult();
6008 EXPECT_EQ(OK, rv);
6009
6010 response = trans->GetResponseInfo();
6011 EXPECT_FALSE(response == NULL);
6012 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6013 EXPECT_EQ(100, response->headers->GetContentLength());
6014}
6015
6016// Test HTTPS connections going through a proxy that sends extra data.
6017TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006018 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576019
6020 HttpRequestInfo request;
6021 request.method = "GET";
6022 request.url = GURL("https://www.google.com/");
6023 request.load_flags = 0;
6024
6025 MockRead proxy_reads[] = {
6026 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6027 MockRead(false, OK)
6028 };
6029
[email protected]31a2bfe2010-02-09 08:03:396030 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596031 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576032
[email protected]5ecc992a42009-11-11 01:41:596033 session_deps.socket_factory.AddSocketDataProvider(&data);
6034 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576035
6036 TestCompletionCallback callback;
6037
6038 session_deps.socket_factory.ResetNextMockIndexes();
6039
6040 scoped_ptr<HttpTransaction> trans(
6041 new HttpNetworkTransaction(CreateSession(&session_deps)));
6042
[email protected]5a1d7ca2010-04-28 20:12:276043 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576044 EXPECT_EQ(ERR_IO_PENDING, rv);
6045
6046 rv = callback.WaitForResult();
6047 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6048}
6049
[email protected]e22e1362009-11-23 21:31:126050TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466051 HttpRequestInfo request;
6052 request.method = "GET";
6053 request.url = GURL("http://www.google.com/");
6054 request.load_flags = 0;
6055
[email protected]cb9bf6ca2011-01-28 13:15:276056 SessionDependencies session_deps;
6057 scoped_ptr<HttpTransaction> trans(
6058 new HttpNetworkTransaction(CreateSession(&session_deps)));
6059
[email protected]e22e1362009-11-23 21:31:126060 MockRead data_reads[] = {
6061 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6062 MockRead(false, OK),
6063 };
[email protected]9492e4a2010-02-24 00:58:466064
6065 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6066 session_deps.socket_factory.AddSocketDataProvider(&data);
6067
6068 TestCompletionCallback callback;
6069
[email protected]5a1d7ca2010-04-28 20:12:276070 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466071 EXPECT_EQ(ERR_IO_PENDING, rv);
6072
6073 EXPECT_EQ(OK, callback.WaitForResult());
6074
6075 const HttpResponseInfo* response = trans->GetResponseInfo();
6076 EXPECT_TRUE(response != NULL);
6077
6078 EXPECT_TRUE(response->headers != NULL);
6079 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6080
6081 std::string response_data;
6082 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f0e2bf42011-07-22 21:21:446083 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126084}
6085
[email protected]95d88ffe2010-02-04 21:25:336086TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336087 HttpRequestInfo request;
6088 request.method = "POST";
6089 request.url = GURL("http://www.google.com/upload");
6090 request.upload_data = new UploadData;
6091 request.load_flags = 0;
6092
[email protected]cb9bf6ca2011-01-28 13:15:276093 SessionDependencies session_deps;
6094 scoped_ptr<HttpTransaction> trans(
6095 new HttpNetworkTransaction(CreateSession(&session_deps)));
6096
[email protected]95d88ffe2010-02-04 21:25:336097 FilePath temp_file_path;
6098 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6099 const uint64 kFakeSize = 100000; // file is actually blank
6100
6101 std::vector<UploadData::Element> elements;
6102 UploadData::Element element;
6103 element.SetToFilePath(temp_file_path);
6104 element.SetContentLength(kFakeSize);
6105 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536106 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336107 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6108
6109 MockRead data_reads[] = {
6110 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6111 MockRead("hello world"),
6112 MockRead(false, OK),
6113 };
[email protected]31a2bfe2010-02-09 08:03:396114 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336115 session_deps.socket_factory.AddSocketDataProvider(&data);
6116
6117 TestCompletionCallback callback;
6118
[email protected]5a1d7ca2010-04-28 20:12:276119 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336120 EXPECT_EQ(ERR_IO_PENDING, rv);
6121
6122 rv = callback.WaitForResult();
6123 EXPECT_EQ(OK, rv);
6124
6125 const HttpResponseInfo* response = trans->GetResponseInfo();
6126 EXPECT_TRUE(response != NULL);
6127
6128 EXPECT_TRUE(response->headers != NULL);
6129 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6130
6131 std::string response_data;
6132 rv = ReadTransaction(trans.get(), &response_data);
6133 EXPECT_EQ(OK, rv);
6134 EXPECT_EQ("hello world", response_data);
6135
6136 file_util::Delete(temp_file_path, false);
6137}
6138
[email protected]6624b4622010-03-29 19:58:366139TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276140 HttpRequestInfo request;
6141 request.method = "POST";
6142 request.url = GURL("http://www.google.com/upload");
6143 request.upload_data = new UploadData;
6144 request.load_flags = 0;
6145
[email protected]6624b4622010-03-29 19:58:366146 // If we try to upload an unreadable file, the network stack should report
6147 // the file size as zero and upload zero bytes for that file.
6148 SessionDependencies session_deps;
6149 scoped_ptr<HttpTransaction> trans(
6150 new HttpNetworkTransaction(CreateSession(&session_deps)));
6151
6152 FilePath temp_file;
6153 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6154 std::string temp_file_content("Unreadable file.");
6155 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6156 temp_file_content.length()));
6157 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6158
[email protected]6624b4622010-03-29 19:58:366159 std::vector<UploadData::Element> elements;
6160 UploadData::Element element;
6161 element.SetToFilePath(temp_file);
6162 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536163 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366164
6165 MockRead data_reads[] = {
6166 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6167 MockRead(false, OK),
6168 };
6169 MockWrite data_writes[] = {
6170 MockWrite("POST /upload HTTP/1.1\r\n"
6171 "Host: www.google.com\r\n"
6172 "Connection: keep-alive\r\n"
6173 "Content-Length: 0\r\n\r\n"),
6174 MockWrite(false, OK),
6175 };
6176 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6177 arraysize(data_writes));
6178 session_deps.socket_factory.AddSocketDataProvider(&data);
6179
6180 TestCompletionCallback callback;
6181
[email protected]5a1d7ca2010-04-28 20:12:276182 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366183 EXPECT_EQ(ERR_IO_PENDING, rv);
6184
6185 rv = callback.WaitForResult();
6186 EXPECT_EQ(OK, rv);
6187
6188 const HttpResponseInfo* response = trans->GetResponseInfo();
6189 EXPECT_TRUE(response != NULL);
6190 EXPECT_TRUE(response->headers != NULL);
6191 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6192
6193 file_util::Delete(temp_file, false);
6194}
6195
6196TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276197 HttpRequestInfo request;
6198 request.method = "POST";
6199 request.url = GURL("http://www.google.com/upload");
6200 request.upload_data = new UploadData;
6201 request.load_flags = 0;
6202
[email protected]6624b4622010-03-29 19:58:366203 SessionDependencies session_deps;
6204 scoped_ptr<HttpTransaction> trans(
6205 new HttpNetworkTransaction(CreateSession(&session_deps)));
6206
6207 FilePath temp_file;
6208 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6209 std::string temp_file_contents("Unreadable file.");
6210 std::string unreadable_contents(temp_file_contents.length(), '\0');
6211 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6212 temp_file_contents.length()));
6213
[email protected]6624b4622010-03-29 19:58:366214 std::vector<UploadData::Element> elements;
6215 UploadData::Element element;
6216 element.SetToFilePath(temp_file);
6217 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536218 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366219
6220 MockRead data_reads[] = {
6221 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6222 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6223 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6224
6225 MockRead("HTTP/1.1 200 OK\r\n"),
6226 MockRead("Content-Length: 0\r\n\r\n"),
6227 MockRead(false, OK),
6228 };
6229 MockWrite data_writes[] = {
6230 MockWrite("POST /upload HTTP/1.1\r\n"
6231 "Host: www.google.com\r\n"
6232 "Connection: keep-alive\r\n"
6233 "Content-Length: 16\r\n\r\n"),
6234 MockWrite(false, temp_file_contents.c_str()),
6235
6236 MockWrite("POST /upload HTTP/1.1\r\n"
6237 "Host: www.google.com\r\n"
6238 "Connection: keep-alive\r\n"
6239 "Content-Length: 16\r\n"
6240 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6241 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6242 MockWrite(false, OK),
6243 };
6244 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6245 arraysize(data_writes));
6246 session_deps.socket_factory.AddSocketDataProvider(&data);
6247
6248 TestCompletionCallback callback1;
6249
[email protected]5a1d7ca2010-04-28 20:12:276250 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366251 EXPECT_EQ(ERR_IO_PENDING, rv);
6252
6253 rv = callback1.WaitForResult();
6254 EXPECT_EQ(OK, rv);
6255
6256 const HttpResponseInfo* response = trans->GetResponseInfo();
6257 EXPECT_TRUE(response != NULL);
6258 EXPECT_TRUE(response->headers != NULL);
6259 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6260
6261 // The password prompt info should have been set in response->auth_challenge.
6262 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6263 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6264 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6265 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6266
6267 // Now make the file unreadable and try again.
6268 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6269
6270 TestCompletionCallback callback2;
6271
[email protected]13c8a092010-07-29 06:15:446272 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366273 EXPECT_EQ(ERR_IO_PENDING, rv);
6274
6275 rv = callback2.WaitForResult();
6276 EXPECT_EQ(OK, rv);
6277
6278 response = trans->GetResponseInfo();
6279 EXPECT_TRUE(response != NULL);
6280 EXPECT_TRUE(response->headers != NULL);
6281 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6283
6284 file_util::Delete(temp_file, false);
6285}
6286
[email protected]aeefc9e82010-02-19 16:18:276287// Tests that changes to Auth realms are treated like auth rejections.
6288TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6289 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276290
6291 HttpRequestInfo request;
6292 request.method = "GET";
6293 request.url = GURL("http://www.google.com/");
6294 request.load_flags = 0;
6295
6296 // First transaction will request a resource and receive a Basic challenge
6297 // with realm="first_realm".
6298 MockWrite data_writes1[] = {
6299 MockWrite("GET / HTTP/1.1\r\n"
6300 "Host: www.google.com\r\n"
6301 "Connection: keep-alive\r\n"
6302 "\r\n"),
6303 };
6304 MockRead data_reads1[] = {
6305 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6306 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6307 "\r\n"),
6308 };
6309
6310 // After calling trans->RestartWithAuth(), provide an Authentication header
6311 // for first_realm. The server will reject and provide a challenge with
6312 // second_realm.
6313 MockWrite data_writes2[] = {
6314 MockWrite("GET / HTTP/1.1\r\n"
6315 "Host: www.google.com\r\n"
6316 "Connection: keep-alive\r\n"
6317 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6318 "\r\n"),
6319 };
6320 MockRead data_reads2[] = {
6321 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6322 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6323 "\r\n"),
6324 };
6325
6326 // This again fails, and goes back to first_realm. Make sure that the
6327 // entry is removed from cache.
6328 MockWrite data_writes3[] = {
6329 MockWrite("GET / HTTP/1.1\r\n"
6330 "Host: www.google.com\r\n"
6331 "Connection: keep-alive\r\n"
6332 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6333 "\r\n"),
6334 };
6335 MockRead data_reads3[] = {
6336 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6337 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6338 "\r\n"),
6339 };
6340
6341 // Try one last time (with the correct password) and get the resource.
6342 MockWrite data_writes4[] = {
6343 MockWrite("GET / HTTP/1.1\r\n"
6344 "Host: www.google.com\r\n"
6345 "Connection: keep-alive\r\n"
6346 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6347 "\r\n"),
6348 };
6349 MockRead data_reads4[] = {
6350 MockRead("HTTP/1.1 200 OK\r\n"
6351 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506352 "Content-Length: 5\r\n"
6353 "\r\n"
6354 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276355 };
6356
6357 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6358 data_writes1, arraysize(data_writes1));
6359 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6360 data_writes2, arraysize(data_writes2));
6361 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6362 data_writes3, arraysize(data_writes3));
6363 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6364 data_writes4, arraysize(data_writes4));
6365 session_deps.socket_factory.AddSocketDataProvider(&data1);
6366 session_deps.socket_factory.AddSocketDataProvider(&data2);
6367 session_deps.socket_factory.AddSocketDataProvider(&data3);
6368 session_deps.socket_factory.AddSocketDataProvider(&data4);
6369
6370 TestCompletionCallback callback1;
6371
[email protected]0b0bf032010-09-21 18:08:506372 scoped_ptr<HttpTransaction> trans(
6373 new HttpNetworkTransaction(CreateSession(&session_deps)));
6374
[email protected]aeefc9e82010-02-19 16:18:276375 // Issue the first request with Authorize headers. There should be a
6376 // password prompt for first_realm waiting to be filled in after the
6377 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276378 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276379 EXPECT_EQ(ERR_IO_PENDING, rv);
6380 rv = callback1.WaitForResult();
6381 EXPECT_EQ(OK, rv);
6382 const HttpResponseInfo* response = trans->GetResponseInfo();
6383 ASSERT_FALSE(response == NULL);
6384 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6385 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6386 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6387 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6388
6389 // Issue the second request with an incorrect password. There should be a
6390 // password prompt for second_realm waiting to be filled in after the
6391 // transaction completes.
6392 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446393 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276394 EXPECT_EQ(ERR_IO_PENDING, rv);
6395 rv = callback2.WaitForResult();
6396 EXPECT_EQ(OK, rv);
6397 response = trans->GetResponseInfo();
6398 ASSERT_FALSE(response == NULL);
6399 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6400 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6401 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6402 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6403
6404 // Issue the third request with another incorrect password. There should be
6405 // a password prompt for first_realm waiting to be filled in. If the password
6406 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6407 // first_realm was not correctly removed.
6408 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446409 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276410 EXPECT_EQ(ERR_IO_PENDING, rv);
6411 rv = callback3.WaitForResult();
6412 EXPECT_EQ(OK, rv);
6413 response = trans->GetResponseInfo();
6414 ASSERT_FALSE(response == NULL);
6415 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6416 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6417 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6418 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6419
6420 // Issue the fourth request with the correct password and username.
6421 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446422 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276423 EXPECT_EQ(ERR_IO_PENDING, rv);
6424 rv = callback4.WaitForResult();
6425 EXPECT_EQ(OK, rv);
6426 response = trans->GetResponseInfo();
6427 ASSERT_FALSE(response == NULL);
6428 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6429}
6430
[email protected]564b4912010-03-09 16:30:426431TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386432 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6433 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426434
[email protected]564b4912010-03-09 16:30:426435 SessionDependencies session_deps;
6436
6437 MockRead data_reads[] = {
6438 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356439 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426440 MockRead("hello world"),
6441 MockRead(false, OK),
6442 };
6443
6444 HttpRequestInfo request;
6445 request.method = "GET";
6446 request.url = GURL("http://www.google.com/");
6447 request.load_flags = 0;
6448
6449 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6450
6451 session_deps.socket_factory.AddSocketDataProvider(&data);
6452
6453 TestCompletionCallback callback;
6454
6455 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6457
[email protected]5a1d7ca2010-04-28 20:12:276458 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426459 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536460
[email protected]2fbaecf22010-07-22 22:20:356461 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426462 const HttpAlternateProtocols& alternate_protocols =
6463 session->alternate_protocols();
6464 EXPECT_FALSE(
6465 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6466
6467 EXPECT_EQ(OK, callback.WaitForResult());
6468
6469 const HttpResponseInfo* response = trans->GetResponseInfo();
6470 ASSERT_TRUE(response != NULL);
6471 ASSERT_TRUE(response->headers != NULL);
6472 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536473 EXPECT_FALSE(response->was_fetched_via_spdy);
6474 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426475
6476 std::string response_data;
6477 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6478 EXPECT_EQ("hello world", response_data);
6479
6480 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6481 const HttpAlternateProtocols::PortProtocolPair alternate =
6482 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6483 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6484 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356485 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426486 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426487
[email protected]8e6441ca2010-08-19 05:56:386488 HttpStreamFactory::set_use_alternate_protocols(false);
6489 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426490}
6491
[email protected]8b95ed62011-03-18 18:12:036492TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386493 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426494 SessionDependencies session_deps;
6495
6496 HttpRequestInfo request;
6497 request.method = "GET";
6498 request.url = GURL("http://www.google.com/");
6499 request.load_flags = 0;
6500
6501 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6502 StaticSocketDataProvider first_data;
6503 first_data.set_connect_data(mock_connect);
6504 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6505
6506 MockRead data_reads[] = {
6507 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6508 MockRead("hello world"),
6509 MockRead(true, OK),
6510 };
6511 StaticSocketDataProvider second_data(
6512 data_reads, arraysize(data_reads), NULL, 0);
6513 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6514
[email protected]564b4912010-03-09 16:30:426515 TestCompletionCallback callback;
6516
6517 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6518
[email protected]2fbaecf22010-07-22 22:20:356519 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426520 HttpAlternateProtocols* alternate_protocols =
6521 session->mutable_alternate_protocols();
6522 alternate_protocols->SetAlternateProtocolFor(
6523 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356524 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426525
6526 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6527
[email protected]5a1d7ca2010-04-28 20:12:276528 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426529 EXPECT_EQ(ERR_IO_PENDING, rv);
6530 EXPECT_EQ(OK, callback.WaitForResult());
6531
6532 const HttpResponseInfo* response = trans->GetResponseInfo();
6533 ASSERT_TRUE(response != NULL);
6534 ASSERT_TRUE(response->headers != NULL);
6535 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6536
6537 std::string response_data;
6538 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6539 EXPECT_EQ("hello world", response_data);
6540
6541 ASSERT_TRUE(
6542 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6543 const HttpAlternateProtocols::PortProtocolPair alternate =
6544 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6545 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386546 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426547}
6548
[email protected]2ff8b312010-04-26 22:20:546549TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386550 HttpStreamFactory::set_use_alternate_protocols(true);
6551 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546552 SessionDependencies session_deps;
6553
6554 HttpRequestInfo request;
6555 request.method = "GET";
6556 request.url = GURL("http://www.google.com/");
6557 request.load_flags = 0;
6558
6559 MockRead data_reads[] = {
6560 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356561 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546562 MockRead("hello world"),
6563 MockRead(true, OK),
6564 };
6565
6566 StaticSocketDataProvider first_transaction(
6567 data_reads, arraysize(data_reads), NULL, 0);
6568 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6569
6570 SSLSocketDataProvider ssl(true, OK);
6571 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356572 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536573 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546574 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6575
[email protected]2bd93022010-07-17 00:58:446576 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136577 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546578
[email protected]2bd93022010-07-17 00:58:446579 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6580 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546581 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136582 CreateMockRead(*resp),
6583 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546584 MockRead(true, 0, 0),
6585 };
6586
6587 scoped_refptr<DelayedSocketData> spdy_data(
6588 new DelayedSocketData(
6589 1, // wait for one write to finish before reading.
6590 spdy_reads, arraysize(spdy_reads),
6591 spdy_writes, arraysize(spdy_writes)));
6592 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6593
[email protected]2d6728692011-03-12 01:39:556594 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6595 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6596 NULL, 0, NULL, 0);
6597 hanging_non_alternate_protocol_socket.set_connect_data(
6598 never_finishing_connect);
6599 session_deps.socket_factory.AddSocketDataProvider(
6600 &hanging_non_alternate_protocol_socket);
6601
[email protected]2ff8b312010-04-26 22:20:546602 TestCompletionCallback callback;
6603
6604 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6605 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6606
[email protected]5a1d7ca2010-04-28 20:12:276607 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546608 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);
6619
6620 trans.reset(new HttpNetworkTransaction(session));
6621
[email protected]5a1d7ca2010-04-28 20:12:276622 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546623 EXPECT_EQ(ERR_IO_PENDING, rv);
6624 EXPECT_EQ(OK, callback.WaitForResult());
6625
6626 response = trans->GetResponseInfo();
6627 ASSERT_TRUE(response != NULL);
6628 ASSERT_TRUE(response->headers != NULL);
6629 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536630 EXPECT_TRUE(response->was_fetched_via_spdy);
6631 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546632
6633 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6634 EXPECT_EQ("hello!", response_data);
6635
[email protected]8e6441ca2010-08-19 05:56:386636 HttpStreamFactory::set_next_protos("");
6637 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546638}
6639
[email protected]2d6728692011-03-12 01:39:556640TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6641 HttpStreamFactory::set_use_alternate_protocols(true);
6642 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6643 SessionDependencies session_deps;
6644
6645 HttpRequestInfo request;
6646 request.method = "GET";
6647 request.url = GURL("http://www.google.com/");
6648 request.load_flags = 0;
6649
6650 MockRead data_reads[] = {
6651 MockRead("HTTP/1.1 200 OK\r\n"),
6652 MockRead(kAlternateProtocolHttpHeader),
6653 MockRead("hello world"),
6654 MockRead(true, OK),
6655 };
6656
6657 StaticSocketDataProvider first_transaction(
6658 data_reads, arraysize(data_reads), NULL, 0);
6659 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6660 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6661
6662 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6663 StaticSocketDataProvider hanging_socket(
6664 NULL, 0, NULL, 0);
6665 hanging_socket.set_connect_data(never_finishing_connect);
6666 // Socket 2 and 3 are the hanging Alternate-Protocol and
6667 // non-Alternate-Protocol jobs from the 2nd transaction.
6668 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6669 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6670
6671 SSLSocketDataProvider ssl(true, OK);
6672 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6673 ssl.next_proto = "spdy/2";
6674 ssl.was_npn_negotiated = true;
6675 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6676
6677 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6678 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6679 MockWrite spdy_writes[] = {
6680 CreateMockWrite(*req1),
6681 CreateMockWrite(*req2),
6682 };
6683 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6684 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6685 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6686 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6687 MockRead spdy_reads[] = {
6688 CreateMockRead(*resp1),
6689 CreateMockRead(*data1),
6690 CreateMockRead(*resp2),
6691 CreateMockRead(*data2),
6692 MockRead(true, 0, 0),
6693 };
6694
6695 scoped_refptr<DelayedSocketData> spdy_data(
6696 new DelayedSocketData(
6697 2, // wait for writes to finish before reading.
6698 spdy_reads, arraysize(spdy_reads),
6699 spdy_writes, arraysize(spdy_writes)));
6700 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6701 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6702
6703 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6704 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6705
6706 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6707 TestCompletionCallback callback1;
6708 HttpNetworkTransaction trans1(session);
6709
6710 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6711 EXPECT_EQ(ERR_IO_PENDING, rv);
6712 EXPECT_EQ(OK, callback1.WaitForResult());
6713
6714 const HttpResponseInfo* response = trans1.GetResponseInfo();
6715 ASSERT_TRUE(response != NULL);
6716 ASSERT_TRUE(response->headers != NULL);
6717 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6718
6719 std::string response_data;
6720 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6721 EXPECT_EQ("hello world", response_data);
6722
6723 TestCompletionCallback callback2;
6724 HttpNetworkTransaction trans2(session);
6725 rv = trans2.Start(&request, &callback2, BoundNetLog());
6726 EXPECT_EQ(ERR_IO_PENDING, rv);
6727
6728 TestCompletionCallback callback3;
6729 HttpNetworkTransaction trans3(session);
6730 rv = trans3.Start(&request, &callback3, BoundNetLog());
6731 EXPECT_EQ(ERR_IO_PENDING, rv);
6732
6733 EXPECT_EQ(OK, callback2.WaitForResult());
6734 EXPECT_EQ(OK, callback3.WaitForResult());
6735
6736 response = trans2.GetResponseInfo();
6737 ASSERT_TRUE(response != NULL);
6738 ASSERT_TRUE(response->headers != NULL);
6739 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6740 EXPECT_TRUE(response->was_fetched_via_spdy);
6741 EXPECT_TRUE(response->was_npn_negotiated);
6742 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6743 EXPECT_EQ("hello!", response_data);
6744
6745 response = trans3.GetResponseInfo();
6746 ASSERT_TRUE(response != NULL);
6747 ASSERT_TRUE(response->headers != NULL);
6748 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6749 EXPECT_TRUE(response->was_fetched_via_spdy);
6750 EXPECT_TRUE(response->was_npn_negotiated);
6751 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6752 EXPECT_EQ("hello!", response_data);
6753
6754 HttpStreamFactory::set_next_protos("");
6755 HttpStreamFactory::set_use_alternate_protocols(false);
6756}
6757
6758TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6759 HttpStreamFactory::set_use_alternate_protocols(true);
6760 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6761 SessionDependencies session_deps;
6762
6763 HttpRequestInfo request;
6764 request.method = "GET";
6765 request.url = GURL("http://www.google.com/");
6766 request.load_flags = 0;
6767
6768 MockRead data_reads[] = {
6769 MockRead("HTTP/1.1 200 OK\r\n"),
6770 MockRead(kAlternateProtocolHttpHeader),
6771 MockRead("hello world"),
6772 MockRead(true, OK),
6773 };
6774
6775 StaticSocketDataProvider first_transaction(
6776 data_reads, arraysize(data_reads), NULL, 0);
6777 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6778
6779 SSLSocketDataProvider ssl(true, OK);
6780 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6781 ssl.next_proto = "spdy/2";
6782 ssl.was_npn_negotiated = true;
6783 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6784
6785 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6786 StaticSocketDataProvider hanging_alternate_protocol_socket(
6787 NULL, 0, NULL, 0);
6788 hanging_alternate_protocol_socket.set_connect_data(
6789 never_finishing_connect);
6790 session_deps.socket_factory.AddSocketDataProvider(
6791 &hanging_alternate_protocol_socket);
6792
6793 // 2nd request is just a copy of the first one, over HTTP again.
6794 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6795
6796 TestCompletionCallback callback;
6797
6798 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6799 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6800
6801 int rv = trans->Start(&request, &callback, BoundNetLog());
6802 EXPECT_EQ(ERR_IO_PENDING, rv);
6803 EXPECT_EQ(OK, callback.WaitForResult());
6804
6805 const HttpResponseInfo* response = trans->GetResponseInfo();
6806 ASSERT_TRUE(response != NULL);
6807 ASSERT_TRUE(response->headers != NULL);
6808 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6809
6810 std::string response_data;
6811 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6812 EXPECT_EQ("hello world", response_data);
6813
6814 trans.reset(new HttpNetworkTransaction(session));
6815
6816 rv = trans->Start(&request, &callback, BoundNetLog());
6817 EXPECT_EQ(ERR_IO_PENDING, rv);
6818 EXPECT_EQ(OK, callback.WaitForResult());
6819
6820 response = trans->GetResponseInfo();
6821 ASSERT_TRUE(response != NULL);
6822 ASSERT_TRUE(response->headers != NULL);
6823 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6824 EXPECT_FALSE(response->was_fetched_via_spdy);
6825 EXPECT_FALSE(response->was_npn_negotiated);
6826
6827 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6828 EXPECT_EQ("hello world", response_data);
6829
6830 HttpStreamFactory::set_next_protos("");
6831 HttpStreamFactory::set_use_alternate_protocols(false);
6832}
6833
[email protected]631f1322010-04-30 17:59:116834class CapturingProxyResolver : public ProxyResolver {
6835 public:
6836 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6837 virtual ~CapturingProxyResolver() {}
6838
6839 virtual int GetProxyForURL(const GURL& url,
6840 ProxyInfo* results,
6841 CompletionCallback* callback,
6842 RequestHandle* request,
6843 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406844 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6845 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426846 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116847 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426848 return OK;
[email protected]631f1322010-04-30 17:59:116849 }
6850
6851 virtual void CancelRequest(RequestHandle request) {
6852 NOTREACHED();
6853 }
6854
[email protected]1e605472010-12-16 21:41:406855 virtual void CancelSetPacScript() {
6856 NOTREACHED();
6857 }
6858
[email protected]24476402010-07-20 20:55:176859 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116860 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426861 return OK;
[email protected]631f1322010-04-30 17:59:116862 }
6863
[email protected]24476402010-07-20 20:55:176864 const std::vector<GURL>& resolved() const { return resolved_; }
6865
6866 private:
[email protected]631f1322010-04-30 17:59:116867 std::vector<GURL> resolved_;
6868
6869 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6870};
6871
[email protected]631f1322010-04-30 17:59:116872TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386873 HttpStreamFactory::set_use_alternate_protocols(true);
6874 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116875
6876 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426877 proxy_config.set_auto_detect(true);
6878 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116879
[email protected]631f1322010-04-30 17:59:116880 CapturingProxyResolver* capturing_proxy_resolver =
6881 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386882 SessionDependencies session_deps(new ProxyService(
6883 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6884 NULL));
[email protected]631f1322010-04-30 17:59:116885
6886 HttpRequestInfo request;
6887 request.method = "GET";
6888 request.url = GURL("http://www.google.com/");
6889 request.load_flags = 0;
6890
6891 MockRead data_reads[] = {
6892 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356893 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116894 MockRead("hello world"),
6895 MockRead(true, OK),
6896 };
6897
6898 StaticSocketDataProvider first_transaction(
6899 data_reads, arraysize(data_reads), NULL, 0);
6900 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6901
6902 SSLSocketDataProvider ssl(true, OK);
6903 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356904 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536905 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116906 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6907
[email protected]2bd93022010-07-17 00:58:446908 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116909 MockWrite spdy_writes[] = {
6910 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6911 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426912 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136913 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116914 };
6915
[email protected]d911f1b2010-05-05 22:39:426916 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6917
[email protected]2bd93022010-07-17 00:58:446918 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6919 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116920 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426921 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136922 CreateMockRead(*resp.get(), 4), // 2, 4
6923 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426924 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116925 };
6926
[email protected]d911f1b2010-05-05 22:39:426927 scoped_refptr<OrderedSocketData> spdy_data(
6928 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116929 spdy_reads, arraysize(spdy_reads),
6930 spdy_writes, arraysize(spdy_writes)));
6931 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6932
[email protected]2d6728692011-03-12 01:39:556933 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6934 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6935 NULL, 0, NULL, 0);
6936 hanging_non_alternate_protocol_socket.set_connect_data(
6937 never_finishing_connect);
6938 session_deps.socket_factory.AddSocketDataProvider(
6939 &hanging_non_alternate_protocol_socket);
6940
[email protected]631f1322010-04-30 17:59:116941 TestCompletionCallback callback;
6942
6943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6944 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6945
6946 int rv = trans->Start(&request, &callback, BoundNetLog());
6947 EXPECT_EQ(ERR_IO_PENDING, rv);
6948 EXPECT_EQ(OK, callback.WaitForResult());
6949
6950 const HttpResponseInfo* response = trans->GetResponseInfo();
6951 ASSERT_TRUE(response != NULL);
6952 ASSERT_TRUE(response->headers != NULL);
6953 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536954 EXPECT_FALSE(response->was_fetched_via_spdy);
6955 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116956
6957 std::string response_data;
6958 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6959 EXPECT_EQ("hello world", response_data);
6960
6961 trans.reset(new HttpNetworkTransaction(session));
6962
6963 rv = trans->Start(&request, &callback, BoundNetLog());
6964 EXPECT_EQ(ERR_IO_PENDING, rv);
6965 EXPECT_EQ(OK, callback.WaitForResult());
6966
6967 response = trans->GetResponseInfo();
6968 ASSERT_TRUE(response != NULL);
6969 ASSERT_TRUE(response->headers != NULL);
6970 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536971 EXPECT_TRUE(response->was_fetched_via_spdy);
6972 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116973
6974 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6975 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:556976 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:426977 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116978 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426979 EXPECT_EQ("https://www.google.com/",
6980 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116981
[email protected]8e6441ca2010-08-19 05:56:386982 HttpStreamFactory::set_next_protos("");
6983 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116984}
[email protected]631f1322010-04-30 17:59:116985
[email protected]2ff8b312010-04-26 22:20:546986TEST_F(HttpNetworkTransactionTest,
6987 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386988 HttpStreamFactory::set_use_alternate_protocols(true);
6989 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546990 SessionDependencies session_deps;
6991
6992 HttpRequestInfo request;
6993 request.method = "GET";
6994 request.url = GURL("http://www.google.com/");
6995 request.load_flags = 0;
6996
6997 MockRead data_reads[] = {
6998 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356999 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547000 MockRead("hello world"),
7001 MockRead(true, OK),
7002 };
7003
7004 StaticSocketDataProvider first_transaction(
7005 data_reads, arraysize(data_reads), NULL, 0);
7006 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7007
7008 SSLSocketDataProvider ssl(true, OK);
7009 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357010 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537011 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547012 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537013 // Make sure we use ssl for spdy here.
7014 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547015
[email protected]2bd93022010-07-17 00:58:447016 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137017 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547018
[email protected]2bd93022010-07-17 00:58:447019 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7020 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547021 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137022 CreateMockRead(*resp),
7023 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547024 MockRead(true, 0, 0),
7025 };
7026
7027 scoped_refptr<DelayedSocketData> spdy_data(
7028 new DelayedSocketData(
7029 1, // wait for one write to finish before reading.
7030 spdy_reads, arraysize(spdy_reads),
7031 spdy_writes, arraysize(spdy_writes)));
7032 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7033
7034 TestCompletionCallback callback;
7035
7036 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7037
7038 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7039
[email protected]5a1d7ca2010-04-28 20:12:277040 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547041 EXPECT_EQ(ERR_IO_PENDING, rv);
7042 EXPECT_EQ(OK, callback.WaitForResult());
7043
7044 const HttpResponseInfo* response = trans->GetResponseInfo();
7045 ASSERT_TRUE(response != NULL);
7046 ASSERT_TRUE(response->headers != NULL);
7047 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7048
7049 std::string response_data;
7050 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7051 EXPECT_EQ("hello world", response_data);
7052
7053 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387054 HostPortPair host_port_pair("www.google.com", 443);
7055 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547056 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317057 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287058 scoped_refptr<TransportSocketParams> transport_params(
7059 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:387060
7061 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7062 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287063 connection->Init(host_port_pair.ToString(),
7064 transport_params,
7065 LOWEST,
7066 &callback,
7067 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387068 BoundNetLog()));
7069 EXPECT_EQ(OK, callback.WaitForResult());
7070
7071 SSLConfig ssl_config;
7072 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347073 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177074 SSLClientSocketContext context;
7075 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347076 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7077 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177078 NULL /* ssl_host_info */, context));
[email protected]9e1bdd32011-02-03 21:48:347079 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387080 EXPECT_EQ(OK, callback.WaitForResult());
7081
[email protected]9e1bdd32011-02-03 21:48:347082 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387083 true, OK));
7084
[email protected]2ff8b312010-04-26 22:20:547085 trans.reset(new HttpNetworkTransaction(session));
7086
[email protected]5a1d7ca2010-04-28 20:12:277087 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547088 EXPECT_EQ(ERR_IO_PENDING, rv);
7089 EXPECT_EQ(OK, callback.WaitForResult());
7090
7091 response = trans->GetResponseInfo();
7092 ASSERT_TRUE(response != NULL);
7093 ASSERT_TRUE(response->headers != NULL);
7094 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537095 EXPECT_TRUE(response->was_fetched_via_spdy);
7096 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547097
7098 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7099 EXPECT_EQ("hello!", response_data);
7100
[email protected]8e6441ca2010-08-19 05:56:387101 HttpStreamFactory::set_next_protos("");
7102 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427103}
7104
[email protected]044de0642010-06-17 10:42:157105// GenerateAuthToken is a mighty big test.
7106// It tests all permutation of GenerateAuthToken behavior:
7107// - Synchronous and Asynchronous completion.
7108// - OK or error on completion.
7109// - Direct connection, non-authenticating proxy, and authenticating proxy.
7110// - HTTP or HTTPS backend (to include proxy tunneling).
7111// - Non-authenticating and authenticating backend.
7112//
7113// In all, there are 44 reasonable permuations (for example, if there are
7114// problems generating an auth token for an authenticating proxy, we don't
7115// need to test all permutations of the backend server).
7116//
7117// The test proceeds by going over each of the configuration cases, and
7118// potentially running up to three rounds in each of the tests. The TestConfig
7119// specifies both the configuration for the test as well as the expectations
7120// for the results.
7121TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507122 static const char kServer[] = "http://www.example.com";
7123 static const char kSecureServer[] = "https://www.example.com";
7124 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157125 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7126
7127 enum AuthTiming {
7128 AUTH_NONE,
7129 AUTH_SYNC,
7130 AUTH_ASYNC,
7131 };
7132
7133 const MockWrite kGet(
7134 "GET / HTTP/1.1\r\n"
7135 "Host: www.example.com\r\n"
7136 "Connection: keep-alive\r\n\r\n");
7137 const MockWrite kGetProxy(
7138 "GET http://www.example.com/ HTTP/1.1\r\n"
7139 "Host: www.example.com\r\n"
7140 "Proxy-Connection: keep-alive\r\n\r\n");
7141 const MockWrite kGetAuth(
7142 "GET / HTTP/1.1\r\n"
7143 "Host: www.example.com\r\n"
7144 "Connection: keep-alive\r\n"
7145 "Authorization: auth_token\r\n\r\n");
7146 const MockWrite kGetProxyAuth(
7147 "GET http://www.example.com/ HTTP/1.1\r\n"
7148 "Host: www.example.com\r\n"
7149 "Proxy-Connection: keep-alive\r\n"
7150 "Proxy-Authorization: auth_token\r\n\r\n");
7151 const MockWrite kGetAuthThroughProxy(
7152 "GET http://www.example.com/ HTTP/1.1\r\n"
7153 "Host: www.example.com\r\n"
7154 "Proxy-Connection: keep-alive\r\n"
7155 "Authorization: auth_token\r\n\r\n");
7156 const MockWrite kGetAuthWithProxyAuth(
7157 "GET http://www.example.com/ HTTP/1.1\r\n"
7158 "Host: www.example.com\r\n"
7159 "Proxy-Connection: keep-alive\r\n"
7160 "Proxy-Authorization: auth_token\r\n"
7161 "Authorization: auth_token\r\n\r\n");
7162 const MockWrite kConnect(
7163 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7164 "Host: www.example.com\r\n"
7165 "Proxy-Connection: keep-alive\r\n\r\n");
7166 const MockWrite kConnectProxyAuth(
7167 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7168 "Host: www.example.com\r\n"
7169 "Proxy-Connection: keep-alive\r\n"
7170 "Proxy-Authorization: auth_token\r\n\r\n");
7171
7172 const MockRead kSuccess(
7173 "HTTP/1.1 200 OK\r\n"
7174 "Content-Type: text/html; charset=iso-8859-1\r\n"
7175 "Content-Length: 3\r\n\r\n"
7176 "Yes");
7177 const MockRead kFailure(
7178 "Should not be called.");
7179 const MockRead kServerChallenge(
7180 "HTTP/1.1 401 Unauthorized\r\n"
7181 "WWW-Authenticate: Mock realm=server\r\n"
7182 "Content-Type: text/html; charset=iso-8859-1\r\n"
7183 "Content-Length: 14\r\n\r\n"
7184 "Unauthorized\r\n");
7185 const MockRead kProxyChallenge(
7186 "HTTP/1.1 407 Unauthorized\r\n"
7187 "Proxy-Authenticate: Mock realm=proxy\r\n"
7188 "Proxy-Connection: close\r\n"
7189 "Content-Type: text/html; charset=iso-8859-1\r\n"
7190 "Content-Length: 14\r\n\r\n"
7191 "Unauthorized\r\n");
7192 const MockRead kProxyConnected(
7193 "HTTP/1.1 200 Connection Established\r\n\r\n");
7194
7195 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7196 // no constructors, but the C++ compiler on Windows warns about
7197 // unspecified data in compound literals. So, moved to using constructors,
7198 // and TestRound's created with the default constructor should not be used.
7199 struct TestRound {
7200 TestRound()
7201 : expected_rv(ERR_UNEXPECTED),
7202 extra_write(NULL),
7203 extra_read(NULL) {
7204 }
7205 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7206 int expected_rv_arg)
7207 : write(write_arg),
7208 read(read_arg),
7209 expected_rv(expected_rv_arg),
7210 extra_write(NULL),
7211 extra_read(NULL) {
7212 }
7213 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7214 int expected_rv_arg, const MockWrite* extra_write_arg,
7215 const MockWrite* extra_read_arg)
7216 : write(write_arg),
7217 read(read_arg),
7218 expected_rv(expected_rv_arg),
7219 extra_write(extra_write_arg),
7220 extra_read(extra_read_arg) {
7221 }
7222 MockWrite write;
7223 MockRead read;
7224 int expected_rv;
7225 const MockWrite* extra_write;
7226 const MockRead* extra_read;
7227 };
7228
7229 static const int kNoSSL = 500;
7230
7231 struct TestConfig {
7232 const char* proxy_url;
7233 AuthTiming proxy_auth_timing;
7234 int proxy_auth_rv;
7235 const char* server_url;
7236 AuthTiming server_auth_timing;
7237 int server_auth_rv;
7238 int num_auth_rounds;
7239 int first_ssl_round;
7240 TestRound rounds[3];
7241 } test_configs[] = {
7242 // Non-authenticating HTTP server with a direct connection.
7243 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7244 { TestRound(kGet, kSuccess, OK)}},
7245 // Authenticating HTTP server with a direct connection.
7246 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7247 { TestRound(kGet, kServerChallenge, OK),
7248 TestRound(kGetAuth, kSuccess, OK)}},
7249 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7250 { TestRound(kGet, kServerChallenge, OK),
7251 TestRound(kGetAuth, kFailure, kAuthErr)}},
7252 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7253 { TestRound(kGet, kServerChallenge, OK),
7254 TestRound(kGetAuth, kSuccess, OK)}},
7255 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7256 { TestRound(kGet, kServerChallenge, OK),
7257 TestRound(kGetAuth, kFailure, kAuthErr)}},
7258 // Non-authenticating HTTP server through a non-authenticating proxy.
7259 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7260 { TestRound(kGetProxy, kSuccess, OK)}},
7261 // Authenticating HTTP server through a non-authenticating proxy.
7262 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7263 { TestRound(kGetProxy, kServerChallenge, OK),
7264 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7265 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7266 { TestRound(kGetProxy, kServerChallenge, OK),
7267 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7268 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7269 { TestRound(kGetProxy, kServerChallenge, OK),
7270 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7271 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7272 { TestRound(kGetProxy, kServerChallenge, OK),
7273 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7274 // Non-authenticating HTTP server through an authenticating proxy.
7275 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7276 { TestRound(kGetProxy, kProxyChallenge, OK),
7277 TestRound(kGetProxyAuth, kSuccess, OK)}},
7278 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7279 { TestRound(kGetProxy, kProxyChallenge, OK),
7280 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7281 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7282 { TestRound(kGetProxy, kProxyChallenge, OK),
7283 TestRound(kGetProxyAuth, kSuccess, OK)}},
7284 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7285 { TestRound(kGetProxy, kProxyChallenge, OK),
7286 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7287 // Authenticating HTTP server through an authenticating proxy.
7288 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7289 { TestRound(kGetProxy, kProxyChallenge, OK),
7290 TestRound(kGetProxyAuth, kServerChallenge, OK),
7291 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7292 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7293 { TestRound(kGetProxy, kProxyChallenge, OK),
7294 TestRound(kGetProxyAuth, kServerChallenge, OK),
7295 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7296 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7297 { TestRound(kGetProxy, kProxyChallenge, OK),
7298 TestRound(kGetProxyAuth, kServerChallenge, OK),
7299 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7300 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7301 { TestRound(kGetProxy, kProxyChallenge, OK),
7302 TestRound(kGetProxyAuth, kServerChallenge, OK),
7303 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7304 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7305 { TestRound(kGetProxy, kProxyChallenge, OK),
7306 TestRound(kGetProxyAuth, kServerChallenge, OK),
7307 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7308 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7309 { TestRound(kGetProxy, kProxyChallenge, OK),
7310 TestRound(kGetProxyAuth, kServerChallenge, OK),
7311 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7312 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7313 { TestRound(kGetProxy, kProxyChallenge, OK),
7314 TestRound(kGetProxyAuth, kServerChallenge, OK),
7315 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7316 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7317 { TestRound(kGetProxy, kProxyChallenge, OK),
7318 TestRound(kGetProxyAuth, kServerChallenge, OK),
7319 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7320 // Non-authenticating HTTPS server with a direct connection.
7321 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7322 { TestRound(kGet, kSuccess, OK)}},
7323 // Authenticating HTTPS server with a direct connection.
7324 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7325 { TestRound(kGet, kServerChallenge, OK),
7326 TestRound(kGetAuth, kSuccess, OK)}},
7327 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7328 { TestRound(kGet, kServerChallenge, OK),
7329 TestRound(kGetAuth, kFailure, kAuthErr)}},
7330 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7331 { TestRound(kGet, kServerChallenge, OK),
7332 TestRound(kGetAuth, kSuccess, OK)}},
7333 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7334 { TestRound(kGet, kServerChallenge, OK),
7335 TestRound(kGetAuth, kFailure, kAuthErr)}},
7336 // Non-authenticating HTTPS server with a non-authenticating proxy.
7337 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7338 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7339 // Authenticating HTTPS server through a non-authenticating proxy.
7340 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7341 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7342 TestRound(kGetAuth, kSuccess, OK)}},
7343 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7344 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7345 TestRound(kGetAuth, kFailure, kAuthErr)}},
7346 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7347 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7348 TestRound(kGetAuth, kSuccess, OK)}},
7349 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7350 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7351 TestRound(kGetAuth, kFailure, kAuthErr)}},
7352 // Non-Authenticating HTTPS server through an authenticating proxy.
7353 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7354 { TestRound(kConnect, kProxyChallenge, OK),
7355 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7356 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7357 { TestRound(kConnect, kProxyChallenge, OK),
7358 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7359 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7360 { TestRound(kConnect, kProxyChallenge, OK),
7361 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7362 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7363 { TestRound(kConnect, kProxyChallenge, OK),
7364 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7365 // Authenticating HTTPS server through an authenticating proxy.
7366 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7367 { TestRound(kConnect, kProxyChallenge, OK),
7368 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7369 &kGet, &kServerChallenge),
7370 TestRound(kGetAuth, kSuccess, OK)}},
7371 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7372 { TestRound(kConnect, kProxyChallenge, OK),
7373 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7374 &kGet, &kServerChallenge),
7375 TestRound(kGetAuth, kFailure, kAuthErr)}},
7376 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7377 { TestRound(kConnect, kProxyChallenge, OK),
7378 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7379 &kGet, &kServerChallenge),
7380 TestRound(kGetAuth, kSuccess, OK)}},
7381 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7382 { TestRound(kConnect, kProxyChallenge, OK),
7383 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7384 &kGet, &kServerChallenge),
7385 TestRound(kGetAuth, kFailure, kAuthErr)}},
7386 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7387 { TestRound(kConnect, kProxyChallenge, OK),
7388 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7389 &kGet, &kServerChallenge),
7390 TestRound(kGetAuth, kSuccess, OK)}},
7391 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7392 { TestRound(kConnect, kProxyChallenge, OK),
7393 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7394 &kGet, &kServerChallenge),
7395 TestRound(kGetAuth, kFailure, kAuthErr)}},
7396 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7397 { TestRound(kConnect, kProxyChallenge, OK),
7398 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7399 &kGet, &kServerChallenge),
7400 TestRound(kGetAuth, kSuccess, OK)}},
7401 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7402 { TestRound(kConnect, kProxyChallenge, OK),
7403 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7404 &kGet, &kServerChallenge),
7405 TestRound(kGetAuth, kFailure, kAuthErr)}},
7406 };
7407
7408 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157409 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087410 HttpAuthHandlerMock::Factory* auth_factory(
7411 new HttpAuthHandlerMock::Factory());
7412 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157413 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267414
7415 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157416 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087417 for (int n = 0; n < 2; n++) {
7418 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7419 std::string auth_challenge = "Mock realm=proxy";
7420 GURL origin(test_config.proxy_url);
7421 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7422 auth_challenge.end());
7423 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7424 origin, BoundNetLog());
7425 auth_handler->SetGenerateExpectation(
7426 test_config.proxy_auth_timing == AUTH_ASYNC,
7427 test_config.proxy_auth_rv);
7428 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7429 }
[email protected]044de0642010-06-17 10:42:157430 }
7431 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007432 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157433 std::string auth_challenge = "Mock realm=server";
7434 GURL origin(test_config.server_url);
7435 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7436 auth_challenge.end());
7437 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7438 origin, BoundNetLog());
7439 auth_handler->SetGenerateExpectation(
7440 test_config.server_auth_timing == AUTH_ASYNC,
7441 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087442 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157443 }
7444 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127445 session_deps.proxy_service.reset(
7446 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157447 } else {
[email protected]6104ea5d2011-04-27 21:37:127448 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157449 }
7450
7451 HttpRequestInfo request;
7452 request.method = "GET";
7453 request.url = GURL(test_config.server_url);
7454 request.load_flags = 0;
7455
[email protected]0b0bf032010-09-21 18:08:507456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7457 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157458
7459 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7460 const TestRound& read_write_round = test_config.rounds[round];
7461
7462 // Set up expected reads and writes.
7463 MockRead reads[2];
7464 reads[0] = read_write_round.read;
7465 size_t length_reads = 1;
7466 if (read_write_round.extra_read) {
7467 reads[1] = *read_write_round.extra_read;
7468 length_reads = 2;
7469 }
7470
7471 MockWrite writes[2];
7472 writes[0] = read_write_round.write;
7473 size_t length_writes = 1;
7474 if (read_write_round.extra_write) {
7475 writes[1] = *read_write_round.extra_write;
7476 length_writes = 2;
7477 }
7478 StaticSocketDataProvider data_provider(
7479 reads, length_reads, writes, length_writes);
7480 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7481
7482 // Add an SSL sequence if necessary.
7483 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7484 if (round >= test_config.first_ssl_round)
7485 session_deps.socket_factory.AddSSLSocketDataProvider(
7486 &ssl_socket_data_provider);
7487
7488 // Start or restart the transaction.
7489 TestCompletionCallback callback;
7490 int rv;
7491 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507492 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157493 } else {
[email protected]0b0bf032010-09-21 18:08:507494 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157495 }
7496 if (rv == ERR_IO_PENDING)
7497 rv = callback.WaitForResult();
7498
7499 // Compare results with expected data.
7500 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507501 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157502 if (read_write_round.expected_rv == OK) {
7503 EXPECT_FALSE(response == NULL);
7504 } else {
7505 EXPECT_TRUE(response == NULL);
7506 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7507 continue;
7508 }
7509 if (round + 1 < test_config.num_auth_rounds) {
7510 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7511 } else {
7512 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7513 }
7514 }
[email protected]e5ae96a2010-04-14 20:12:457515 }
7516}
7517
[email protected]c871bce92010-07-15 21:51:147518TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7519 // Do multi-round authentication and make sure it works correctly.
7520 SessionDependencies session_deps;
7521 HttpAuthHandlerMock::Factory* auth_factory(
7522 new HttpAuthHandlerMock::Factory());
7523 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127524 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147525 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7526 session_deps.host_resolver->set_synchronous_mode(true);
7527
7528 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7529 auth_handler->set_connection_based(true);
7530 std::string auth_challenge = "Mock realm=server";
7531 GURL origin("http://www.example.com");
7532 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7533 auth_challenge.end());
7534 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7535 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087536 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147537
[email protected]c871bce92010-07-15 21:51:147538 int rv = OK;
7539 const HttpResponseInfo* response = NULL;
7540 HttpRequestInfo request;
7541 request.method = "GET";
7542 request.url = origin;
7543 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277544
7545 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107546
7547 // Use a TCP Socket Pool with only one connection per group. This is used
7548 // to validate that the TCP socket is not released to the pool between
7549 // each round of multi-round authentication.
7550 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287551 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7552 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107553 50, // Max sockets for pool
7554 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287555 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107556 session_deps.host_resolver.get(),
7557 &session_deps.socket_factory,
7558 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287559 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107560
[email protected]cb9bf6ca2011-01-28 13:15:277561 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147562 TestCompletionCallback callback;
7563
7564 const MockWrite kGet(
7565 "GET / HTTP/1.1\r\n"
7566 "Host: www.example.com\r\n"
7567 "Connection: keep-alive\r\n\r\n");
7568 const MockWrite kGetAuth(
7569 "GET / HTTP/1.1\r\n"
7570 "Host: www.example.com\r\n"
7571 "Connection: keep-alive\r\n"
7572 "Authorization: auth_token\r\n\r\n");
7573
7574 const MockRead kServerChallenge(
7575 "HTTP/1.1 401 Unauthorized\r\n"
7576 "WWW-Authenticate: Mock realm=server\r\n"
7577 "Content-Type: text/html; charset=iso-8859-1\r\n"
7578 "Content-Length: 14\r\n\r\n"
7579 "Unauthorized\r\n");
7580 const MockRead kSuccess(
7581 "HTTP/1.1 200 OK\r\n"
7582 "Content-Type: text/html; charset=iso-8859-1\r\n"
7583 "Content-Length: 3\r\n\r\n"
7584 "Yes");
7585
7586 MockWrite writes[] = {
7587 // First round
7588 kGet,
7589 // Second round
7590 kGetAuth,
7591 // Third round
7592 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307593 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107594 kGetAuth,
7595 // Competing request
7596 kGet,
[email protected]c871bce92010-07-15 21:51:147597 };
7598 MockRead reads[] = {
7599 // First round
7600 kServerChallenge,
7601 // Second round
7602 kServerChallenge,
7603 // Third round
[email protected]eca50e122010-09-11 14:03:307604 kServerChallenge,
7605 // Fourth round
[email protected]c871bce92010-07-15 21:51:147606 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107607 // Competing response
7608 kSuccess,
[email protected]c871bce92010-07-15 21:51:147609 };
7610 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7611 writes, arraysize(writes));
7612 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7613
[email protected]7ef4cbbb2011-02-06 11:19:107614 const char* const kSocketGroup = "www.example.com:80";
7615
7616 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147617 auth_handler->SetGenerateExpectation(false, OK);
7618 rv = trans->Start(&request, &callback, BoundNetLog());
7619 if (rv == ERR_IO_PENDING)
7620 rv = callback.WaitForResult();
7621 EXPECT_EQ(OK, rv);
7622 response = trans->GetResponseInfo();
7623 ASSERT_FALSE(response == NULL);
7624 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287625 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147626
[email protected]7ef4cbbb2011-02-06 11:19:107627 // In between rounds, another request comes in for the same domain.
7628 // It should not be able to grab the TCP socket that trans has already
7629 // claimed.
7630 scoped_ptr<HttpTransaction> trans_compete(
7631 new HttpNetworkTransaction(session));
7632 TestCompletionCallback callback_compete;
7633 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7634 EXPECT_EQ(ERR_IO_PENDING, rv);
7635 // callback_compete.WaitForResult at this point would stall forever,
7636 // since the HttpNetworkTransaction does not release the request back to
7637 // the pool until after authentication completes.
7638
7639 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147640 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447641 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147642 if (rv == ERR_IO_PENDING)
7643 rv = callback.WaitForResult();
7644 EXPECT_EQ(OK, rv);
7645 response = trans->GetResponseInfo();
7646 ASSERT_FALSE(response == NULL);
7647 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287648 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147649
[email protected]7ef4cbbb2011-02-06 11:19:107650 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147651 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447652 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147653 if (rv == ERR_IO_PENDING)
7654 rv = callback.WaitForResult();
7655 EXPECT_EQ(OK, rv);
7656 response = trans->GetResponseInfo();
7657 ASSERT_FALSE(response == NULL);
7658 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287659 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307660
[email protected]7ef4cbbb2011-02-06 11:19:107661 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307662 auth_handler->SetGenerateExpectation(false, OK);
7663 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7664 if (rv == ERR_IO_PENDING)
7665 rv = callback.WaitForResult();
7666 EXPECT_EQ(OK, rv);
7667 response = trans->GetResponseInfo();
7668 ASSERT_FALSE(response == NULL);
7669 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287670 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107671
7672 // Read the body since the fourth round was successful. This will also
7673 // release the socket back to the pool.
7674 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7675 rv = trans->Read(io_buf, io_buf->size(), &callback);
7676 if (rv == ERR_IO_PENDING)
7677 rv = callback.WaitForResult();
7678 EXPECT_EQ(3, rv);
7679 rv = trans->Read(io_buf, io_buf->size(), &callback);
7680 EXPECT_EQ(0, rv);
7681 // There are still 0 idle sockets, since the trans_compete transaction
7682 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287683 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107684
7685 // The competing request can now finish. Wait for the headers and then
7686 // read the body.
7687 rv = callback_compete.WaitForResult();
7688 EXPECT_EQ(OK, rv);
7689 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7690 if (rv == ERR_IO_PENDING)
7691 rv = callback.WaitForResult();
7692 EXPECT_EQ(3, rv);
7693 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7694 EXPECT_EQ(0, rv);
7695
7696 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287697 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147698}
7699
[email protected]aeaca1f2010-04-20 22:05:217700class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7701 public:
[email protected]06650c52010-06-03 00:49:177702 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217703 : fail_all_(fail_all) {
7704 }
7705
7706 virtual MockRead GetNextRead() {
7707 if (fail_all_)
7708 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7709
7710 return MockRead(false /* async */,
7711 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7712 }
7713
7714 virtual MockWriteResult OnWrite(const std::string& data) {
7715 return MockWriteResult(false /* async */, data.size());
7716 }
7717
7718 void Reset() {
7719 }
7720
7721 private:
7722 const bool fail_all_;
7723};
7724
7725// Test that we restart a connection when we see a decompression failure from
7726// the peer during the handshake. (In the real world we'll restart with SSLv3
7727// and we won't offer DEFLATE in that case.)
7728TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7729 HttpRequestInfo request;
7730 request.method = "GET";
7731 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7732 request.load_flags = 0;
7733
7734 SessionDependencies session_deps;
7735 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7736 false /* fail all reads */);
7737 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7738 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117739 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217740 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7741 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7742 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7743 session_deps.socket_factory.AddSSLSocketDataProvider(
7744 &ssl_socket_data_provider1);
7745 session_deps.socket_factory.AddSSLSocketDataProvider(
7746 &ssl_socket_data_provider2);
7747
[email protected]e60e47a2010-07-14 03:37:187748 // Work around http://crbug.com/37454
7749 StaticSocketDataProvider bug37454_connection;
7750 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7751 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7752
[email protected]aeaca1f2010-04-20 22:05:217753 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7754 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7755 TestCompletionCallback callback;
7756
[email protected]5a1d7ca2010-04-28 20:12:277757 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217758 EXPECT_EQ(ERR_IO_PENDING, rv);
7759 EXPECT_EQ(OK, callback.WaitForResult());
7760
7761 const HttpResponseInfo* response = trans->GetResponseInfo();
7762 ASSERT_TRUE(response != NULL);
7763 ASSERT_TRUE(response->headers != NULL);
7764 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7765
7766 std::string response_data;
7767 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7768 EXPECT_EQ("ok.", response_data);
7769}
7770
7771// Test that we restart a connection if we get a decompression failure from the
7772// peer while reading the first bytes from the connection. This occurs when the
7773// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7774// in the handshake.
7775TEST_F(HttpNetworkTransactionTest,
7776 RestartAfterTLSDecompressionFailureWithFalseStart) {
7777 HttpRequestInfo request;
7778 request.method = "GET";
7779 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7780 request.load_flags = 0;
7781
7782 SessionDependencies session_deps;
7783 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7784 true /* fail all reads */);
7785 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7786 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7787 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7788 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7789 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7790 session_deps.socket_factory.AddSSLSocketDataProvider(
7791 &ssl_socket_data_provider1);
7792 session_deps.socket_factory.AddSSLSocketDataProvider(
7793 &ssl_socket_data_provider2);
7794
7795 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7796 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7797 TestCompletionCallback callback;
7798
[email protected]5a1d7ca2010-04-28 20:12:277799 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217800 EXPECT_EQ(ERR_IO_PENDING, rv);
7801 EXPECT_EQ(OK, callback.WaitForResult());
7802
7803 const HttpResponseInfo* response = trans->GetResponseInfo();
7804 ASSERT_TRUE(response != NULL);
7805 ASSERT_TRUE(response->headers != NULL);
7806 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7807
7808 std::string response_data;
7809 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7810 EXPECT_EQ("ok.", response_data);
7811}
7812
[email protected]65041fa2010-05-21 06:56:537813// This tests the case that a request is issued via http instead of spdy after
7814// npn is negotiated.
7815TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387816 HttpStreamFactory::set_use_alternate_protocols(true);
7817 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537818 SessionDependencies session_deps;
7819 HttpRequestInfo request;
7820 request.method = "GET";
7821 request.url = GURL("https://www.google.com/");
7822 request.load_flags = 0;
7823
7824 MockWrite data_writes[] = {
7825 MockWrite("GET / HTTP/1.1\r\n"
7826 "Host: www.google.com\r\n"
7827 "Connection: keep-alive\r\n\r\n"),
7828 };
7829
7830 MockRead data_reads[] = {
7831 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357832 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537833 MockRead("hello world"),
7834 MockRead(false, OK),
7835 };
7836
7837 SSLSocketDataProvider ssl(true, OK);
7838 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7839 ssl.next_proto = "http/1.1";
7840
7841 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7842
7843 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7844 data_writes, arraysize(data_writes));
7845 session_deps.socket_factory.AddSocketDataProvider(&data);
7846
7847 TestCompletionCallback callback;
7848
7849 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7850 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7851
7852 int rv = trans->Start(&request, &callback, BoundNetLog());
7853
7854 EXPECT_EQ(ERR_IO_PENDING, rv);
7855 EXPECT_EQ(OK, callback.WaitForResult());
7856
7857 const HttpResponseInfo* response = trans->GetResponseInfo();
7858 ASSERT_TRUE(response != NULL);
7859 ASSERT_TRUE(response->headers != NULL);
7860 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7861
7862 std::string response_data;
7863 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7864 EXPECT_EQ("hello world", response_data);
7865
7866 EXPECT_FALSE(response->was_fetched_via_spdy);
7867 EXPECT_TRUE(response->was_npn_negotiated);
7868
[email protected]8e6441ca2010-08-19 05:56:387869 HttpStreamFactory::set_next_protos("");
7870 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537871}
[email protected]26ef6582010-06-24 02:30:477872
7873TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7874 // Simulate the SSL handshake completing with an NPN negotiation
7875 // followed by an immediate server closing of the socket.
7876 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387877 HttpStreamFactory::set_use_alternate_protocols(true);
7878 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477879 SessionDependencies session_deps;
7880
7881 HttpRequestInfo request;
7882 request.method = "GET";
7883 request.url = GURL("https://www.google.com/");
7884 request.load_flags = 0;
7885
7886 SSLSocketDataProvider ssl(true, OK);
7887 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357888 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477889 ssl.was_npn_negotiated = true;
7890 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7891
[email protected]2bd93022010-07-17 00:58:447892 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137893 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477894
7895 MockRead spdy_reads[] = {
7896 MockRead(false, 0, 0) // Not async - return 0 immediately.
7897 };
7898
7899 scoped_refptr<DelayedSocketData> spdy_data(
7900 new DelayedSocketData(
7901 0, // don't wait in this case, immediate hangup.
7902 spdy_reads, arraysize(spdy_reads),
7903 spdy_writes, arraysize(spdy_writes)));
7904 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7905
7906 TestCompletionCallback callback;
7907
7908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7909 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7910
7911 int rv = trans->Start(&request, &callback, BoundNetLog());
7912 EXPECT_EQ(ERR_IO_PENDING, rv);
7913 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7914
[email protected]8e6441ca2010-08-19 05:56:387915 HttpStreamFactory::set_next_protos("");
7916 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477917}
[email protected]65d34382010-07-01 18:12:267918
[email protected]f45c1ee2010-08-03 00:54:307919TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7920 // This test ensures that the URL passed into the proxy is upgraded
7921 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387922 HttpStreamFactory::set_use_alternate_protocols(true);
7923 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307924 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7925
[email protected]81cdfcd2010-10-16 00:49:007926 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307927 HttpAuthHandlerMock::Factory* auth_factory =
7928 new HttpAuthHandlerMock::Factory();
7929 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
[email protected]2d01c262011-08-11 23:07:087930 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:307931 auth_factory->set_do_init_from_challenge(true);
7932 session_deps.http_auth_handler_factory.reset(auth_factory);
7933
7934 HttpRequestInfo request;
7935 request.method = "GET";
7936 request.url = GURL("http://www.google.com");
7937 request.load_flags = 0;
7938
7939 // First round goes unauthenticated through the proxy.
7940 MockWrite data_writes_1[] = {
7941 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7942 "Host: www.google.com\r\n"
7943 "Proxy-Connection: keep-alive\r\n"
7944 "\r\n"),
7945 };
7946 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597947 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307948 MockRead("HTTP/1.1 200 OK\r\n"
7949 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7950 "Proxy-Connection: close\r\n"
7951 "\r\n"),
7952 };
7953 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7954 data_writes_1, arraysize(data_writes_1));
7955
7956 // Second round tries to tunnel to www.google.com due to the
7957 // Alternate-Protocol announcement in the first round. It fails due
7958 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597959 // After the failure, a tunnel is established to www.google.com using
7960 // Proxy-Authorization headers. There is then a SPDY request round.
7961 //
7962 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7963 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7964 // does a Disconnect and Connect on the same socket, rather than trying
7965 // to obtain a new one.
7966 //
7967 // NOTE: Originally, the proxy response to the second CONNECT request
7968 // simply returned another 407 so the unit test could skip the SSL connection
7969 // establishment and SPDY framing issues. Alas, the
7970 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307971 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597972
[email protected]f45c1ee2010-08-03 00:54:307973 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7974 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7975 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7976
[email protected]394816e92010-08-03 07:38:597977 MockWrite data_writes_2[] = {
7978 // First connection attempt without Proxy-Authorization.
7979 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7980 "Host: www.google.com\r\n"
7981 "Proxy-Connection: keep-alive\r\n"
7982 "\r\n"),
7983
7984 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307985 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7986 "Host: www.google.com\r\n"
7987 "Proxy-Connection: keep-alive\r\n"
7988 "Proxy-Authorization: auth_token\r\n"
7989 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307990
[email protected]394816e92010-08-03 07:38:597991 // SPDY request
7992 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307993 };
[email protected]394816e92010-08-03 07:38:597994 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7995 "Proxy-Authenticate: Mock\r\n"
7996 "Proxy-Connection: close\r\n"
7997 "\r\n");
7998 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7999 MockRead data_reads_2[] = {
8000 // First connection attempt fails
8001 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8002 MockRead(true, kRejectConnectResponse,
8003 arraysize(kRejectConnectResponse) - 1, 1),
8004
8005 // Second connection attempt passes
8006 MockRead(true, kAcceptConnectResponse,
8007 arraysize(kAcceptConnectResponse) -1, 4),
8008
8009 // SPDY response
8010 CreateMockRead(*resp.get(), 6),
8011 CreateMockRead(*data.get(), 6),
8012 MockRead(true, 0, 0, 6),
8013 };
8014 scoped_refptr<OrderedSocketData> data_2(
8015 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8016 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308017
8018 SSLSocketDataProvider ssl(true, OK);
8019 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8020 ssl.next_proto = "spdy/2";
8021 ssl.was_npn_negotiated = true;
8022
[email protected]2d6728692011-03-12 01:39:558023 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8024 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8025 NULL, 0, NULL, 0);
8026 hanging_non_alternate_protocol_socket.set_connect_data(
8027 never_finishing_connect);
8028
[email protected]f45c1ee2010-08-03 00:54:308029 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598030 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308031 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558032 session_deps.socket_factory.AddSocketDataProvider(
8033 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308034 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8035
8036 // First round should work and provide the Alternate-Protocol state.
8037 TestCompletionCallback callback_1;
8038 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8039 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8040 EXPECT_EQ(ERR_IO_PENDING, rv);
8041 EXPECT_EQ(OK, callback_1.WaitForResult());
8042
8043 // Second round should attempt a tunnel connect and get an auth challenge.
8044 TestCompletionCallback callback_2;
8045 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8046 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8047 EXPECT_EQ(ERR_IO_PENDING, rv);
8048 EXPECT_EQ(OK, callback_2.WaitForResult());
8049 const HttpResponseInfo* response = trans_2->GetResponseInfo();
8050 ASSERT_FALSE(response == NULL);
8051 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8052
8053 // Restart with auth. Tunnel should work and response received.
8054 TestCompletionCallback callback_3;
8055 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
8056 EXPECT_EQ(ERR_IO_PENDING, rv);
8057 EXPECT_EQ(OK, callback_3.WaitForResult());
8058
8059 // After all that work, these two lines (or actually, just the scheme) are
8060 // what this test is all about. Make sure it happens correctly.
8061 const GURL& request_url = auth_handler->request_url();
8062 EXPECT_EQ("https", request_url.scheme());
8063 EXPECT_EQ("www.google.com", request_url.host());
8064
[email protected]8e6441ca2010-08-19 05:56:388065 HttpStreamFactory::set_next_protos("");
8066 HttpStreamFactory::set_use_alternate_protocols(false);
8067}
8068
8069// Test that if we cancel the transaction as the connection is completing, that
8070// everything tears down correctly.
8071TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8072 // Setup everything about the connection to complete synchronously, so that
8073 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8074 // for is the callback from the HttpStreamRequest.
8075 // Then cancel the transaction.
8076 // Verify that we don't crash.
8077 MockConnect mock_connect(false, OK);
8078 MockRead data_reads[] = {
8079 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8080 MockRead(false, "hello world"),
8081 MockRead(false, OK),
8082 };
8083
[email protected]8e6441ca2010-08-19 05:56:388084 HttpRequestInfo request;
8085 request.method = "GET";
8086 request.url = GURL("http://www.google.com/");
8087 request.load_flags = 0;
8088
[email protected]cb9bf6ca2011-01-28 13:15:278089 SessionDependencies session_deps;
8090 session_deps.host_resolver->set_synchronous_mode(true);
8091 scoped_ptr<HttpTransaction> trans(
8092 new HttpNetworkTransaction(CreateSession(&session_deps)));
8093
[email protected]8e6441ca2010-08-19 05:56:388094 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8095 data.set_connect_data(mock_connect);
8096 session_deps.socket_factory.AddSocketDataProvider(&data);
8097
8098 TestCompletionCallback callback;
8099
8100 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8101 int rv = trans->Start(&request, &callback, log.bound());
8102 EXPECT_EQ(ERR_IO_PENDING, rv);
8103 trans.reset(); // Cancel the transaction here.
8104
8105 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308106}
8107
[email protected]76a505b2010-08-25 06:23:008108// Test a basic GET request through a proxy.
8109TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008110 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008111 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8112 session_deps.net_log = log.bound().net_log();
8113 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8114
[email protected]76a505b2010-08-25 06:23:008115 HttpRequestInfo request;
8116 request.method = "GET";
8117 request.url = GURL("http://www.google.com/");
8118
8119 MockWrite data_writes1[] = {
8120 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8121 "Host: www.google.com\r\n"
8122 "Proxy-Connection: keep-alive\r\n\r\n"),
8123 };
8124
8125 MockRead data_reads1[] = {
8126 MockRead("HTTP/1.1 200 OK\r\n"),
8127 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8128 MockRead("Content-Length: 100\r\n\r\n"),
8129 MockRead(false, OK),
8130 };
8131
8132 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8133 data_writes1, arraysize(data_writes1));
8134 session_deps.socket_factory.AddSocketDataProvider(&data1);
8135
8136 TestCompletionCallback callback1;
8137
[email protected]0b0bf032010-09-21 18:08:508138 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8139
[email protected]76a505b2010-08-25 06:23:008140 int rv = trans->Start(&request, &callback1, log.bound());
8141 EXPECT_EQ(ERR_IO_PENDING, rv);
8142
8143 rv = callback1.WaitForResult();
8144 EXPECT_EQ(OK, rv);
8145
8146 const HttpResponseInfo* response = trans->GetResponseInfo();
8147 ASSERT_FALSE(response == NULL);
8148
8149 EXPECT_TRUE(response->headers->IsKeepAlive());
8150 EXPECT_EQ(200, response->headers->response_code());
8151 EXPECT_EQ(100, response->headers->GetContentLength());
8152 EXPECT_TRUE(response->was_fetched_via_proxy);
8153 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8154}
8155
8156// Test a basic HTTPS GET request through a proxy.
8157TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008158 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008159 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8160 session_deps.net_log = log.bound().net_log();
8161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8162
[email protected]76a505b2010-08-25 06:23:008163 HttpRequestInfo request;
8164 request.method = "GET";
8165 request.url = GURL("https://www.google.com/");
8166
8167 // Since we have proxy, should try to establish tunnel.
8168 MockWrite data_writes1[] = {
8169 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8170 "Host: www.google.com\r\n"
8171 "Proxy-Connection: keep-alive\r\n\r\n"),
8172
8173 MockWrite("GET / HTTP/1.1\r\n"
8174 "Host: www.google.com\r\n"
8175 "Connection: keep-alive\r\n\r\n"),
8176 };
8177
8178 MockRead data_reads1[] = {
8179 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8180
8181 MockRead("HTTP/1.1 200 OK\r\n"),
8182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8183 MockRead("Content-Length: 100\r\n\r\n"),
8184 MockRead(false, OK),
8185 };
8186
8187 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8188 data_writes1, arraysize(data_writes1));
8189 session_deps.socket_factory.AddSocketDataProvider(&data1);
8190 SSLSocketDataProvider ssl(true, OK);
8191 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8192
8193 TestCompletionCallback callback1;
8194
[email protected]0b0bf032010-09-21 18:08:508195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8196
[email protected]76a505b2010-08-25 06:23:008197 int rv = trans->Start(&request, &callback1, log.bound());
8198 EXPECT_EQ(ERR_IO_PENDING, rv);
8199
8200 rv = callback1.WaitForResult();
8201 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408202 net::CapturingNetLog::EntryList entries;
8203 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008204 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408205 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008206 NetLog::PHASE_NONE);
8207 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408208 entries, pos,
[email protected]76a505b2010-08-25 06:23:008209 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8210 NetLog::PHASE_NONE);
8211
8212 const HttpResponseInfo* response = trans->GetResponseInfo();
8213 ASSERT_FALSE(response == NULL);
8214
8215 EXPECT_TRUE(response->headers->IsKeepAlive());
8216 EXPECT_EQ(200, response->headers->response_code());
8217 EXPECT_EQ(100, response->headers->GetContentLength());
8218 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8219 EXPECT_TRUE(response->was_fetched_via_proxy);
8220}
8221
8222// Test a basic HTTPS GET request through a proxy, but the server hangs up
8223// while establishing the tunnel.
8224TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008225 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008226 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8227 session_deps.net_log = log.bound().net_log();
8228 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8229
[email protected]76a505b2010-08-25 06:23:008230 HttpRequestInfo request;
8231 request.method = "GET";
8232 request.url = GURL("https://www.google.com/");
8233
8234 // Since we have proxy, should try to establish tunnel.
8235 MockWrite data_writes1[] = {
8236 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8237 "Host: www.google.com\r\n"
8238 "Proxy-Connection: keep-alive\r\n\r\n"),
8239
8240 MockWrite("GET / HTTP/1.1\r\n"
8241 "Host: www.google.com\r\n"
8242 "Connection: keep-alive\r\n\r\n"),
8243 };
8244
8245 MockRead data_reads1[] = {
8246 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8247 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8248 MockRead(true, 0, 0), // EOF
8249 };
8250
8251 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8252 data_writes1, arraysize(data_writes1));
8253 session_deps.socket_factory.AddSocketDataProvider(&data1);
8254 SSLSocketDataProvider ssl(true, OK);
8255 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8256
8257 TestCompletionCallback callback1;
8258
[email protected]0b0bf032010-09-21 18:08:508259 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8260
[email protected]76a505b2010-08-25 06:23:008261 int rv = trans->Start(&request, &callback1, log.bound());
8262 EXPECT_EQ(ERR_IO_PENDING, rv);
8263
8264 rv = callback1.WaitForResult();
8265 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408266 net::CapturingNetLog::EntryList entries;
8267 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008268 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408269 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008270 NetLog::PHASE_NONE);
8271 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408272 entries, pos,
[email protected]76a505b2010-08-25 06:23:008273 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8274 NetLog::PHASE_NONE);
8275}
8276
[email protected]749eefa82010-09-13 22:14:038277// Test for crbug.com/55424.
8278TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8279 SessionDependencies session_deps;
8280
8281 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8282 "https://www.google.com", false, 1, LOWEST));
8283 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8284
8285 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8286 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8287 MockRead spdy_reads[] = {
8288 CreateMockRead(*resp),
8289 CreateMockRead(*data),
8290 MockRead(true, 0, 0),
8291 };
8292
8293 scoped_refptr<DelayedSocketData> spdy_data(
8294 new DelayedSocketData(
8295 1, // wait for one write to finish before reading.
8296 spdy_reads, arraysize(spdy_reads),
8297 spdy_writes, arraysize(spdy_writes)));
8298 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8299
8300 SSLSocketDataProvider ssl(true, OK);
8301 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8302 ssl.next_proto = "spdy/2";
8303 ssl.was_npn_negotiated = true;
8304 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8305
8306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8307
8308 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388309 HostPortPair host_port_pair("www.google.com", 443);
8310 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038311 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318312 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288313 scoped_refptr<TransportSocketParams> transport_params(
8314 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:388315 TestCompletionCallback callback;
8316
8317 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8318 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288319 connection->Init(host_port_pair.ToString(), transport_params,
8320 LOWEST, &callback,
8321 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388322 EXPECT_EQ(OK, callback.WaitForResult());
8323 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038324
8325 HttpRequestInfo request;
8326 request.method = "GET";
8327 request.url = GURL("https://www.google.com/");
8328 request.load_flags = 0;
8329
8330 // This is the important line that marks this as a preconnect.
8331 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8332
8333 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8334
[email protected]749eefa82010-09-13 22:14:038335 int rv = trans->Start(&request, &callback, BoundNetLog());
8336 EXPECT_EQ(ERR_IO_PENDING, rv);
8337 EXPECT_EQ(OK, callback.WaitForResult());
8338}
8339
[email protected]73b8dd222010-11-11 19:55:248340// Given a net error, cause that error to be returned from the first Write()
8341// call and verify that the HttpTransaction fails with that error.
8342static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278343 net::HttpRequestInfo request_info;
8344 request_info.url = GURL("https://www.example.com/");
8345 request_info.method = "GET";
8346 request_info.load_flags = net::LOAD_NORMAL;
8347
[email protected]73b8dd222010-11-11 19:55:248348 SessionDependencies session_deps;
8349
8350 SSLSocketDataProvider ssl_data(async, OK);
8351 net::MockWrite data_writes[] = {
8352 net::MockWrite(async, error),
8353 };
8354 net::StaticSocketDataProvider data(NULL, 0,
8355 data_writes, arraysize(data_writes));
8356 session_deps.socket_factory.AddSocketDataProvider(&data);
8357 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8358
8359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8360 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8361
[email protected]73b8dd222010-11-11 19:55:248362 TestCompletionCallback callback;
8363 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8364 if (rv == net::ERR_IO_PENDING)
8365 rv = callback.WaitForResult();
8366 ASSERT_EQ(error, rv);
8367}
8368
8369TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8370 // Just check a grab bag of cert errors.
8371 static const int kErrors[] = {
8372 ERR_CERT_COMMON_NAME_INVALID,
8373 ERR_CERT_AUTHORITY_INVALID,
8374 ERR_CERT_DATE_INVALID,
8375 };
8376 for (size_t i = 0; i < arraysize(kErrors); i++) {
8377 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8378 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8379 }
8380}
8381
[email protected]bd0b6772011-01-11 19:59:308382// Ensure that a client certificate is removed from the SSL client auth
8383// cache when:
8384// 1) No proxy is involved.
8385// 2) TLS False Start is disabled.
8386// 3) The initial TLS handshake requests a client certificate.
8387// 4) The client supplies an invalid/unacceptable certificate.
8388TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278389 net::HttpRequestInfo request_info;
8390 request_info.url = GURL("https://www.example.com/");
8391 request_info.method = "GET";
8392 request_info.load_flags = net::LOAD_NORMAL;
8393
[email protected]bd0b6772011-01-11 19:59:308394 SessionDependencies session_deps;
8395
8396 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8397 cert_request->host_and_port = "www.example.com:443";
8398
8399 // [ssl_]data1 contains the data for the first SSL handshake. When a
8400 // CertificateRequest is received for the first time, the handshake will
8401 // be aborted to allow the caller to provide a certificate.
8402 SSLSocketDataProvider ssl_data1(true /* async */,
8403 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8404 ssl_data1.cert_request_info = cert_request.get();
8405 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8406 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8407 session_deps.socket_factory.AddSocketDataProvider(&data1);
8408
8409 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8410 // False Start is not being used, the result of the SSL handshake will be
8411 // returned as part of the SSLClientSocket::Connect() call. This test
8412 // matches the result of a server sending a handshake_failure alert,
8413 // rather than a Finished message, because it requires a client
8414 // certificate and none was supplied.
8415 SSLSocketDataProvider ssl_data2(true /* async */,
8416 net::ERR_SSL_PROTOCOL_ERROR);
8417 ssl_data2.cert_request_info = cert_request.get();
8418 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8419 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8420 session_deps.socket_factory.AddSocketDataProvider(&data2);
8421
8422 // [ssl_]data3 contains the data for the third SSL handshake. When a
8423 // connection to a server fails during an SSL handshake,
8424 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8425 // connection was attempted with TLSv1. This is transparent to the caller
8426 // of the HttpNetworkTransaction. Because this test failure is due to
8427 // requiring a client certificate, this fallback handshake should also
8428 // fail.
8429 SSLSocketDataProvider ssl_data3(true /* async */,
8430 net::ERR_SSL_PROTOCOL_ERROR);
8431 ssl_data3.cert_request_info = cert_request.get();
8432 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8433 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8434 session_deps.socket_factory.AddSocketDataProvider(&data3);
8435
8436 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8437 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8438
[email protected]bd0b6772011-01-11 19:59:308439 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8440 TestCompletionCallback callback;
8441 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8442 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8443
8444 // Complete the SSL handshake, which should abort due to requiring a
8445 // client certificate.
8446 rv = callback.WaitForResult();
8447 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8448
8449 // Indicate that no certificate should be supplied. From the perspective
8450 // of SSLClientCertCache, NULL is just as meaningful as a real
8451 // certificate, so this is the same as supply a
8452 // legitimate-but-unacceptable certificate.
8453 rv = trans->RestartWithCertificate(NULL, &callback);
8454 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8455
8456 // Ensure the certificate was added to the client auth cache before
8457 // allowing the connection to continue restarting.
8458 scoped_refptr<X509Certificate> client_cert;
8459 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8460 &client_cert));
8461 ASSERT_EQ(NULL, client_cert.get());
8462
8463 // Restart the handshake. This will consume ssl_data2, which fails, and
8464 // then consume ssl_data3, which should also fail. The result code is
8465 // checked against what ssl_data3 should return.
8466 rv = callback.WaitForResult();
8467 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8468
8469 // Ensure that the client certificate is removed from the cache on a
8470 // handshake failure.
8471 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8472 &client_cert));
8473}
8474
8475// Ensure that a client certificate is removed from the SSL client auth
8476// cache when:
8477// 1) No proxy is involved.
8478// 2) TLS False Start is enabled.
8479// 3) The initial TLS handshake requests a client certificate.
8480// 4) The client supplies an invalid/unacceptable certificate.
8481TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278482 net::HttpRequestInfo request_info;
8483 request_info.url = GURL("https://www.example.com/");
8484 request_info.method = "GET";
8485 request_info.load_flags = net::LOAD_NORMAL;
8486
[email protected]bd0b6772011-01-11 19:59:308487 SessionDependencies session_deps;
8488
8489 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8490 cert_request->host_and_port = "www.example.com:443";
8491
8492 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8493 // return successfully after reading up to the peer's Certificate message.
8494 // This is to allow the caller to call SSLClientSocket::Write(), which can
8495 // enqueue application data to be sent in the same packet as the
8496 // ChangeCipherSpec and Finished messages.
8497 // The actual handshake will be finished when SSLClientSocket::Read() is
8498 // called, which expects to process the peer's ChangeCipherSpec and
8499 // Finished messages. If there was an error negotiating with the peer,
8500 // such as due to the peer requiring a client certificate when none was
8501 // supplied, the alert sent by the peer won't be processed until Read() is
8502 // called.
8503
8504 // Like the non-False Start case, when a client certificate is requested by
8505 // the peer, the handshake is aborted during the Connect() call.
8506 // [ssl_]data1 represents the initial SSL handshake with the peer.
8507 SSLSocketDataProvider ssl_data1(true /* async */,
8508 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8509 ssl_data1.cert_request_info = cert_request.get();
8510 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8511 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8512 session_deps.socket_factory.AddSocketDataProvider(&data1);
8513
8514 // When a client certificate is supplied, Connect() will not be aborted
8515 // when the peer requests the certificate. Instead, the handshake will
8516 // artificially succeed, allowing the caller to write the HTTP request to
8517 // the socket. The handshake messages are not processed until Read() is
8518 // called, which then detects that the handshake was aborted, due to the
8519 // peer sending a handshake_failure because it requires a client
8520 // certificate.
8521 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8522 ssl_data2.cert_request_info = cert_request.get();
8523 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8524 net::MockRead data2_reads[] = {
8525 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8526 };
8527 net::StaticSocketDataProvider data2(
8528 data2_reads, arraysize(data2_reads), NULL, 0);
8529 session_deps.socket_factory.AddSocketDataProvider(&data2);
8530
8531 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8532 // the data for the SSL handshake once the TLSv1 connection falls back to
8533 // SSLv3. It has the same behaviour as [ssl_]data2.
8534 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8535 ssl_data3.cert_request_info = cert_request.get();
8536 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8537 net::StaticSocketDataProvider data3(
8538 data2_reads, arraysize(data2_reads), NULL, 0);
8539 session_deps.socket_factory.AddSocketDataProvider(&data3);
8540
8541 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8542 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8543
[email protected]bd0b6772011-01-11 19:59:308544 // Begin the initial SSL handshake.
8545 TestCompletionCallback callback;
8546 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8547 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8548
8549 // Complete the SSL handshake, which should abort due to requiring a
8550 // client certificate.
8551 rv = callback.WaitForResult();
8552 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8553
8554 // Indicate that no certificate should be supplied. From the perspective
8555 // of SSLClientCertCache, NULL is just as meaningful as a real
8556 // certificate, so this is the same as supply a
8557 // legitimate-but-unacceptable certificate.
8558 rv = trans->RestartWithCertificate(NULL, &callback);
8559 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8560
8561 // Ensure the certificate was added to the client auth cache before
8562 // allowing the connection to continue restarting.
8563 scoped_refptr<X509Certificate> client_cert;
8564 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8565 &client_cert));
8566 ASSERT_EQ(NULL, client_cert.get());
8567
8568
8569 // Restart the handshake. This will consume ssl_data2, which fails, and
8570 // then consume ssl_data3, which should also fail. The result code is
8571 // checked against what ssl_data3 should return.
8572 rv = callback.WaitForResult();
8573 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8574
8575 // Ensure that the client certificate is removed from the cache on a
8576 // handshake failure.
8577 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8578 &client_cert));
8579}
8580
[email protected]8c405132011-01-11 22:03:188581// Ensure that a client certificate is removed from the SSL client auth
8582// cache when:
8583// 1) An HTTPS proxy is involved.
8584// 3) The HTTPS proxy requests a client certificate.
8585// 4) The client supplies an invalid/unacceptable certificate for the
8586// proxy.
8587// The test is repeated twice, first for connecting to an HTTPS endpoint,
8588// then for connecting to an HTTP endpoint.
8589TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8590 SessionDependencies session_deps(
8591 ProxyService::CreateFixed("https://proxy:70"));
8592 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8593 session_deps.net_log = log.bound().net_log();
8594
8595 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8596 cert_request->host_and_port = "proxy:70";
8597
8598 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8599 // [ssl_]data[1-3]. Rather than represending the endpoint
8600 // (www.example.com:443), they represent failures with the HTTPS proxy
8601 // (proxy:70).
8602 SSLSocketDataProvider ssl_data1(true /* async */,
8603 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8604 ssl_data1.cert_request_info = cert_request.get();
8605 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8606 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8607 session_deps.socket_factory.AddSocketDataProvider(&data1);
8608
8609 SSLSocketDataProvider ssl_data2(true /* async */,
8610 net::ERR_SSL_PROTOCOL_ERROR);
8611 ssl_data2.cert_request_info = cert_request.get();
8612 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8613 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8614 session_deps.socket_factory.AddSocketDataProvider(&data2);
8615
8616 SSLSocketDataProvider ssl_data3(true /* async */,
8617 net::ERR_SSL_PROTOCOL_ERROR);
8618 ssl_data3.cert_request_info = cert_request.get();
8619 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8620 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8621 session_deps.socket_factory.AddSocketDataProvider(&data3);
8622
8623 net::HttpRequestInfo requests[2];
8624 requests[0].url = GURL("https://www.example.com/");
8625 requests[0].method = "GET";
8626 requests[0].load_flags = net::LOAD_NORMAL;
8627
8628 requests[1].url = GURL("http://www.example.com/");
8629 requests[1].method = "GET";
8630 requests[1].load_flags = net::LOAD_NORMAL;
8631
8632 for (size_t i = 0; i < arraysize(requests); ++i) {
8633 session_deps.socket_factory.ResetNextMockIndexes();
8634 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8635 scoped_ptr<HttpNetworkTransaction> trans(
8636 new HttpNetworkTransaction(session));
8637
8638 // Begin the SSL handshake with the proxy.
8639 TestCompletionCallback callback;
8640 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8641 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8642
8643 // Complete the SSL handshake, which should abort due to requiring a
8644 // client certificate.
8645 rv = callback.WaitForResult();
8646 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8647
8648 // Indicate that no certificate should be supplied. From the perspective
8649 // of SSLClientCertCache, NULL is just as meaningful as a real
8650 // certificate, so this is the same as supply a
8651 // legitimate-but-unacceptable certificate.
8652 rv = trans->RestartWithCertificate(NULL, &callback);
8653 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8654
8655 // Ensure the certificate was added to the client auth cache before
8656 // allowing the connection to continue restarting.
8657 scoped_refptr<X509Certificate> client_cert;
8658 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8659 &client_cert));
8660 ASSERT_EQ(NULL, client_cert.get());
8661 // Ensure the certificate was NOT cached for the endpoint. This only
8662 // applies to HTTPS requests, but is fine to check for HTTP requests.
8663 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8664 &client_cert));
8665
8666 // Restart the handshake. This will consume ssl_data2, which fails, and
8667 // then consume ssl_data3, which should also fail. The result code is
8668 // checked against what ssl_data3 should return.
8669 rv = callback.WaitForResult();
8670 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8671
8672 // Now that the new handshake has failed, ensure that the client
8673 // certificate was removed from the client auth cache.
8674 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8675 &client_cert));
8676 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8677 &client_cert));
8678 }
8679}
8680
[email protected]5c288bc2011-07-26 15:12:058681void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8682 SpdySessionPoolPeer* pool_peer,
8683 std::string host,
8684 int port,
8685 std::string iplist) {
8686 // Create a host resolver dependency that returns address |iplist| for
8687 // resolutions of |host|.
8688 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048689
[email protected]5c288bc2011-07-26 15:12:058690 // Setup a HostPortProxyPair.
8691 HostPortPair host_port_pair(host, port);
8692 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8693 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048694
[email protected]5c288bc2011-07-26 15:12:058695 // Resolve the host and port.
8696 AddressList addresses;
8697 HostResolver::RequestInfo info(host_port_pair);
[email protected]6e78dfb2011-07-28 21:34:478698 TestCompletionCallback callback;
8699 int rv = host_resolver->Resolve(info, &addresses, &callback, NULL,
8700 BoundNetLog());
8701 if (rv == ERR_IO_PENDING)
8702 rv = callback.WaitForResult();
8703 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:048704
[email protected]5c288bc2011-07-26 15:12:058705 // Add the first address as an alias. It would have been better to call
8706 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8707 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8708 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8709 // the |pair|.
8710 const addrinfo* address = addresses.head();
8711 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048712}
8713
[email protected]e3ceb682011-06-28 23:55:468714TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8715 HttpStreamFactory::set_use_alternate_protocols(true);
8716 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]e3ceb682011-06-28 23:55:468717
8718 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8719 SessionDependencies session_deps;
8720 MockCachingHostResolver host_resolver;
8721 net::HttpNetworkSession::Params params;
8722 params.client_socket_factory = &session_deps.socket_factory;
8723 params.host_resolver = &host_resolver;
8724 params.cert_verifier = session_deps.cert_verifier.get();
8725 params.proxy_service = session_deps.proxy_service.get();
8726 params.ssl_config_service = session_deps.ssl_config_service;
8727 params.http_auth_handler_factory =
8728 session_deps.http_auth_handler_factory.get();
8729 params.net_log = session_deps.net_log;
8730 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268731 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8732 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468733
8734 SSLSocketDataProvider ssl(true, OK);
8735 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8736 ssl.next_proto = "spdy/2";
8737 ssl.was_npn_negotiated = true;
8738 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8739
8740 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8741 "https://www.google.com", false, 1, LOWEST));
8742 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8743 "https://www.gmail.com", false, 3, LOWEST));
8744 MockWrite spdy_writes[] = {
8745 CreateMockWrite(*host1_req, 1),
8746 CreateMockWrite(*host2_req, 4),
8747 };
8748 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8749 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8750 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8751 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8752 MockRead spdy_reads[] = {
8753 CreateMockRead(*host1_resp, 2),
8754 CreateMockRead(*host1_resp_body, 3),
8755 CreateMockRead(*host2_resp, 5),
8756 CreateMockRead(*host2_resp_body, 6),
8757 MockRead(true, 0, 7),
8758 };
8759
8760 scoped_refptr<OrderedSocketData> spdy_data(
8761 new OrderedSocketData(
8762 spdy_reads, arraysize(spdy_reads),
8763 spdy_writes, arraysize(spdy_writes)));
8764 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8765
8766 TestCompletionCallback callback;
8767 HttpRequestInfo request1;
8768 request1.method = "GET";
8769 request1.url = GURL("https://www.google.com/");
8770 request1.load_flags = 0;
8771 HttpNetworkTransaction trans1(session);
8772
8773 int rv = trans1.Start(&request1, &callback, BoundNetLog());
8774 EXPECT_EQ(ERR_IO_PENDING, rv);
8775 EXPECT_EQ(OK, callback.WaitForResult());
8776
8777 const HttpResponseInfo* response = trans1.GetResponseInfo();
8778 ASSERT_TRUE(response != NULL);
8779 ASSERT_TRUE(response->headers != NULL);
8780 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8781
8782 std::string response_data;
8783 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8784 EXPECT_EQ("hello!", response_data);
8785
8786 // Preload www.gmail.com into HostCache.
8787 HostPortPair host_port("www.gmail.com", 443);
8788 HostResolver::RequestInfo resolve_info(host_port);
8789 AddressList ignored;
[email protected]6e78dfb2011-07-28 21:34:478790 rv = host_resolver.Resolve(resolve_info, &ignored, &callback, NULL,
8791 BoundNetLog());
8792 EXPECT_EQ(ERR_IO_PENDING, rv);
8793 rv = callback.WaitForResult();
8794 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:468795
[email protected]5c288bc2011-07-26 15:12:058796 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
8797 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
8798 // (www.google.com, 443).
8799 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
8800 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:048801
[email protected]e3ceb682011-06-28 23:55:468802 HttpRequestInfo request2;
8803 request2.method = "GET";
8804 request2.url = GURL("https://www.gmail.com/");
8805 request2.load_flags = 0;
8806 HttpNetworkTransaction trans2(session);
8807
8808 rv = trans2.Start(&request2, &callback, BoundNetLog());
8809 EXPECT_EQ(ERR_IO_PENDING, rv);
8810 EXPECT_EQ(OK, callback.WaitForResult());
8811
8812 response = trans2.GetResponseInfo();
8813 ASSERT_TRUE(response != NULL);
8814 ASSERT_TRUE(response->headers != NULL);
8815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8816 EXPECT_TRUE(response->was_fetched_via_spdy);
8817 EXPECT_TRUE(response->was_npn_negotiated);
8818 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8819 EXPECT_EQ("hello!", response_data);
8820
8821 HttpStreamFactory::set_next_protos("");
8822 HttpStreamFactory::set_use_alternate_protocols(false);
8823}
8824
8825class OneTimeCachingHostResolver : public net::HostResolver {
8826 public:
8827 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
8828 : host_port_(host_port) {}
8829 virtual ~OneTimeCachingHostResolver() {}
8830
8831 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
8832
8833 // HostResolver methods:
8834 virtual int Resolve(const RequestInfo& info,
8835 AddressList* addresses,
8836 CompletionCallback* callback,
8837 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:408838 const BoundNetLog& net_log) OVERRIDE {
8839 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:468840 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:408841 }
8842
8843 virtual int ResolveFromCache(const RequestInfo& info,
8844 AddressList* addresses,
8845 const BoundNetLog& net_log) OVERRIDE {
8846 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
8847 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]e3ceb682011-06-28 23:55:468848 host_resolver_.Reset(NULL);
[email protected]e3ceb682011-06-28 23:55:468849 return rv;
8850 }
8851
[email protected]95a214c2011-08-04 21:50:408852 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:468853 host_resolver_.CancelRequest(req);
8854 }
8855
[email protected]95a214c2011-08-04 21:50:408856 virtual void AddObserver(Observer* observer) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:468857 return host_resolver_.AddObserver(observer);
8858 }
8859
[email protected]95a214c2011-08-04 21:50:408860 virtual void RemoveObserver(Observer* observer) OVERRIDE{
[email protected]e3ceb682011-06-28 23:55:468861 return host_resolver_.RemoveObserver(observer);
8862 }
8863
[email protected]46da33be2011-07-19 21:58:048864 MockCachingHostResolver* GetMockHostResolver() {
8865 return &host_resolver_;
8866 }
8867
[email protected]e3ceb682011-06-28 23:55:468868 private:
8869 MockCachingHostResolver host_resolver_;
8870 const HostPortPair host_port_;
8871};
8872
8873TEST_F(HttpNetworkTransactionTest,
8874 UseIPConnectionPoolingWithHostCacheExpiration) {
8875 HttpStreamFactory::set_use_alternate_protocols(true);
8876 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]e3ceb682011-06-28 23:55:468877
8878 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
8879 SessionDependencies session_deps;
8880 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
8881 net::HttpNetworkSession::Params params;
8882 params.client_socket_factory = &session_deps.socket_factory;
8883 params.host_resolver = &host_resolver;
8884 params.cert_verifier = session_deps.cert_verifier.get();
8885 params.proxy_service = session_deps.proxy_service.get();
8886 params.ssl_config_service = session_deps.ssl_config_service;
8887 params.http_auth_handler_factory =
8888 session_deps.http_auth_handler_factory.get();
8889 params.net_log = session_deps.net_log;
8890 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268891 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8892 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468893
8894 SSLSocketDataProvider ssl(true, OK);
8895 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8896 ssl.next_proto = "spdy/2";
8897 ssl.was_npn_negotiated = true;
8898 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8899
8900 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8901 "https://www.google.com", false, 1, LOWEST));
8902 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8903 "https://www.gmail.com", false, 3, LOWEST));
8904 MockWrite spdy_writes[] = {
8905 CreateMockWrite(*host1_req, 1),
8906 CreateMockWrite(*host2_req, 4),
8907 };
8908 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8909 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8910 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8911 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8912 MockRead spdy_reads[] = {
8913 CreateMockRead(*host1_resp, 2),
8914 CreateMockRead(*host1_resp_body, 3),
8915 CreateMockRead(*host2_resp, 5),
8916 CreateMockRead(*host2_resp_body, 6),
8917 MockRead(true, 0, 7),
8918 };
8919
8920 scoped_refptr<OrderedSocketData> spdy_data(
8921 new OrderedSocketData(
8922 spdy_reads, arraysize(spdy_reads),
8923 spdy_writes, arraysize(spdy_writes)));
8924 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8925
8926 TestCompletionCallback callback;
8927 HttpRequestInfo request1;
8928 request1.method = "GET";
8929 request1.url = GURL("https://www.google.com/");
8930 request1.load_flags = 0;
8931 HttpNetworkTransaction trans1(session);
8932
8933 int rv = trans1.Start(&request1, &callback, BoundNetLog());
8934 EXPECT_EQ(ERR_IO_PENDING, rv);
8935 EXPECT_EQ(OK, callback.WaitForResult());
8936
8937 const HttpResponseInfo* response = trans1.GetResponseInfo();
8938 ASSERT_TRUE(response != NULL);
8939 ASSERT_TRUE(response->headers != NULL);
8940 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8941
8942 std::string response_data;
8943 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8944 EXPECT_EQ("hello!", response_data);
8945
8946 // Preload cache entries into HostCache.
8947 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
8948 AddressList ignored;
[email protected]6e78dfb2011-07-28 21:34:478949 rv = host_resolver.Resolve(resolve_info, &ignored, &callback, NULL,
8950 BoundNetLog());
8951 EXPECT_EQ(ERR_IO_PENDING, rv);
8952 rv = callback.WaitForResult();
8953 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:468954
8955 HttpRequestInfo request2;
8956 request2.method = "GET";
8957 request2.url = GURL("https://www.gmail.com/");
8958 request2.load_flags = 0;
8959 HttpNetworkTransaction trans2(session);
8960
[email protected]5c288bc2011-07-26 15:12:058961 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
8962 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
8963 // (www.google.com, 443).
8964 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
8965 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:048966
[email protected]e3ceb682011-06-28 23:55:468967 rv = trans2.Start(&request2, &callback, BoundNetLog());
8968 EXPECT_EQ(ERR_IO_PENDING, rv);
8969 EXPECT_EQ(OK, callback.WaitForResult());
8970
8971 response = trans2.GetResponseInfo();
8972 ASSERT_TRUE(response != NULL);
8973 ASSERT_TRUE(response->headers != NULL);
8974 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8975 EXPECT_TRUE(response->was_fetched_via_spdy);
8976 EXPECT_TRUE(response->was_npn_negotiated);
8977 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8978 EXPECT_EQ("hello!", response_data);
8979
8980 HttpStreamFactory::set_next_protos("");
8981 HttpStreamFactory::set_use_alternate_protocols(false);
8982}
8983
[email protected]89ceba9a2009-03-21 03:46:068984} // namespace net