blob: ad41eac5d148c3c2657f6aecde519834d8bf54e5 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5632#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5733#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3834#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5235#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5336#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1137#include "net/proxy/proxy_resolver.h"
38#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4439#include "net/socket/client_socket_factory.h"
40#include "net/socket/socket_test_util.h"
41#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5442#include "net/spdy/spdy_framer.h"
43#include "net/spdy/spdy_session.h"
44#include "net/spdy/spdy_session_pool.h"
45#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5246#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1547#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5248
49//-----------------------------------------------------------------------------
50
[email protected]13c8a092010-07-29 06:15:4451namespace {
52
53const string16 kBar(ASCIIToUTF16("bar"));
54const string16 kBar2(ASCIIToUTF16("bar2"));
55const string16 kBar3(ASCIIToUTF16("bar3"));
56const string16 kBaz(ASCIIToUTF16("baz"));
57const string16 kFirst(ASCIIToUTF16("first"));
58const string16 kFoo(ASCIIToUTF16("foo"));
59const string16 kFoo2(ASCIIToUTF16("foo2"));
60const string16 kFoo3(ASCIIToUTF16("foo3"));
61const string16 kFou(ASCIIToUTF16("fou"));
62const string16 kSecond(ASCIIToUTF16("second"));
63const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
64const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
65
66} // namespace
67
[email protected]89ceba9a2009-03-21 03:46:0668namespace net {
69
[email protected]e44de5d2009-06-05 20:12:4570// Helper to manage the lifetimes of the dependencies for a
71// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4472struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5973 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4274 SessionDependencies()
75 : host_resolver(new MockHostResolver),
[email protected]ebeefff32010-09-15 05:10:0276 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1077 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0878 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5479 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5480 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5981
82 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4583 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4284 : host_resolver(new MockHostResolver),
85 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1086 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0887 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5488 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5489 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5990
[email protected]73c45322010-10-01 23:57:5491 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0992 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4293 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5994 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5095 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:5496 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:5997};
98
[email protected]1c773ea12009-04-28 19:58:4299ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50100 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48101 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39102 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53103}
104
[email protected]228ff742009-06-05 01:19:59105HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54106 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]80d6524d2009-08-18 03:58:09107 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42108 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10109 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56110 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17111 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44112 NULL,
[email protected]a7ea8832010-07-12 17:54:54113 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14114}
115
[email protected]89836e22008-09-25 20:33:42116class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52117 public:
[email protected]2ff8b312010-04-26 22:20:54118 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50119 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
120 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54121 spdy::SpdyFramer::set_enable_compression_default(false);
122 }
123
[email protected]0e75a732008-10-16 20:36:09124 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50125 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
126 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54127 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09128 // Empty the current queue.
129 MessageLoop::current()->RunAllPending();
130 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50131 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
132 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09133 }
134
[email protected]3d2a59b2008-09-26 19:44:25135 protected:
136 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52137
[email protected]ff007e162009-05-23 09:13:15138 struct SimpleGetHelperResult {
139 int rv;
140 std::string status_line;
141 std::string response_data;
142 };
initial.commit586acc5fe2008-07-26 22:42:52143
[email protected]31a2bfe2010-02-09 08:03:39144 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
145 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15146 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52147
[email protected]228ff742009-06-05 01:19:59148 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40149 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43150 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52151
[email protected]ff007e162009-05-23 09:13:15152 HttpRequestInfo request;
153 request.method = "GET";
154 request.url = GURL("http://www.google.com/");
155 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52156
[email protected]31a2bfe2010-02-09 08:03:39157 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59158 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52159
[email protected]ff007e162009-05-23 09:13:15160 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52161
[email protected]169d0012010-05-10 23:20:12162 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
163 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15164 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52165
[email protected]ff007e162009-05-23 09:13:15166 out.rv = callback.WaitForResult();
167 if (out.rv != OK)
168 return out;
169
170 const HttpResponseInfo* response = trans->GetResponseInfo();
171 EXPECT_TRUE(response != NULL);
172
173 EXPECT_TRUE(response->headers != NULL);
174 out.status_line = response->headers->GetStatusLine();
175
176 rv = ReadTransaction(trans.get(), &out.response_data);
177 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39178 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12179 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
180 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39181 ExpectLogContainsSomewhere(
182 log.entries(), pos,
183 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
184 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15185
[email protected]aecfbf22008-10-16 02:02:47186 return out;
[email protected]ff007e162009-05-23 09:13:15187 }
initial.commit586acc5fe2008-07-26 22:42:52188
[email protected]ff007e162009-05-23 09:13:15189 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
190 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52191
[email protected]ff007e162009-05-23 09:13:15192 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15193};
[email protected]231d5a32008-09-13 00:45:27194
[email protected]15a5ccf82008-10-23 19:57:43195// Fill |str| with a long header list that consumes >= |size| bytes.
196void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19197 const char* row =
198 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
199 const int sizeof_row = strlen(row);
200 const int num_rows = static_cast<int>(
201 ceil(static_cast<float>(size) / sizeof_row));
202 const int sizeof_data = num_rows * sizeof_row;
203 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43204 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51205
[email protected]4ddaf2502008-10-23 18:26:19206 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43207 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19208}
209
[email protected]385a4672009-03-11 22:21:29210// Alternative functions that eliminate randomness and dependency on the local
211// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20212void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29213 static const uint8 bytes[] = {
214 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
215 };
216 static size_t current_byte = 0;
217 for (size_t i = 0; i < n; ++i) {
218 output[i] = bytes[current_byte++];
219 current_byte %= arraysize(bytes);
220 }
221}
222
[email protected]fe2bc6a2009-03-23 16:52:20223void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29224 static const uint8 bytes[] = {
225 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
226 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
227 };
228 static size_t current_byte = 0;
229 for (size_t i = 0; i < n; ++i) {
230 output[i] = bytes[current_byte++];
231 current_byte %= arraysize(bytes);
232 }
233}
234
[email protected]fe2bc6a2009-03-23 16:52:20235std::string MockGetHostName() {
236 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29237}
238
[email protected]e60e47a2010-07-14 03:37:18239template<typename ParentPool>
240class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31241 public:
[email protected]e60e47a2010-07-14 03:37:18242 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
243
[email protected]d80a4322009-08-14 07:07:49244 const std::string last_group_name_received() const {
245 return last_group_name_;
246 }
247
[email protected]684970b2009-08-14 04:54:46248 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49249 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31250 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31251 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46252 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53253 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31254 last_group_name_ = group_name;
255 return ERR_IO_PENDING;
256 }
[email protected]04e5be32009-06-26 20:00:31257 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21258 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31259 virtual void ReleaseSocket(const std::string& group_name,
260 ClientSocket* socket) {}
261 virtual void CloseIdleSockets() {}
262 virtual HostResolver* GetHostResolver() const {
263 return NULL;
264 }
265 virtual int IdleSocketCount() const {
266 return 0;
267 }
268 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
269 return 0;
270 }
271 virtual LoadState GetLoadState(const std::string& group_name,
272 const ClientSocketHandle* handle) const {
273 return LOAD_STATE_IDLE;
274 }
[email protected]a796bcec2010-03-22 17:17:26275 virtual base::TimeDelta ConnectionTimeout() const {
276 return base::TimeDelta();
277 }
[email protected]d80a4322009-08-14 07:07:49278
279 private:
[email protected]04e5be32009-06-26 20:00:31280 std::string last_group_name_;
281};
282
[email protected]2d731a32010-04-29 01:04:06283typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11284CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13285typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
286CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06287typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11288CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18289typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
290CaptureGroupNameSSLSocketPool;
291
292template<typename ParentPool>
293CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
294 HttpNetworkSession* session)
295 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
296
297template<>
[email protected]2df19bb2010-08-25 20:13:46298CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
299 HttpNetworkSession* session)
300 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
301 NULL, NULL) {}
302
303template<>
[email protected]e60e47a2010-07-14 03:37:18304CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
305 HttpNetworkSession* session)
306 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
[email protected]7abf7d22010-09-04 01:41:59307 NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11308
[email protected]231d5a32008-09-13 00:45:27309//-----------------------------------------------------------------------------
310
[email protected]dae22c52010-07-30 02:16:35311// This is the expected list of advertised protocols from the browser's NPN
312// list.
313static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
314
315// This is the expected return from a current server advertising SPDY.
316static const char kAlternateProtocolHttpHeader[] =
317 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
318
[email protected]231d5a32008-09-13 00:45:27319TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59320 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40321 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43322 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27323}
324
325TEST_F(HttpNetworkTransactionTest, SimpleGET) {
326 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35327 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
328 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42329 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27330 };
[email protected]31a2bfe2010-02-09 08:03:39331 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
332 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42333 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27334 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
335 EXPECT_EQ("hello world", out.response_data);
336}
337
338// Response with no status line.
339TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
340 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35341 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42342 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27343 };
[email protected]31a2bfe2010-02-09 08:03:39344 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
345 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42346 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27347 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
348 EXPECT_EQ("hello world", out.response_data);
349}
350
351// Allow up to 4 bytes of junk to precede status line.
352TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
353 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35354 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42355 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27356 };
[email protected]31a2bfe2010-02-09 08:03:39357 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
358 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42359 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27360 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
361 EXPECT_EQ("DATA", out.response_data);
362}
363
364// Allow up to 4 bytes of junk to precede status line.
365TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
366 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35367 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42368 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27369 };
[email protected]31a2bfe2010-02-09 08:03:39370 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
371 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42372 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27373 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
374 EXPECT_EQ("DATA", out.response_data);
375}
376
377// Beyond 4 bytes of slop and it should fail to find a status line.
378TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
379 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35380 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42381 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27382 };
[email protected]31a2bfe2010-02-09 08:03:39383 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
384 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42385 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25386 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
387 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27388}
389
390// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
391TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
392 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35393 MockRead("\n"),
394 MockRead("\n"),
395 MockRead("Q"),
396 MockRead("J"),
397 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42398 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27399 };
[email protected]31a2bfe2010-02-09 08:03:39400 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
401 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42402 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27403 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
404 EXPECT_EQ("DATA", out.response_data);
405}
406
407// Close the connection before enough bytes to have a status line.
408TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
409 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35410 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42411 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27412 };
[email protected]31a2bfe2010-02-09 08:03:39413 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
414 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42415 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27416 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
417 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52418}
419
[email protected]f9d44aa2008-09-23 23:57:17420// Simulate a 204 response, lacking a Content-Length header, sent over a
421// persistent connection. The response should still terminate since a 204
422// cannot have a response body.
423TEST_F(HttpNetworkTransactionTest, StopsReading204) {
424 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35425 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
426 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42427 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17428 };
[email protected]31a2bfe2010-02-09 08:03:39429 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
430 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42431 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17432 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
433 EXPECT_EQ("", out.response_data);
434}
435
[email protected]0877e3d2009-10-17 22:29:57436// A simple request using chunked encoding with some extra data after.
437// (Like might be seen in a pipelined response.)
438TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
439 MockRead data_reads[] = {
440 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
441 MockRead("5\r\nHello\r\n"),
442 MockRead("1\r\n"),
443 MockRead(" \r\n"),
444 MockRead("5\r\nworld\r\n"),
445 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
446 MockRead(false, OK),
447 };
[email protected]31a2bfe2010-02-09 08:03:39448 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
449 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57450 EXPECT_EQ(OK, out.rv);
451 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
452 EXPECT_EQ("Hello world", out.response_data);
453}
454
[email protected]9fe44f52010-09-23 18:36:00455// Next tests deal with http://crbug.com/56344.
456
457TEST_F(HttpNetworkTransactionTest,
458 MultipleContentLengthHeadersNoTransferEncoding) {
459 MockRead data_reads[] = {
460 MockRead("HTTP/1.1 200 OK\r\n"),
461 MockRead("Content-Length: 10\r\n"),
462 MockRead("Content-Length: 5\r\n\r\n"),
463 };
464 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
465 arraysize(data_reads));
466 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
467}
468
469TEST_F(HttpNetworkTransactionTest,
470 MultipleContentLengthHeadersTransferEncoding) {
471 MockRead data_reads[] = {
472 MockRead("HTTP/1.1 200 OK\r\n"),
473 MockRead("Content-Length: 666\r\n"),
474 MockRead("Content-Length: 1337\r\n"),
475 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
476 MockRead("5\r\nHello\r\n"),
477 MockRead("1\r\n"),
478 MockRead(" \r\n"),
479 MockRead("5\r\nworld\r\n"),
480 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
481 MockRead(false, OK),
482 };
483 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
484 arraysize(data_reads));
485 EXPECT_EQ(OK, out.rv);
486 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
487 EXPECT_EQ("Hello world", out.response_data);
488}
489
[email protected]ef0faf2e72009-03-05 23:27:23490// Do a request using the HEAD method. Verify that we don't try to read the
491// message body (since HEAD has none).
492TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59493 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40494 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43495 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23496
[email protected]1c773ea12009-04-28 19:58:42497 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23498 request.method = "HEAD";
499 request.url = GURL("http://www.google.com/");
500 request.load_flags = 0;
501
502 MockWrite data_writes1[] = {
503 MockWrite("HEAD / HTTP/1.1\r\n"
504 "Host: www.google.com\r\n"
505 "Connection: keep-alive\r\n"
506 "Content-Length: 0\r\n\r\n"),
507 };
508 MockRead data_reads1[] = {
509 MockRead("HTTP/1.1 404 Not Found\r\n"),
510 MockRead("Server: Blah\r\n"),
511 MockRead("Content-Length: 1234\r\n\r\n"),
512
513 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42514 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23515 };
516
[email protected]31a2bfe2010-02-09 08:03:39517 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
518 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59519 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23520
521 TestCompletionCallback callback1;
522
[email protected]5a1d7ca2010-04-28 20:12:27523 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42524 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23525
526 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42527 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23528
[email protected]1c773ea12009-04-28 19:58:42529 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23530 EXPECT_FALSE(response == NULL);
531
532 // Check that the headers got parsed.
533 EXPECT_TRUE(response->headers != NULL);
534 EXPECT_EQ(1234, response->headers->GetContentLength());
535 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
536
537 std::string server_header;
538 void* iter = NULL;
539 bool has_server_header = response->headers->EnumerateHeader(
540 &iter, "Server", &server_header);
541 EXPECT_TRUE(has_server_header);
542 EXPECT_EQ("Blah", server_header);
543
544 // Reading should give EOF right away, since there is no message body
545 // (despite non-zero content-length).
546 std::string response_data;
547 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42548 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23549 EXPECT_EQ("", response_data);
550}
551
initial.commit586acc5fe2008-07-26 22:42:52552TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59553 SessionDependencies session_deps;
554 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52555
556 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35557 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
558 MockRead("hello"),
559 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
560 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42561 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52562 };
[email protected]31a2bfe2010-02-09 08:03:39563 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59564 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52565
[email protected]0b0bf032010-09-21 18:08:50566 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52567 "hello", "world"
568 };
569
570 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43571 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52572
[email protected]1c773ea12009-04-28 19:58:42573 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52574 request.method = "GET";
575 request.url = GURL("http://www.google.com/");
576 request.load_flags = 0;
577
578 TestCompletionCallback callback;
579
[email protected]5a1d7ca2010-04-28 20:12:27580 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42581 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52582
583 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42584 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52585
[email protected]1c773ea12009-04-28 19:58:42586 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52587 EXPECT_TRUE(response != NULL);
588
589 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25590 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52591
592 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57593 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42594 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25595 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52596 }
597}
598
599TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59600 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40601 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43602 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52603
[email protected]1c773ea12009-04-28 19:58:42604 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52605 request.method = "POST";
606 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42607 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52608 request.upload_data->AppendBytes("foo", 3);
609 request.load_flags = 0;
610
611 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35612 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
613 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
614 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42615 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52616 };
[email protected]31a2bfe2010-02-09 08:03:39617 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59618 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52619
620 TestCompletionCallback callback;
621
[email protected]5a1d7ca2010-04-28 20:12:27622 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42623 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52624
625 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42626 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52627
[email protected]1c773ea12009-04-28 19:58:42628 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52629 EXPECT_TRUE(response != NULL);
630
631 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25632 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52633
634 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57635 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42636 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25637 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52638}
639
[email protected]3a2d3662009-03-27 03:49:14640// This test is almost the same as Ignores100 above, but the response contains
641// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57642// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14643TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59644 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40645 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43646 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14647
[email protected]1c773ea12009-04-28 19:58:42648 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14649 request.method = "GET";
650 request.url = GURL("http://www.foo.com/");
651 request.load_flags = 0;
652
653 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57654 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
655 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14656 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42657 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14658 };
[email protected]31a2bfe2010-02-09 08:03:39659 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59660 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14661
662 TestCompletionCallback callback;
663
[email protected]5a1d7ca2010-04-28 20:12:27664 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42665 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14666
667 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14669
[email protected]1c773ea12009-04-28 19:58:42670 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14671 EXPECT_TRUE(response != NULL);
672
673 EXPECT_TRUE(response->headers != NULL);
674 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
675
676 std::string response_data;
677 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42678 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14679 EXPECT_EQ("hello world", response_data);
680}
681
[email protected]ee9410e72010-01-07 01:42:38682TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
683 SessionDependencies session_deps;
684 scoped_ptr<HttpTransaction> trans(
685 new HttpNetworkTransaction(CreateSession(&session_deps)));
686
687 HttpRequestInfo request;
688 request.method = "POST";
689 request.url = GURL("http://www.foo.com/");
690 request.load_flags = 0;
691
692 MockRead data_reads[] = {
693 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
694 MockRead(true, 0),
695 };
[email protected]31a2bfe2010-02-09 08:03:39696 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38697 session_deps.socket_factory.AddSocketDataProvider(&data);
698
699 TestCompletionCallback callback;
700
[email protected]5a1d7ca2010-04-28 20:12:27701 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38702 EXPECT_EQ(ERR_IO_PENDING, rv);
703
704 rv = callback.WaitForResult();
705 EXPECT_EQ(OK, rv);
706
707 std::string response_data;
708 rv = ReadTransaction(trans.get(), &response_data);
709 EXPECT_EQ(OK, rv);
710 EXPECT_EQ("", response_data);
711}
712
713TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
714 SessionDependencies session_deps;
715 scoped_ptr<HttpTransaction> trans(
716 new HttpNetworkTransaction(CreateSession(&session_deps)));
717
718 HttpRequestInfo request;
719 request.method = "POST";
720 request.url = GURL("http://www.foo.com/");
721 request.load_flags = 0;
722
723 MockRead data_reads[] = {
724 MockRead(true, 0),
725 };
[email protected]31a2bfe2010-02-09 08:03:39726 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38727 session_deps.socket_factory.AddSocketDataProvider(&data);
728
729 TestCompletionCallback callback;
730
[email protected]5a1d7ca2010-04-28 20:12:27731 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38732 EXPECT_EQ(ERR_IO_PENDING, rv);
733
734 rv = callback.WaitForResult();
735 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
736}
737
[email protected]3d2a59b2008-09-26 19:44:25738// read_failure specifies a read failure that should cause the network
739// transaction to resend the request.
740void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
741 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59742 SessionDependencies session_deps;
743 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52744
[email protected]1c773ea12009-04-28 19:58:42745 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52746 request.method = "GET";
747 request.url = GURL("http://www.foo.com/");
748 request.load_flags = 0;
749
750 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35751 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
752 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25753 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52754 };
[email protected]31a2bfe2010-02-09 08:03:39755 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59756 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52757
758 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35759 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
760 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42761 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52762 };
[email protected]31a2bfe2010-02-09 08:03:39763 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59764 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52765
766 const char* kExpectedResponseData[] = {
767 "hello", "world"
768 };
769
770 for (int i = 0; i < 2; ++i) {
771 TestCompletionCallback callback;
772
[email protected]5695b8c2009-09-30 21:36:43773 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52774
[email protected]5a1d7ca2010-04-28 20:12:27775 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42776 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52777
778 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42779 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52780
[email protected]1c773ea12009-04-28 19:58:42781 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52782 EXPECT_TRUE(response != NULL);
783
784 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25785 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52786
787 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57788 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42789 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25790 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52791 }
792}
[email protected]3d2a59b2008-09-26 19:44:25793
794TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42795 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25796 KeepAliveConnectionResendRequestTest(read_failure);
797}
798
799TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42800 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25801 KeepAliveConnectionResendRequestTest(read_failure);
802}
803
804TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59805 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40806 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43807 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25808
[email protected]1c773ea12009-04-28 19:58:42809 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25810 request.method = "GET";
811 request.url = GURL("http://www.google.com/");
812 request.load_flags = 0;
813
814 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42815 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35816 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
817 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42818 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25819 };
[email protected]31a2bfe2010-02-09 08:03:39820 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59821 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25822
823 TestCompletionCallback callback;
824
[email protected]5a1d7ca2010-04-28 20:12:27825 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25827
828 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42829 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25830
[email protected]1c773ea12009-04-28 19:58:42831 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25832 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25833}
834
835// What do various browsers do when the server closes a non-keepalive
836// connection without sending any response header or body?
837//
838// IE7: error page
839// Safari 3.1.2 (Windows): error page
840// Firefox 3.0.1: blank page
841// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42842// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
843// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25844TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
845 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42846 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35847 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
848 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42849 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25850 };
[email protected]31a2bfe2010-02-09 08:03:39851 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
852 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42853 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25854}
[email protected]038e9a32008-10-08 22:40:16855
[email protected]0b0bf032010-09-21 18:08:50856// Test that we correctly reuse a keep-alive connection after not explicitly
857// reading the body.
858TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13859 SessionDependencies session_deps;
860 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
861
862 HttpRequestInfo request;
863 request.method = "GET";
864 request.url = GURL("http://www.foo.com/");
865 request.load_flags = 0;
866
[email protected]0b0bf032010-09-21 18:08:50867 // Note that because all these reads happen in the same
868 // StaticSocketDataProvider, it shows that the same socket is being reused for
869 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13870 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50871 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
872 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13873 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50874 MockRead("HTTP/1.1 302 Found\r\n"
875 "Content-Length: 0\r\n\r\n"),
876 MockRead("HTTP/1.1 302 Found\r\n"
877 "Content-Length: 5\r\n\r\n"
878 "hello"),
879 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
880 "Content-Length: 0\r\n\r\n"),
881 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
882 "Content-Length: 5\r\n\r\n"
883 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13884 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
885 MockRead("hello"),
886 };
887 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
888 session_deps.socket_factory.AddSocketDataProvider(&data1);
889
890 MockRead data2_reads[] = {
891 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
892 };
893 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
894 session_deps.socket_factory.AddSocketDataProvider(&data2);
895
[email protected]0b0bf032010-09-21 18:08:50896 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
897 std::string response_lines[kNumUnreadBodies];
898
899 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13900 TestCompletionCallback callback;
901
902 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
903
904 int rv = trans->Start(&request, &callback, BoundNetLog());
905 EXPECT_EQ(ERR_IO_PENDING, rv);
906
907 rv = callback.WaitForResult();
908 EXPECT_EQ(OK, rv);
909
910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50911 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13912
[email protected]0b0bf032010-09-21 18:08:50913 ASSERT_TRUE(response->headers != NULL);
914 response_lines[i] = response->headers->GetStatusLine();
915
916 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13917 }
[email protected]0b0bf032010-09-21 18:08:50918
919 const char* const kStatusLines[] = {
920 "HTTP/1.1 204 No Content",
921 "HTTP/1.1 205 Reset Content",
922 "HTTP/1.1 304 Not Modified",
923 "HTTP/1.1 302 Found",
924 "HTTP/1.1 302 Found",
925 "HTTP/1.1 301 Moved Permanently",
926 "HTTP/1.1 301 Moved Permanently",
927 };
928
929 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
930 forgot_to_update_kStatusLines);
931
932 for (int i = 0; i < kNumUnreadBodies; ++i)
933 EXPECT_EQ(kStatusLines[i], response_lines[i]);
934
935 TestCompletionCallback callback;
936 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
937 int rv = trans->Start(&request, &callback, BoundNetLog());
938 EXPECT_EQ(ERR_IO_PENDING, rv);
939 rv = callback.WaitForResult();
940 EXPECT_EQ(OK, rv);
941 const HttpResponseInfo* response = trans->GetResponseInfo();
942 ASSERT_TRUE(response != NULL);
943 ASSERT_TRUE(response->headers != NULL);
944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
945 std::string response_data;
946 rv = ReadTransaction(trans.get(), &response_data);
947 EXPECT_EQ(OK, rv);
948 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:13949}
950
[email protected]038e9a32008-10-08 22:40:16951// Test the request-challenge-retry sequence for basic auth.
952// (basic auth is the easiest to mock, because it has no randomness).
953TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59954 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40955 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43956 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16957
[email protected]1c773ea12009-04-28 19:58:42958 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16959 request.method = "GET";
960 request.url = GURL("http://www.google.com/");
961 request.load_flags = 0;
962
[email protected]f9ee6b52008-11-08 06:46:23963 MockWrite data_writes1[] = {
964 MockWrite("GET / HTTP/1.1\r\n"
965 "Host: www.google.com\r\n"
966 "Connection: keep-alive\r\n\r\n"),
967 };
968
[email protected]038e9a32008-10-08 22:40:16969 MockRead data_reads1[] = {
970 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
971 // Give a couple authenticate options (only the middle one is actually
972 // supported).
[email protected]22927ad2009-09-21 19:56:19973 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16974 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
975 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
976 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
977 // Large content-length -- won't matter, as connection will be reset.
978 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42979 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16980 };
981
982 // After calling trans->RestartWithAuth(), this is the request we should
983 // be issuing -- the final header line contains the credentials.
984 MockWrite data_writes2[] = {
985 MockWrite("GET / HTTP/1.1\r\n"
986 "Host: www.google.com\r\n"
987 "Connection: keep-alive\r\n"
988 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
989 };
990
991 // Lastly, the server responds with the actual content.
992 MockRead data_reads2[] = {
993 MockRead("HTTP/1.0 200 OK\r\n"),
994 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
995 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42996 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16997 };
998
[email protected]31a2bfe2010-02-09 08:03:39999 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1000 data_writes1, arraysize(data_writes1));
1001 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1002 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591003 session_deps.socket_factory.AddSocketDataProvider(&data1);
1004 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161005
1006 TestCompletionCallback callback1;
1007
[email protected]5a1d7ca2010-04-28 20:12:271008 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421009 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161010
1011 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421012 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161013
[email protected]1c773ea12009-04-28 19:58:421014 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161015 EXPECT_FALSE(response == NULL);
1016
1017 // The password prompt info should have been set in response->auth_challenge.
1018 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1019
[email protected]71e4573a2009-05-21 22:03:001020 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161021 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1022 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1023
1024 TestCompletionCallback callback2;
1025
[email protected]13c8a092010-07-29 06:15:441026 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161028
1029 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421030 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161031
1032 response = trans->GetResponseInfo();
1033 EXPECT_FALSE(response == NULL);
1034 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1035 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161036}
1037
[email protected]861fcd52009-08-26 02:33:461038TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1039 SessionDependencies session_deps;
1040 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431041 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461042
1043 HttpRequestInfo request;
1044 request.method = "GET";
1045 request.url = GURL("http://www.google.com/");
1046 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1047
1048 MockWrite data_writes[] = {
1049 MockWrite("GET / HTTP/1.1\r\n"
1050 "Host: www.google.com\r\n"
1051 "Connection: keep-alive\r\n\r\n"),
1052 };
1053
1054 MockRead data_reads[] = {
1055 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1056 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1057 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1058 // Large content-length -- won't matter, as connection will be reset.
1059 MockRead("Content-Length: 10000\r\n\r\n"),
1060 MockRead(false, ERR_FAILED),
1061 };
1062
[email protected]31a2bfe2010-02-09 08:03:391063 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1064 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591065 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461066 TestCompletionCallback callback;
1067
[email protected]5a1d7ca2010-04-28 20:12:271068 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461069 EXPECT_EQ(ERR_IO_PENDING, rv);
1070
1071 rv = callback.WaitForResult();
1072 EXPECT_EQ(0, rv);
1073
1074 const HttpResponseInfo* response = trans->GetResponseInfo();
1075 ASSERT_FALSE(response == NULL);
1076 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1077}
1078
[email protected]2d2697f92009-02-18 21:00:321079// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1080// connection.
1081TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591082 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501083 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321084
[email protected]1c773ea12009-04-28 19:58:421085 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321086 request.method = "GET";
1087 request.url = GURL("http://www.google.com/");
1088 request.load_flags = 0;
1089
1090 MockWrite data_writes1[] = {
1091 MockWrite("GET / HTTP/1.1\r\n"
1092 "Host: www.google.com\r\n"
1093 "Connection: keep-alive\r\n\r\n"),
1094
1095 // After calling trans->RestartWithAuth(), this is the request we should
1096 // be issuing -- the final header line contains the credentials.
1097 MockWrite("GET / HTTP/1.1\r\n"
1098 "Host: www.google.com\r\n"
1099 "Connection: keep-alive\r\n"
1100 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1101 };
1102
1103 MockRead data_reads1[] = {
1104 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1105 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1106 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1107 MockRead("Content-Length: 14\r\n\r\n"),
1108 MockRead("Unauthorized\r\n"),
1109
1110 // Lastly, the server responds with the actual content.
1111 MockRead("HTTP/1.1 200 OK\r\n"),
1112 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501113 MockRead("Content-Length: 5\r\n\r\n"),
1114 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321115 };
1116
[email protected]31a2bfe2010-02-09 08:03:391117 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1118 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591119 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321120
1121 TestCompletionCallback callback1;
1122
[email protected]0b0bf032010-09-21 18:08:501123 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271124 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421125 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321126
1127 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421128 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321129
[email protected]1c773ea12009-04-28 19:58:421130 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321131 EXPECT_FALSE(response == NULL);
1132
1133 // The password prompt info should have been set in response->auth_challenge.
1134 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1135
[email protected]71e4573a2009-05-21 22:03:001136 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321137 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1138 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1139
1140 TestCompletionCallback callback2;
1141
[email protected]13c8a092010-07-29 06:15:441142 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421143 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321144
1145 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421146 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321147
1148 response = trans->GetResponseInfo();
1149 EXPECT_FALSE(response == NULL);
1150 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501151 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321152}
1153
1154// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1155// connection and with no response body to drain.
1156TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591157 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501158 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321159
[email protected]1c773ea12009-04-28 19:58:421160 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321161 request.method = "GET";
1162 request.url = GURL("http://www.google.com/");
1163 request.load_flags = 0;
1164
1165 MockWrite data_writes1[] = {
1166 MockWrite("GET / HTTP/1.1\r\n"
1167 "Host: www.google.com\r\n"
1168 "Connection: keep-alive\r\n\r\n"),
1169
1170 // After calling trans->RestartWithAuth(), this is the request we should
1171 // be issuing -- the final header line contains the credentials.
1172 MockWrite("GET / HTTP/1.1\r\n"
1173 "Host: www.google.com\r\n"
1174 "Connection: keep-alive\r\n"
1175 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1176 };
1177
[email protected]2d2697f92009-02-18 21:00:321178 MockRead data_reads1[] = {
1179 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1180 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311181 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321182
1183 // Lastly, the server responds with the actual content.
1184 MockRead("HTTP/1.1 200 OK\r\n"),
1185 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501186 MockRead("Content-Length: 5\r\n\r\n"),
1187 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321188 };
1189
[email protected]31a2bfe2010-02-09 08:03:391190 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1191 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591192 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321193
1194 TestCompletionCallback callback1;
1195
[email protected]0b0bf032010-09-21 18:08:501196 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271197 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321199
1200 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421201 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321202
[email protected]1c773ea12009-04-28 19:58:421203 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321204 EXPECT_FALSE(response == NULL);
1205
1206 // The password prompt info should have been set in response->auth_challenge.
1207 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1208
[email protected]71e4573a2009-05-21 22:03:001209 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321210 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1211 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1212
1213 TestCompletionCallback callback2;
1214
[email protected]13c8a092010-07-29 06:15:441215 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421216 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321217
1218 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421219 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321220
1221 response = trans->GetResponseInfo();
1222 EXPECT_FALSE(response == NULL);
1223 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501224 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321225}
1226
1227// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1228// connection and with a large response body to drain.
1229TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591230 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501231 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321232
[email protected]1c773ea12009-04-28 19:58:421233 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321234 request.method = "GET";
1235 request.url = GURL("http://www.google.com/");
1236 request.load_flags = 0;
1237
1238 MockWrite data_writes1[] = {
1239 MockWrite("GET / HTTP/1.1\r\n"
1240 "Host: www.google.com\r\n"
1241 "Connection: keep-alive\r\n\r\n"),
1242
1243 // After calling trans->RestartWithAuth(), this is the request we should
1244 // be issuing -- the final header line contains the credentials.
1245 MockWrite("GET / HTTP/1.1\r\n"
1246 "Host: www.google.com\r\n"
1247 "Connection: keep-alive\r\n"
1248 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1249 };
1250
1251 // Respond with 5 kb of response body.
1252 std::string large_body_string("Unauthorized");
1253 large_body_string.append(5 * 1024, ' ');
1254 large_body_string.append("\r\n");
1255
1256 MockRead data_reads1[] = {
1257 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1258 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1260 // 5134 = 12 + 5 * 1024 + 2
1261 MockRead("Content-Length: 5134\r\n\r\n"),
1262 MockRead(true, large_body_string.data(), large_body_string.size()),
1263
1264 // Lastly, the server responds with the actual content.
1265 MockRead("HTTP/1.1 200 OK\r\n"),
1266 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501267 MockRead("Content-Length: 5\r\n\r\n"),
1268 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321269 };
1270
[email protected]31a2bfe2010-02-09 08:03:391271 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1272 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591273 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321274
1275 TestCompletionCallback callback1;
1276
[email protected]0b0bf032010-09-21 18:08:501277 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271278 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421279 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321280
1281 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421282 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321283
[email protected]1c773ea12009-04-28 19:58:421284 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321285 EXPECT_FALSE(response == NULL);
1286
1287 // The password prompt info should have been set in response->auth_challenge.
1288 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1289
[email protected]71e4573a2009-05-21 22:03:001290 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321291 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1292 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1293
1294 TestCompletionCallback callback2;
1295
[email protected]13c8a092010-07-29 06:15:441296 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421297 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321298
1299 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421300 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321301
1302 response = trans->GetResponseInfo();
1303 EXPECT_FALSE(response == NULL);
1304 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501305 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321306}
1307
1308// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311309// connection, but the server gets impatient and closes the connection.
1310TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1311 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311313
1314 HttpRequestInfo request;
1315 request.method = "GET";
1316 request.url = GURL("http://www.google.com/");
1317 request.load_flags = 0;
1318
1319 MockWrite data_writes1[] = {
1320 MockWrite("GET / HTTP/1.1\r\n"
1321 "Host: www.google.com\r\n"
1322 "Connection: keep-alive\r\n\r\n"),
1323 // This simulates the seemingly successful write to a closed connection
1324 // if the bug is not fixed.
1325 MockWrite("GET / HTTP/1.1\r\n"
1326 "Host: www.google.com\r\n"
1327 "Connection: keep-alive\r\n"
1328 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1329 };
1330
1331 MockRead data_reads1[] = {
1332 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1333 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1335 MockRead("Content-Length: 14\r\n\r\n"),
1336 // Tell MockTCPClientSocket to simulate the server closing the connection.
1337 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1338 MockRead("Unauthorized\r\n"),
1339 MockRead(false, OK), // The server closes the connection.
1340 };
1341
1342 // After calling trans->RestartWithAuth(), this is the request we should
1343 // be issuing -- the final header line contains the credentials.
1344 MockWrite data_writes2[] = {
1345 MockWrite("GET / HTTP/1.1\r\n"
1346 "Host: www.google.com\r\n"
1347 "Connection: keep-alive\r\n"
1348 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1349 };
1350
1351 // Lastly, the server responds with the actual content.
1352 MockRead data_reads2[] = {
1353 MockRead("HTTP/1.1 200 OK\r\n"),
1354 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501355 MockRead("Content-Length: 5\r\n\r\n"),
1356 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311357 };
1358
[email protected]31a2bfe2010-02-09 08:03:391359 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1360 data_writes1, arraysize(data_writes1));
1361 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1362 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311363 session_deps.socket_factory.AddSocketDataProvider(&data1);
1364 session_deps.socket_factory.AddSocketDataProvider(&data2);
1365
1366 TestCompletionCallback callback1;
1367
[email protected]0b0bf032010-09-21 18:08:501368 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271369 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311370 EXPECT_EQ(ERR_IO_PENDING, rv);
1371
1372 rv = callback1.WaitForResult();
1373 EXPECT_EQ(OK, rv);
1374
1375 const HttpResponseInfo* response = trans->GetResponseInfo();
1376 EXPECT_FALSE(response == NULL);
1377
1378 // The password prompt info should have been set in response->auth_challenge.
1379 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1380
1381 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1382 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1383 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1384
1385 TestCompletionCallback callback2;
1386
[email protected]13c8a092010-07-29 06:15:441387 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311388 EXPECT_EQ(ERR_IO_PENDING, rv);
1389
1390 rv = callback2.WaitForResult();
1391 EXPECT_EQ(OK, rv);
1392
1393 response = trans->GetResponseInfo();
1394 ASSERT_FALSE(response == NULL);
1395 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501396 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311397}
1398
[email protected]394816e92010-08-03 07:38:591399// Test the request-challenge-retry sequence for basic auth, over a connection
1400// that requires a restart when setting up an SSL tunnel.
1401TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1402 // Configure against proxy server "myproxy:70".
1403 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1404 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1405 session_deps.net_log = log.bound().net_log();
1406 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1407
[email protected]394816e92010-08-03 07:38:591408 HttpRequestInfo request;
1409 request.method = "GET";
1410 request.url = GURL("https://www.google.com/");
1411 // when the no authentication data flag is set.
1412 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1413
1414 // Since we have proxy, should try to establish tunnel.
1415 MockWrite data_writes1[] = {
1416 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1417 "Host: www.google.com\r\n"
1418 "Proxy-Connection: keep-alive\r\n\r\n"),
1419
1420 // After calling trans->RestartWithAuth(), this is the request we should
1421 // be issuing -- the final header line contains the credentials.
1422 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1423 "Host: www.google.com\r\n"
1424 "Proxy-Connection: keep-alive\r\n"
1425 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1426
1427 MockWrite("GET / HTTP/1.1\r\n"
1428 "Host: www.google.com\r\n"
1429 "Connection: keep-alive\r\n\r\n"),
1430 };
1431
1432 // The proxy responds to the connect with a 407, using a persistent
1433 // connection.
1434 MockRead data_reads1[] = {
1435 // No credentials.
1436 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1437 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1438 MockRead("Proxy-Connection: close\r\n\r\n"),
1439
1440 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1441
1442 MockRead("HTTP/1.1 200 OK\r\n"),
1443 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501444 MockRead("Content-Length: 5\r\n\r\n"),
1445 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591446 };
1447
1448 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1449 data_writes1, arraysize(data_writes1));
1450 session_deps.socket_factory.AddSocketDataProvider(&data1);
1451 SSLSocketDataProvider ssl(true, OK);
1452 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1453
1454 TestCompletionCallback callback1;
1455
[email protected]0b0bf032010-09-21 18:08:501456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1457
[email protected]394816e92010-08-03 07:38:591458 int rv = trans->Start(&request, &callback1, log.bound());
1459 EXPECT_EQ(ERR_IO_PENDING, rv);
1460
1461 rv = callback1.WaitForResult();
1462 EXPECT_EQ(OK, rv);
1463 size_t pos = ExpectLogContainsSomewhere(
1464 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1465 NetLog::PHASE_NONE);
1466 ExpectLogContainsSomewhere(
1467 log.entries(), pos,
1468 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1469 NetLog::PHASE_NONE);
1470
1471 const HttpResponseInfo* response = trans->GetResponseInfo();
1472 ASSERT_FALSE(response == NULL);
1473
1474 EXPECT_EQ(407, response->headers->response_code());
1475 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1476
1477 // The password prompt info should have been set in response->auth_challenge.
1478 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1479
1480 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1481 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1482 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1483
1484 TestCompletionCallback callback2;
1485
1486 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1487 EXPECT_EQ(ERR_IO_PENDING, rv);
1488
1489 rv = callback2.WaitForResult();
1490 EXPECT_EQ(OK, rv);
1491
1492 response = trans->GetResponseInfo();
1493 ASSERT_FALSE(response == NULL);
1494
1495 EXPECT_TRUE(response->headers->IsKeepAlive());
1496 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501497 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591498 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1499
1500 // The password prompt info should not be set.
1501 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501502
1503 trans.reset();
1504 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591505}
1506
[email protected]11203f012009-11-12 23:02:311507// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321508// proxy connection, when setting up an SSL tunnel.
1509TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1510 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591511 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541512 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1513 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591514 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321515
[email protected]5695b8c2009-09-30 21:36:431516 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321517
[email protected]1c773ea12009-04-28 19:58:421518 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321519 request.method = "GET";
1520 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461521 // Ensure that proxy authentication is attempted even
1522 // when the no authentication data flag is set.
1523 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321524
1525 // Since we have proxy, should try to establish tunnel.
1526 MockWrite data_writes1[] = {
1527 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451528 "Host: www.google.com\r\n"
1529 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321530
1531 // After calling trans->RestartWithAuth(), this is the request we should
1532 // be issuing -- the final header line contains the credentials.
1533 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1534 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451535 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321536 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1537 };
1538
1539 // The proxy responds to the connect with a 407, using a persistent
1540 // connection.
1541 MockRead data_reads1[] = {
1542 // No credentials.
1543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1544 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1545 MockRead("Content-Length: 10\r\n\r\n"),
1546 MockRead("0123456789"),
1547
1548 // Wrong credentials (wrong password).
1549 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1550 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1551 MockRead("Content-Length: 10\r\n\r\n"),
1552 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421553 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321554 };
1555
[email protected]31a2bfe2010-02-09 08:03:391556 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1557 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591558 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321559
1560 TestCompletionCallback callback1;
1561
[email protected]dbb83db2010-05-11 18:13:391562 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421563 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321564
1565 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421566 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391567 size_t pos = ExpectLogContainsSomewhere(
1568 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1569 NetLog::PHASE_NONE);
1570 ExpectLogContainsSomewhere(
1571 log.entries(), pos,
1572 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1573 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321574
[email protected]1c773ea12009-04-28 19:58:421575 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321576 EXPECT_FALSE(response == NULL);
1577
1578 EXPECT_TRUE(response->headers->IsKeepAlive());
1579 EXPECT_EQ(407, response->headers->response_code());
1580 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421581 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321582
1583 // The password prompt info should have been set in response->auth_challenge.
1584 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1585
[email protected]71e4573a2009-05-21 22:03:001586 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321587 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1588 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1589
1590 TestCompletionCallback callback2;
1591
1592 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441593 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421594 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321595
1596 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421597 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321598
1599 response = trans->GetResponseInfo();
1600 EXPECT_FALSE(response == NULL);
1601
1602 EXPECT_TRUE(response->headers->IsKeepAlive());
1603 EXPECT_EQ(407, response->headers->response_code());
1604 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421605 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321606
1607 // The password prompt info should have been set in response->auth_challenge.
1608 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1609
[email protected]71e4573a2009-05-21 22:03:001610 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321611 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1612 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131613
[email protected]e60e47a2010-07-14 03:37:181614 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1615 // out of scope.
1616 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321617}
1618
[email protected]a8e9b162009-03-12 00:06:441619// Test that we don't read the response body when we fail to establish a tunnel,
1620// even if the user cancels the proxy's auth attempt.
1621TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1622 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591623 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441624
[email protected]e44de5d2009-06-05 20:12:451625 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441626
[email protected]5695b8c2009-09-30 21:36:431627 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441628
[email protected]1c773ea12009-04-28 19:58:421629 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441630 request.method = "GET";
1631 request.url = GURL("https://www.google.com/");
1632 request.load_flags = 0;
1633
1634 // Since we have proxy, should try to establish tunnel.
1635 MockWrite data_writes[] = {
1636 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451637 "Host: www.google.com\r\n"
1638 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441639 };
1640
1641 // The proxy responds to the connect with a 407.
1642 MockRead data_reads[] = {
1643 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1644 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1645 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421646 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441647 };
1648
[email protected]31a2bfe2010-02-09 08:03:391649 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1650 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591651 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441652
1653 TestCompletionCallback callback;
1654
[email protected]5a1d7ca2010-04-28 20:12:271655 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421656 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441657
1658 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421659 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441660
[email protected]1c773ea12009-04-28 19:58:421661 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441662 EXPECT_FALSE(response == NULL);
1663
1664 EXPECT_TRUE(response->headers->IsKeepAlive());
1665 EXPECT_EQ(407, response->headers->response_code());
1666 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421667 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441668
1669 std::string response_data;
1670 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421671 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181672
1673 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1674 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441675}
1676
[email protected]8fdbcd22010-05-05 02:54:521677// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1678// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1679TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1680 // We are using a DIRECT connection (i.e. no proxy) for this session.
1681 SessionDependencies session_deps;
1682 scoped_ptr<HttpTransaction> trans(
1683 new HttpNetworkTransaction(CreateSession(&session_deps)));
1684
1685 HttpRequestInfo request;
1686 request.method = "GET";
1687 request.url = GURL("http://www.google.com/");
1688 request.load_flags = 0;
1689
1690 MockWrite data_writes1[] = {
1691 MockWrite("GET / HTTP/1.1\r\n"
1692 "Host: www.google.com\r\n"
1693 "Connection: keep-alive\r\n\r\n"),
1694 };
1695
1696 MockRead data_reads1[] = {
1697 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1698 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1699 // Large content-length -- won't matter, as connection will be reset.
1700 MockRead("Content-Length: 10000\r\n\r\n"),
1701 MockRead(false, ERR_FAILED),
1702 };
1703
1704 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1705 data_writes1, arraysize(data_writes1));
1706 session_deps.socket_factory.AddSocketDataProvider(&data1);
1707
1708 TestCompletionCallback callback;
1709
1710 int rv = trans->Start(&request, &callback, BoundNetLog());
1711 EXPECT_EQ(ERR_IO_PENDING, rv);
1712
1713 rv = callback.WaitForResult();
1714 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1715}
1716
[email protected]2df19bb2010-08-25 20:13:461717
1718// Test a simple get through an HTTPS Proxy.
1719TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1720 // Configure against https proxy server "proxy:70".
1721 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1722 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1723 session_deps.net_log = log.bound().net_log();
1724 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1725
[email protected]2df19bb2010-08-25 20:13:461726 HttpRequestInfo request;
1727 request.method = "GET";
1728 request.url = GURL("http://www.google.com/");
1729
1730 // Since we have proxy, should use full url
1731 MockWrite data_writes1[] = {
1732 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1733 "Host: www.google.com\r\n"
1734 "Proxy-Connection: keep-alive\r\n\r\n"),
1735 };
1736
1737 MockRead data_reads1[] = {
1738 MockRead("HTTP/1.1 200 OK\r\n"),
1739 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1740 MockRead("Content-Length: 100\r\n\r\n"),
1741 MockRead(false, OK),
1742 };
1743
1744 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1745 data_writes1, arraysize(data_writes1));
1746 session_deps.socket_factory.AddSocketDataProvider(&data1);
1747 SSLSocketDataProvider ssl(true, OK);
1748 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1749
1750 TestCompletionCallback callback1;
1751
[email protected]0b0bf032010-09-21 18:08:501752 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1753
[email protected]2df19bb2010-08-25 20:13:461754 int rv = trans->Start(&request, &callback1, log.bound());
1755 EXPECT_EQ(ERR_IO_PENDING, rv);
1756
1757 rv = callback1.WaitForResult();
1758 EXPECT_EQ(OK, rv);
1759
1760 const HttpResponseInfo* response = trans->GetResponseInfo();
1761 ASSERT_FALSE(response == NULL);
1762
1763 EXPECT_TRUE(response->headers->IsKeepAlive());
1764 EXPECT_EQ(200, response->headers->response_code());
1765 EXPECT_EQ(100, response->headers->GetContentLength());
1766 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1767
1768 // The password prompt info should not be set.
1769 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1770}
1771
[email protected]7642b5ae2010-09-01 20:55:171772// Test a SPDY get through an HTTPS Proxy.
1773TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1774 // Configure against https proxy server "proxy:70".
1775 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1776 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1777 session_deps.net_log = log.bound().net_log();
1778 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1779
[email protected]7642b5ae2010-09-01 20:55:171780 HttpRequestInfo request;
1781 request.method = "GET";
1782 request.url = GURL("http://www.google.com/");
1783 request.load_flags = 0;
1784
1785 // fetch http://www.google.com/ via SPDY
1786 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1787 false));
1788 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1789
1790 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1791 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1792 MockRead spdy_reads[] = {
1793 CreateMockRead(*resp),
1794 CreateMockRead(*data),
1795 MockRead(true, 0, 0),
1796 };
1797
1798 scoped_refptr<DelayedSocketData> spdy_data(
1799 new DelayedSocketData(
1800 1, // wait for one write to finish before reading.
1801 spdy_reads, arraysize(spdy_reads),
1802 spdy_writes, arraysize(spdy_writes)));
1803 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1804
1805 SSLSocketDataProvider ssl(true, OK);
1806 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1807 ssl.next_proto = "spdy/2";
1808 ssl.was_npn_negotiated = true;
1809 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1810
1811 TestCompletionCallback callback1;
1812
[email protected]0b0bf032010-09-21 18:08:501813 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1814
[email protected]7642b5ae2010-09-01 20:55:171815 int rv = trans->Start(&request, &callback1, log.bound());
1816 EXPECT_EQ(ERR_IO_PENDING, rv);
1817
1818 rv = callback1.WaitForResult();
1819 EXPECT_EQ(OK, rv);
1820
1821 const HttpResponseInfo* response = trans->GetResponseInfo();
1822 ASSERT_TRUE(response != NULL);
1823 ASSERT_TRUE(response->headers != NULL);
1824 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1825
1826 std::string response_data;
1827 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1828 EXPECT_EQ(net::kUploadData, response_data);
1829}
1830
[email protected]2df19bb2010-08-25 20:13:461831// Test the challenge-response-retry sequence through an HTTPS Proxy
1832TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
1833 // Configure against https proxy server "proxy:70".
1834 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1835 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1836 session_deps.net_log = log.bound().net_log();
1837 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1838
[email protected]2df19bb2010-08-25 20:13:461839 HttpRequestInfo request;
1840 request.method = "GET";
1841 request.url = GURL("http://www.google.com/");
1842 // when the no authentication data flag is set.
1843 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1844
1845 // Since we have proxy, should use full url
1846 MockWrite data_writes1[] = {
1847 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1848 "Host: www.google.com\r\n"
1849 "Proxy-Connection: keep-alive\r\n\r\n"),
1850
1851 // After calling trans->RestartWithAuth(), this is the request we should
1852 // be issuing -- the final header line contains the credentials.
1853 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1854 "Host: www.google.com\r\n"
1855 "Proxy-Connection: keep-alive\r\n"
1856 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1857 };
1858
1859 // The proxy responds to the GET with a 407, using a persistent
1860 // connection.
1861 MockRead data_reads1[] = {
1862 // No credentials.
1863 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1864 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1865 MockRead("Proxy-Connection: keep-alive\r\n"),
1866 MockRead("Content-Length: 0\r\n\r\n"),
1867
1868 MockRead("HTTP/1.1 200 OK\r\n"),
1869 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1870 MockRead("Content-Length: 100\r\n\r\n"),
1871 MockRead(false, OK),
1872 };
1873
1874 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1875 data_writes1, arraysize(data_writes1));
1876 session_deps.socket_factory.AddSocketDataProvider(&data1);
1877 SSLSocketDataProvider ssl(true, OK);
1878 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1879
1880 TestCompletionCallback callback1;
1881
[email protected]0b0bf032010-09-21 18:08:501882 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1883
[email protected]2df19bb2010-08-25 20:13:461884 int rv = trans->Start(&request, &callback1, log.bound());
1885 EXPECT_EQ(ERR_IO_PENDING, rv);
1886
1887 rv = callback1.WaitForResult();
1888 EXPECT_EQ(OK, rv);
1889
1890 const HttpResponseInfo* response = trans->GetResponseInfo();
1891 ASSERT_FALSE(response == NULL);
1892
1893 EXPECT_EQ(407, response->headers->response_code());
1894 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1895
1896 // The password prompt info should have been set in response->auth_challenge.
1897 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1898
1899 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
1900 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1901 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1902
1903 TestCompletionCallback callback2;
1904
1905 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1906 EXPECT_EQ(ERR_IO_PENDING, rv);
1907
1908 rv = callback2.WaitForResult();
1909 EXPECT_EQ(OK, rv);
1910
1911 response = trans->GetResponseInfo();
1912 ASSERT_FALSE(response == NULL);
1913
1914 EXPECT_TRUE(response->headers->IsKeepAlive());
1915 EXPECT_EQ(200, response->headers->response_code());
1916 EXPECT_EQ(100, response->headers->GetContentLength());
1917 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1918
1919 // The password prompt info should not be set.
1920 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1921}
1922
[email protected]ff007e162009-05-23 09:13:151923void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081924 const MockRead& status, int expected_status) {
1925 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591926 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081927
[email protected]228ff742009-06-05 01:19:591928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081929
[email protected]1c773ea12009-04-28 19:58:421930 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081931 request.method = "GET";
1932 request.url = GURL("https://www.google.com/");
1933 request.load_flags = 0;
1934
1935 // Since we have proxy, should try to establish tunnel.
1936 MockWrite data_writes[] = {
1937 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451938 "Host: www.google.com\r\n"
1939 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081940 };
1941
1942 MockRead data_reads[] = {
1943 status,
1944 MockRead("Content-Length: 10\r\n\r\n"),
1945 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421946 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081947 };
1948
[email protected]31a2bfe2010-02-09 08:03:391949 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1950 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591951 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081952
1953 TestCompletionCallback callback;
1954
[email protected]0b0bf032010-09-21 18:08:501955 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1956
[email protected]5a1d7ca2010-04-28 20:12:271957 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421958 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081959
1960 rv = callback.WaitForResult();
1961 EXPECT_EQ(expected_status, rv);
1962}
1963
[email protected]ff007e162009-05-23 09:13:151964void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081965 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421966 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081967}
1968
1969TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1970 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1971}
1972
1973TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1974 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1975}
1976
1977TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1978 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1979}
1980
1981TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1982 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1983}
1984
1985TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1986 ConnectStatusHelper(
1987 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1988}
1989
1990TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1991 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1992}
1993
1994TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1995 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1996}
1997
1998TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1999 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2000}
2001
2002TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2003 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2004}
2005
2006TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2007 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2008}
2009
2010TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2011 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2012}
2013
2014TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2015 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2016}
2017
2018TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2019 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2020}
2021
2022TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2023 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2024}
2025
2026TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2027 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2028}
2029
2030TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2031 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2032}
2033
2034TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2035 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2036}
2037
2038TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2039 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2040}
2041
2042TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2043 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2044}
2045
2046TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2047 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2048}
2049
2050TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2051 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2052}
2053
2054TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2055 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2056}
2057
2058TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2059 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2060}
2061
2062TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2063 ConnectStatusHelperWithExpectedStatus(
2064 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542065 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082066}
2067
2068TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2069 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2070}
2071
2072TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2073 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2074}
2075
2076TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2077 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2078}
2079
2080TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2081 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2082}
2083
2084TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2085 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2086}
2087
2088TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2089 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2090}
2091
2092TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2093 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2094}
2095
2096TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2097 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2098}
2099
2100TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2101 ConnectStatusHelper(
2102 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2103}
2104
2105TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2106 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2107}
2108
2109TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2110 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2111}
2112
2113TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2114 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2115}
2116
2117TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2118 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2119}
2120
2121TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2122 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2123}
2124
2125TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2126 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2127}
2128
2129TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2130 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2131}
2132
[email protected]038e9a32008-10-08 22:40:162133// Test the flow when both the proxy server AND origin server require
2134// authentication. Again, this uses basic auth for both since that is
2135// the simplest to mock.
2136TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:592137 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012138
[email protected]038e9a32008-10-08 22:40:162139 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422140 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432141 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162142
[email protected]1c773ea12009-04-28 19:58:422143 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162144 request.method = "GET";
2145 request.url = GURL("http://www.google.com/");
2146 request.load_flags = 0;
2147
[email protected]f9ee6b52008-11-08 06:46:232148 MockWrite data_writes1[] = {
2149 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2150 "Host: www.google.com\r\n"
2151 "Proxy-Connection: keep-alive\r\n\r\n"),
2152 };
2153
[email protected]038e9a32008-10-08 22:40:162154 MockRead data_reads1[] = {
2155 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2156 // Give a couple authenticate options (only the middle one is actually
2157 // supported).
[email protected]22927ad2009-09-21 19:56:192158 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162159 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2160 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2161 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2162 // Large content-length -- won't matter, as connection will be reset.
2163 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422164 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162165 };
2166
2167 // After calling trans->RestartWithAuth() the first time, this is the
2168 // request we should be issuing -- the final header line contains the
2169 // proxy's credentials.
2170 MockWrite data_writes2[] = {
2171 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2172 "Host: www.google.com\r\n"
2173 "Proxy-Connection: keep-alive\r\n"
2174 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2175 };
2176
2177 // Now the proxy server lets the request pass through to origin server.
2178 // The origin server responds with a 401.
2179 MockRead data_reads2[] = {
2180 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2181 // Note: We are using the same realm-name as the proxy server. This is
2182 // completely valid, as realms are unique across hosts.
2183 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2185 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422186 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162187 };
2188
2189 // After calling trans->RestartWithAuth() the second time, we should send
2190 // the credentials for both the proxy and origin server.
2191 MockWrite data_writes3[] = {
2192 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2193 "Host: www.google.com\r\n"
2194 "Proxy-Connection: keep-alive\r\n"
2195 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2196 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2197 };
2198
2199 // Lastly we get the desired content.
2200 MockRead data_reads3[] = {
2201 MockRead("HTTP/1.0 200 OK\r\n"),
2202 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2203 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422204 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162205 };
2206
[email protected]31a2bfe2010-02-09 08:03:392207 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2208 data_writes1, arraysize(data_writes1));
2209 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2210 data_writes2, arraysize(data_writes2));
2211 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2212 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592213 session_deps.socket_factory.AddSocketDataProvider(&data1);
2214 session_deps.socket_factory.AddSocketDataProvider(&data2);
2215 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162216
2217 TestCompletionCallback callback1;
2218
[email protected]5a1d7ca2010-04-28 20:12:272219 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422220 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162221
2222 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422223 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162224
[email protected]1c773ea12009-04-28 19:58:422225 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162226 EXPECT_FALSE(response == NULL);
2227
2228 // The password prompt info should have been set in response->auth_challenge.
2229 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2230
[email protected]71e4573a2009-05-21 22:03:002231 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162232 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2233 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2234
2235 TestCompletionCallback callback2;
2236
[email protected]13c8a092010-07-29 06:15:442237 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422238 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162239
2240 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422241 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162242
2243 response = trans->GetResponseInfo();
2244 EXPECT_FALSE(response == NULL);
2245 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2246
[email protected]71e4573a2009-05-21 22:03:002247 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162248 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2249 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2250
2251 TestCompletionCallback callback3;
2252
[email protected]13c8a092010-07-29 06:15:442253 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422254 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162255
2256 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422257 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162258
2259 response = trans->GetResponseInfo();
2260 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2261 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162262}
[email protected]4ddaf2502008-10-23 18:26:192263
[email protected]ea9dc9a2009-09-05 00:43:322264// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2265// can't hook into its internals to cause it to generate predictable NTLM
2266// authorization headers.
2267#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292268// The NTLM authentication unit tests were generated by capturing the HTTP
2269// requests and responses using Fiddler 2 and inspecting the generated random
2270// bytes in the debugger.
2271
2272// Enter the correct password and authenticate successfully.
2273TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422274 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112275 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592276 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502277 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242278
[email protected]1c773ea12009-04-28 19:58:422279 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242280 request.method = "GET";
2281 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2282 request.load_flags = 0;
2283
2284 MockWrite data_writes1[] = {
2285 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2286 "Host: 172.22.68.17\r\n"
2287 "Connection: keep-alive\r\n\r\n"),
2288 };
2289
2290 MockRead data_reads1[] = {
2291 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042292 // Negotiate and NTLM are often requested together. However, we only want
2293 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2294 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242295 MockRead("WWW-Authenticate: NTLM\r\n"),
2296 MockRead("Connection: close\r\n"),
2297 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362298 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242299 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422300 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242301 };
2302
2303 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222304 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242305 // request we should be issuing -- the final header line contains a Type
2306 // 1 message.
2307 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2308 "Host: 172.22.68.17\r\n"
2309 "Connection: keep-alive\r\n"
2310 "Authorization: NTLM "
2311 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2312
2313 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2314 // (the credentials for the origin server). The second request continues
2315 // on the same connection.
2316 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2317 "Host: 172.22.68.17\r\n"
2318 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292319 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2320 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2321 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2322 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2323 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242324 };
2325
2326 MockRead data_reads2[] = {
2327 // The origin server responds with a Type 2 message.
2328 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2329 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292330 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242331 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2332 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2333 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2334 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2335 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2336 "BtAAAAAAA=\r\n"),
2337 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362338 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242339 MockRead("You are not authorized to view this page\r\n"),
2340
2341 // Lastly we get the desired content.
2342 MockRead("HTTP/1.1 200 OK\r\n"),
2343 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2344 MockRead("Content-Length: 13\r\n\r\n"),
2345 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422346 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242347 };
2348
[email protected]31a2bfe2010-02-09 08:03:392349 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2350 data_writes1, arraysize(data_writes1));
2351 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2352 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592353 session_deps.socket_factory.AddSocketDataProvider(&data1);
2354 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242355
2356 TestCompletionCallback callback1;
2357
[email protected]0b0bf032010-09-21 18:08:502358 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2359
[email protected]5a1d7ca2010-04-28 20:12:272360 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422361 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242362
2363 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422364 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242365
[email protected]0757e7702009-03-27 04:00:222366 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2367 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442368 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422369 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222370 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422371 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222372 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2373
[email protected]1c773ea12009-04-28 19:58:422374 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042375 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242376
[email protected]aef04272010-06-28 18:03:042377 // The password prompt info should have been set in
2378 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242379 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2380
[email protected]71e4573a2009-05-21 22:03:002381 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242382 EXPECT_EQ(L"", response->auth_challenge->realm);
2383 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2384
[email protected]0757e7702009-03-27 04:00:222385 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242386
[email protected]13c8a092010-07-29 06:15:442387 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422388 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242389
[email protected]0757e7702009-03-27 04:00:222390 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422391 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242392
2393 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042394 ASSERT_FALSE(response == NULL);
2395
[email protected]3f918782009-02-28 01:29:242396 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2397 EXPECT_EQ(13, response->headers->GetContentLength());
2398}
2399
[email protected]385a4672009-03-11 22:21:292400// Enter a wrong password, and then the correct one.
2401TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422402 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112403 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592404 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292406
[email protected]1c773ea12009-04-28 19:58:422407 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292408 request.method = "GET";
2409 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2410 request.load_flags = 0;
2411
2412 MockWrite data_writes1[] = {
2413 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2414 "Host: 172.22.68.17\r\n"
2415 "Connection: keep-alive\r\n\r\n"),
2416 };
2417
2418 MockRead data_reads1[] = {
2419 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042420 // Negotiate and NTLM are often requested together. However, we only want
2421 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2422 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292423 MockRead("WWW-Authenticate: NTLM\r\n"),
2424 MockRead("Connection: close\r\n"),
2425 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362426 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292427 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422428 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292429 };
2430
2431 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222432 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292433 // request we should be issuing -- the final header line contains a Type
2434 // 1 message.
2435 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2436 "Host: 172.22.68.17\r\n"
2437 "Connection: keep-alive\r\n"
2438 "Authorization: NTLM "
2439 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2440
2441 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2442 // (the credentials for the origin server). The second request continues
2443 // on the same connection.
2444 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2445 "Host: 172.22.68.17\r\n"
2446 "Connection: keep-alive\r\n"
2447 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2448 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2449 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2450 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2451 "4Ww7b7E=\r\n\r\n"),
2452 };
2453
2454 MockRead data_reads2[] = {
2455 // The origin server responds with a Type 2 message.
2456 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2457 MockRead("WWW-Authenticate: NTLM "
2458 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2459 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2460 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2461 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2462 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2463 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2464 "BtAAAAAAA=\r\n"),
2465 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362466 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292467 MockRead("You are not authorized to view this page\r\n"),
2468
2469 // Wrong password.
2470 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292471 MockRead("WWW-Authenticate: NTLM\r\n"),
2472 MockRead("Connection: close\r\n"),
2473 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362474 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292475 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422476 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292477 };
2478
2479 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222480 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292481 // request we should be issuing -- the final header line contains a Type
2482 // 1 message.
2483 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2484 "Host: 172.22.68.17\r\n"
2485 "Connection: keep-alive\r\n"
2486 "Authorization: NTLM "
2487 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2488
2489 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2490 // (the credentials for the origin server). The second request continues
2491 // on the same connection.
2492 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2493 "Host: 172.22.68.17\r\n"
2494 "Connection: keep-alive\r\n"
2495 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2496 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2497 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2498 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2499 "+4MUm7c=\r\n\r\n"),
2500 };
2501
2502 MockRead data_reads3[] = {
2503 // The origin server responds with a Type 2 message.
2504 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2505 MockRead("WWW-Authenticate: NTLM "
2506 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2507 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2508 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2509 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2510 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2511 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2512 "BtAAAAAAA=\r\n"),
2513 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362514 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292515 MockRead("You are not authorized to view this page\r\n"),
2516
2517 // Lastly we get the desired content.
2518 MockRead("HTTP/1.1 200 OK\r\n"),
2519 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2520 MockRead("Content-Length: 13\r\n\r\n"),
2521 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422522 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292523 };
2524
[email protected]31a2bfe2010-02-09 08:03:392525 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2526 data_writes1, arraysize(data_writes1));
2527 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2528 data_writes2, arraysize(data_writes2));
2529 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2530 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592531 session_deps.socket_factory.AddSocketDataProvider(&data1);
2532 session_deps.socket_factory.AddSocketDataProvider(&data2);
2533 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292534
2535 TestCompletionCallback callback1;
2536
[email protected]0b0bf032010-09-21 18:08:502537 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2538
[email protected]5a1d7ca2010-04-28 20:12:272539 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422540 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292541
2542 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422543 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292544
[email protected]0757e7702009-03-27 04:00:222545 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292546 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442547 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422548 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292549 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422550 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222551 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292552
[email protected]1c773ea12009-04-28 19:58:422553 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292554 EXPECT_FALSE(response == NULL);
2555
2556 // The password prompt info should have been set in response->auth_challenge.
2557 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2558
[email protected]71e4573a2009-05-21 22:03:002559 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292560 EXPECT_EQ(L"", response->auth_challenge->realm);
2561 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2562
2563 TestCompletionCallback callback3;
2564
[email protected]0757e7702009-03-27 04:00:222565 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442566 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422567 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292568
2569 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422570 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292571
[email protected]0757e7702009-03-27 04:00:222572 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2573 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442574 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422575 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222576 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422577 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222578 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2579
2580 response = trans->GetResponseInfo();
2581 EXPECT_FALSE(response == NULL);
2582
2583 // The password prompt info should have been set in response->auth_challenge.
2584 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2585
[email protected]71e4573a2009-05-21 22:03:002586 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222587 EXPECT_EQ(L"", response->auth_challenge->realm);
2588 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2589
2590 TestCompletionCallback callback5;
2591
2592 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442593 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422594 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222595
2596 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422597 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222598
[email protected]385a4672009-03-11 22:21:292599 response = trans->GetResponseInfo();
2600 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2601 EXPECT_EQ(13, response->headers->GetContentLength());
2602}
[email protected]ea9dc9a2009-09-05 00:43:322603#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292604
[email protected]4ddaf2502008-10-23 18:26:192605// Test reading a server response which has only headers, and no body.
2606// After some maximum number of bytes is consumed, the transaction should
2607// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2608TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592609 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402610 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432611 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192612
[email protected]1c773ea12009-04-28 19:58:422613 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192614 request.method = "GET";
2615 request.url = GURL("http://www.google.com/");
2616 request.load_flags = 0;
2617
[email protected]b75b7b2f2009-10-06 00:54:532618 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432619 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532620 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192621
2622 MockRead data_reads[] = {
2623 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432624 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192625 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422626 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192627 };
[email protected]31a2bfe2010-02-09 08:03:392628 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592629 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192630
2631 TestCompletionCallback callback;
2632
[email protected]5a1d7ca2010-04-28 20:12:272633 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422634 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192635
2636 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422637 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192638
[email protected]1c773ea12009-04-28 19:58:422639 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192640 EXPECT_TRUE(response == NULL);
2641}
[email protected]f4e426b2008-11-05 00:24:492642
2643// Make sure that we don't try to reuse a TCPClientSocket when failing to
2644// establish tunnel.
2645// http://code.google.com/p/chromium/issues/detail?id=3772
2646TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2647 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592648 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012649
[email protected]228ff742009-06-05 01:19:592650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492651
[email protected]5695b8c2009-09-30 21:36:432652 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492653
[email protected]1c773ea12009-04-28 19:58:422654 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492655 request.method = "GET";
2656 request.url = GURL("https://www.google.com/");
2657 request.load_flags = 0;
2658
2659 // Since we have proxy, should try to establish tunnel.
2660 MockWrite data_writes1[] = {
2661 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452662 "Host: www.google.com\r\n"
2663 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492664 };
2665
[email protected]77848d12008-11-14 00:00:222666 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492667 // connection. Usually a proxy would return 501 (not implemented),
2668 // or 200 (tunnel established).
2669 MockRead data_reads1[] = {
2670 MockRead("HTTP/1.1 404 Not Found\r\n"),
2671 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422672 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492673 };
2674
[email protected]31a2bfe2010-02-09 08:03:392675 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2676 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592677 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492678
2679 TestCompletionCallback callback1;
2680
[email protected]5a1d7ca2010-04-28 20:12:272681 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422682 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492683
2684 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422685 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492686
[email protected]1c773ea12009-04-28 19:58:422687 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082688 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492689
[email protected]b4404c02009-04-10 16:38:522690 // Empty the current queue. This is necessary because idle sockets are
2691 // added to the connection pool asynchronously with a PostTask.
2692 MessageLoop::current()->RunAllPending();
2693
[email protected]f4e426b2008-11-05 00:24:492694 // We now check to make sure the TCPClientSocket was not added back to
2695 // the pool.
[email protected]a937a06d2009-08-19 21:19:242696 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492697 trans.reset();
[email protected]b4404c02009-04-10 16:38:522698 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492699 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242700 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492701}
[email protected]372d34a2008-11-05 21:30:512702
[email protected]1b157c02009-04-21 01:55:402703// Make sure that we recycle a socket after reading all of the response body.
2704TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592705 SessionDependencies session_deps;
2706 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402707
[email protected]5695b8c2009-09-30 21:36:432708 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402709
[email protected]1c773ea12009-04-28 19:58:422710 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402711 request.method = "GET";
2712 request.url = GURL("http://www.google.com/");
2713 request.load_flags = 0;
2714
2715 MockRead data_reads[] = {
2716 // A part of the response body is received with the response headers.
2717 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2718 // The rest of the response body is received in two parts.
2719 MockRead("lo"),
2720 MockRead(" world"),
2721 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422722 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402723 };
2724
[email protected]31a2bfe2010-02-09 08:03:392725 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592726 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402727
2728 TestCompletionCallback callback;
2729
[email protected]5a1d7ca2010-04-28 20:12:272730 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422731 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402732
2733 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422734 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402735
[email protected]1c773ea12009-04-28 19:58:422736 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402737 EXPECT_TRUE(response != NULL);
2738
2739 EXPECT_TRUE(response->headers != NULL);
2740 std::string status_line = response->headers->GetStatusLine();
2741 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2742
[email protected]a937a06d2009-08-19 21:19:242743 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402744
2745 std::string response_data;
2746 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422747 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402748 EXPECT_EQ("hello world", response_data);
2749
2750 // Empty the current queue. This is necessary because idle sockets are
2751 // added to the connection pool asynchronously with a PostTask.
2752 MessageLoop::current()->RunAllPending();
2753
2754 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242755 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402756}
2757
[email protected]76a505b2010-08-25 06:23:002758// Make sure that we recycle a SSL socket after reading all of the response
2759// body.
2760TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
2761 SessionDependencies session_deps;
2762 HttpRequestInfo request;
2763 request.method = "GET";
2764 request.url = GURL("https://www.google.com/");
2765 request.load_flags = 0;
2766
2767 MockWrite data_writes[] = {
2768 MockWrite("GET / HTTP/1.1\r\n"
2769 "Host: www.google.com\r\n"
2770 "Connection: keep-alive\r\n\r\n"),
2771 };
2772
2773 MockRead data_reads[] = {
2774 MockRead("HTTP/1.1 200 OK\r\n"),
2775 MockRead("Content-Length: 11\r\n\r\n"),
2776 MockRead("hello world"),
2777 MockRead(false, OK),
2778 };
2779
2780 SSLSocketDataProvider ssl(true, OK);
2781 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2782
2783 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2784 data_writes, arraysize(data_writes));
2785 session_deps.socket_factory.AddSocketDataProvider(&data);
2786
2787 TestCompletionCallback callback;
2788
2789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2790 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2791
2792 int rv = trans->Start(&request, &callback, BoundNetLog());
2793
2794 EXPECT_EQ(ERR_IO_PENDING, rv);
2795 EXPECT_EQ(OK, callback.WaitForResult());
2796
2797 const HttpResponseInfo* response = trans->GetResponseInfo();
2798 ASSERT_TRUE(response != NULL);
2799 ASSERT_TRUE(response->headers != NULL);
2800 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2801
2802 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2803
2804 std::string response_data;
2805 rv = ReadTransaction(trans.get(), &response_data);
2806 EXPECT_EQ(OK, rv);
2807 EXPECT_EQ("hello world", response_data);
2808
2809 // Empty the current queue. This is necessary because idle sockets are
2810 // added to the connection pool asynchronously with a PostTask.
2811 MessageLoop::current()->RunAllPending();
2812
2813 // We now check to make sure the socket was added back to the pool.
2814 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2815}
2816
2817// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
2818// from the pool and make sure that we recover okay.
2819TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
2820 SessionDependencies session_deps;
2821 HttpRequestInfo request;
2822 request.method = "GET";
2823 request.url = GURL("https://www.google.com/");
2824 request.load_flags = 0;
2825
2826 MockWrite data_writes[] = {
2827 MockWrite("GET / HTTP/1.1\r\n"
2828 "Host: www.google.com\r\n"
2829 "Connection: keep-alive\r\n\r\n"),
2830 MockWrite("GET / HTTP/1.1\r\n"
2831 "Host: www.google.com\r\n"
2832 "Connection: keep-alive\r\n\r\n"),
2833 };
2834
2835 MockRead data_reads[] = {
2836 MockRead("HTTP/1.1 200 OK\r\n"),
2837 MockRead("Content-Length: 11\r\n\r\n"),
2838 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2839 MockRead("hello world"),
2840 MockRead(true, 0, 0) // EOF
2841 };
2842
2843 SSLSocketDataProvider ssl(true, OK);
2844 SSLSocketDataProvider ssl2(true, OK);
2845 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2846 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2847
2848 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2849 data_writes, arraysize(data_writes));
2850 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
2851 data_writes, arraysize(data_writes));
2852 session_deps.socket_factory.AddSocketDataProvider(&data);
2853 session_deps.socket_factory.AddSocketDataProvider(&data2);
2854
2855 TestCompletionCallback callback;
2856
2857 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2858 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2859
2860 int rv = trans->Start(&request, &callback, BoundNetLog());
2861
2862 EXPECT_EQ(ERR_IO_PENDING, rv);
2863 EXPECT_EQ(OK, callback.WaitForResult());
2864
2865 const HttpResponseInfo* response = trans->GetResponseInfo();
2866 ASSERT_TRUE(response != NULL);
2867 ASSERT_TRUE(response->headers != NULL);
2868 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2869
2870 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2871
2872 std::string response_data;
2873 rv = ReadTransaction(trans.get(), &response_data);
2874 EXPECT_EQ(OK, rv);
2875 EXPECT_EQ("hello world", response_data);
2876
2877 // Empty the current queue. This is necessary because idle sockets are
2878 // added to the connection pool asynchronously with a PostTask.
2879 MessageLoop::current()->RunAllPending();
2880
2881 // We now check to make sure the socket was added back to the pool.
2882 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2883
2884 // Now start the second transaction, which should reuse the previous socket.
2885
2886 trans.reset(new HttpNetworkTransaction(session));
2887
2888 rv = trans->Start(&request, &callback, BoundNetLog());
2889
2890 EXPECT_EQ(ERR_IO_PENDING, rv);
2891 EXPECT_EQ(OK, callback.WaitForResult());
2892
2893 response = trans->GetResponseInfo();
2894 ASSERT_TRUE(response != NULL);
2895 ASSERT_TRUE(response->headers != NULL);
2896 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2897
2898 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2899
2900 rv = ReadTransaction(trans.get(), &response_data);
2901 EXPECT_EQ(OK, rv);
2902 EXPECT_EQ("hello world", response_data);
2903
2904 // Empty the current queue. This is necessary because idle sockets are
2905 // added to the connection pool asynchronously with a PostTask.
2906 MessageLoop::current()->RunAllPending();
2907
2908 // We now check to make sure the socket was added back to the pool.
2909 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2910}
2911
[email protected]b4404c02009-04-10 16:38:522912// Make sure that we recycle a socket after a zero-length response.
2913// http://crbug.com/9880
2914TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592915 SessionDependencies session_deps;
2916 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522917
[email protected]5695b8c2009-09-30 21:36:432918 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522919
[email protected]1c773ea12009-04-28 19:58:422920 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522921 request.method = "GET";
2922 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2923 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2924 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2925 "rt=prt.2642,ol.2649,xjs.2951");
2926 request.load_flags = 0;
2927
2928 MockRead data_reads[] = {
2929 MockRead("HTTP/1.1 204 No Content\r\n"
2930 "Content-Length: 0\r\n"
2931 "Content-Type: text/html\r\n\r\n"),
2932 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422933 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522934 };
2935
[email protected]31a2bfe2010-02-09 08:03:392936 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592937 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522938
2939 TestCompletionCallback callback;
2940
[email protected]5a1d7ca2010-04-28 20:12:272941 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422942 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522943
2944 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422945 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522946
[email protected]1c773ea12009-04-28 19:58:422947 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522948 EXPECT_TRUE(response != NULL);
2949
2950 EXPECT_TRUE(response->headers != NULL);
2951 std::string status_line = response->headers->GetStatusLine();
2952 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2953
[email protected]a937a06d2009-08-19 21:19:242954 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522955
2956 std::string response_data;
2957 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422958 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522959 EXPECT_EQ("", response_data);
2960
2961 // Empty the current queue. This is necessary because idle sockets are
2962 // added to the connection pool asynchronously with a PostTask.
2963 MessageLoop::current()->RunAllPending();
2964
2965 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242966 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522967}
2968
[email protected]372d34a2008-11-05 21:30:512969TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422970 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512971 // Transaction 1: a GET request that succeeds. The socket is recycled
2972 // after use.
2973 request[0].method = "GET";
2974 request[0].url = GURL("http://www.google.com/");
2975 request[0].load_flags = 0;
2976 // Transaction 2: a POST request. Reuses the socket kept alive from
2977 // transaction 1. The first attempts fails when writing the POST data.
2978 // This causes the transaction to retry with a new socket. The second
2979 // attempt succeeds.
2980 request[1].method = "POST";
2981 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422982 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512983 request[1].upload_data->AppendBytes("foo", 3);
2984 request[1].load_flags = 0;
2985
[email protected]228ff742009-06-05 01:19:592986 SessionDependencies session_deps;
2987 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512988
2989 // The first socket is used for transaction 1 and the first attempt of
2990 // transaction 2.
2991
2992 // The response of transaction 1.
2993 MockRead data_reads1[] = {
2994 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2995 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422996 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512997 };
2998 // The mock write results of transaction 1 and the first attempt of
2999 // transaction 2.
3000 MockWrite data_writes1[] = {
3001 MockWrite(false, 64), // GET
3002 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423003 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513004 };
[email protected]31a2bfe2010-02-09 08:03:393005 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3006 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513007
3008 // The second socket is used for the second attempt of transaction 2.
3009
3010 // The response of transaction 2.
3011 MockRead data_reads2[] = {
3012 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3013 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423014 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513015 };
3016 // The mock write results of the second attempt of transaction 2.
3017 MockWrite data_writes2[] = {
3018 MockWrite(false, 93), // POST
3019 MockWrite(false, 3), // POST data
3020 };
[email protected]31a2bfe2010-02-09 08:03:393021 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3022 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513023
[email protected]5ecc992a42009-11-11 01:41:593024 session_deps.socket_factory.AddSocketDataProvider(&data1);
3025 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513026
3027 const char* kExpectedResponseData[] = {
3028 "hello world", "welcome"
3029 };
3030
3031 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423032 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433033 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513034
3035 TestCompletionCallback callback;
3036
[email protected]5a1d7ca2010-04-28 20:12:273037 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513039
3040 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423041 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513042
[email protected]1c773ea12009-04-28 19:58:423043 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513044 EXPECT_TRUE(response != NULL);
3045
3046 EXPECT_TRUE(response->headers != NULL);
3047 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3048
3049 std::string response_data;
3050 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423051 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513052 EXPECT_EQ(kExpectedResponseData[i], response_data);
3053 }
3054}
[email protected]f9ee6b52008-11-08 06:46:233055
3056// Test the request-challenge-retry sequence for basic auth when there is
3057// an identity in the URL. The request should be sent as normal, but when
3058// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323059TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593060 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403061 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433062 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233063
[email protected]1c773ea12009-04-28 19:58:423064 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233065 request.method = "GET";
3066 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293067 request.url = GURL("http://foo:b@[email protected]/");
3068
3069 // The password contains an escaped character -- for this test to pass it
3070 // will need to be unescaped by HttpNetworkTransaction.
3071 EXPECT_EQ("b%40r", request.url.password());
3072
[email protected]ea9dc9a2009-09-05 00:43:323073 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233074
3075 MockWrite data_writes1[] = {
3076 MockWrite("GET / HTTP/1.1\r\n"
3077 "Host: www.google.com\r\n"
3078 "Connection: keep-alive\r\n\r\n"),
3079 };
3080
3081 MockRead data_reads1[] = {
3082 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3083 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3084 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423085 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233086 };
3087
3088 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323089 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233090 MockWrite data_writes2[] = {
3091 MockWrite("GET / HTTP/1.1\r\n"
3092 "Host: www.google.com\r\n"
3093 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293094 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233095 };
3096
3097 MockRead data_reads2[] = {
3098 MockRead("HTTP/1.0 200 OK\r\n"),
3099 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423100 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233101 };
3102
[email protected]31a2bfe2010-02-09 08:03:393103 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3104 data_writes1, arraysize(data_writes1));
3105 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3106 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593107 session_deps.socket_factory.AddSocketDataProvider(&data1);
3108 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233109
3110 TestCompletionCallback callback1;
3111
[email protected]5a1d7ca2010-04-28 20:12:273112 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423113 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233114
3115 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423116 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233117
[email protected]0757e7702009-03-27 04:00:223118 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3119 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443120 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423121 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223122 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423123 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223124 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3125
[email protected]1c773ea12009-04-28 19:58:423126 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233127 EXPECT_FALSE(response == NULL);
3128
3129 // There is no challenge info, since the identity in URL worked.
3130 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3131
3132 EXPECT_EQ(100, response->headers->GetContentLength());
3133
3134 // Empty the current queue.
3135 MessageLoop::current()->RunAllPending();
3136}
3137
[email protected]ea9dc9a2009-09-05 00:43:323138// Test the request-challenge-retry sequence for basic auth when there is
3139// an incorrect identity in the URL. The identity from the URL should be used
3140// only once.
3141TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3142 SessionDependencies session_deps;
3143 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433144 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323145
3146 HttpRequestInfo request;
3147 request.method = "GET";
3148 // Note: the URL has a username:password in it. The password "baz" is
3149 // wrong (should be "bar").
3150 request.url = GURL("http://foo:[email protected]/");
3151
3152 request.load_flags = LOAD_NORMAL;
3153
3154 MockWrite data_writes1[] = {
3155 MockWrite("GET / HTTP/1.1\r\n"
3156 "Host: www.google.com\r\n"
3157 "Connection: keep-alive\r\n\r\n"),
3158 };
3159
3160 MockRead data_reads1[] = {
3161 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3162 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3163 MockRead("Content-Length: 10\r\n\r\n"),
3164 MockRead(false, ERR_FAILED),
3165 };
3166
3167 // After the challenge above, the transaction will be restarted using the
3168 // identity from the url (foo, baz) to answer the challenge.
3169 MockWrite data_writes2[] = {
3170 MockWrite("GET / HTTP/1.1\r\n"
3171 "Host: www.google.com\r\n"
3172 "Connection: keep-alive\r\n"
3173 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3174 };
3175
3176 MockRead data_reads2[] = {
3177 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3178 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3179 MockRead("Content-Length: 10\r\n\r\n"),
3180 MockRead(false, ERR_FAILED),
3181 };
3182
3183 // After the challenge above, the transaction will be restarted using the
3184 // identity supplied by the user (foo, bar) to answer the challenge.
3185 MockWrite data_writes3[] = {
3186 MockWrite("GET / HTTP/1.1\r\n"
3187 "Host: www.google.com\r\n"
3188 "Connection: keep-alive\r\n"
3189 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3190 };
3191
3192 MockRead data_reads3[] = {
3193 MockRead("HTTP/1.0 200 OK\r\n"),
3194 MockRead("Content-Length: 100\r\n\r\n"),
3195 MockRead(false, OK),
3196 };
3197
[email protected]31a2bfe2010-02-09 08:03:393198 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3199 data_writes1, arraysize(data_writes1));
3200 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3201 data_writes2, arraysize(data_writes2));
3202 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3203 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593204 session_deps.socket_factory.AddSocketDataProvider(&data1);
3205 session_deps.socket_factory.AddSocketDataProvider(&data2);
3206 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323207
3208 TestCompletionCallback callback1;
3209
[email protected]5a1d7ca2010-04-28 20:12:273210 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323211 EXPECT_EQ(ERR_IO_PENDING, rv);
3212
3213 rv = callback1.WaitForResult();
3214 EXPECT_EQ(OK, rv);
3215
3216 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3217 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443218 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323219 EXPECT_EQ(ERR_IO_PENDING, rv);
3220 rv = callback2.WaitForResult();
3221 EXPECT_EQ(OK, rv);
3222 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3223
3224 const HttpResponseInfo* response = trans->GetResponseInfo();
3225 EXPECT_FALSE(response == NULL);
3226 // The password prompt info should have been set in response->auth_challenge.
3227 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3228
3229 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3230 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3231 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3232
3233 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443234 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323235 EXPECT_EQ(ERR_IO_PENDING, rv);
3236 rv = callback3.WaitForResult();
3237 EXPECT_EQ(OK, rv);
3238 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3239
3240 response = trans->GetResponseInfo();
3241 EXPECT_FALSE(response == NULL);
3242
3243 // There is no challenge info, since the identity worked.
3244 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3245
3246 EXPECT_EQ(100, response->headers->GetContentLength());
3247
3248 // Empty the current queue.
3249 MessageLoop::current()->RunAllPending();
3250}
3251
[email protected]f9ee6b52008-11-08 06:46:233252// Test that previously tried username/passwords for a realm get re-used.
3253TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593254 SessionDependencies session_deps;
3255 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:233256
3257 // Transaction 1: authenticate (foo, bar) on MyRealm1
3258 {
[email protected]5695b8c2009-09-30 21:36:433259 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233260
[email protected]1c773ea12009-04-28 19:58:423261 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233262 request.method = "GET";
3263 request.url = GURL("http://www.google.com/x/y/z");
3264 request.load_flags = 0;
3265
3266 MockWrite data_writes1[] = {
3267 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3268 "Host: www.google.com\r\n"
3269 "Connection: keep-alive\r\n\r\n"),
3270 };
3271
3272 MockRead data_reads1[] = {
3273 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3274 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3275 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423276 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233277 };
3278
3279 // Resend with authorization (username=foo, password=bar)
3280 MockWrite data_writes2[] = {
3281 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3282 "Host: www.google.com\r\n"
3283 "Connection: keep-alive\r\n"
3284 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3285 };
3286
3287 // Sever accepts the authorization.
3288 MockRead data_reads2[] = {
3289 MockRead("HTTP/1.0 200 OK\r\n"),
3290 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423291 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233292 };
3293
[email protected]31a2bfe2010-02-09 08:03:393294 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3295 data_writes1, arraysize(data_writes1));
3296 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3297 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593298 session_deps.socket_factory.AddSocketDataProvider(&data1);
3299 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233300
3301 TestCompletionCallback callback1;
3302
[email protected]5a1d7ca2010-04-28 20:12:273303 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423304 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233305
3306 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423307 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233308
[email protected]1c773ea12009-04-28 19:58:423309 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233310 EXPECT_FALSE(response == NULL);
3311
3312 // The password prompt info should have been set in
3313 // response->auth_challenge.
3314 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3315
[email protected]71e4573a2009-05-21 22:03:003316 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233317 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3318 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3319
3320 TestCompletionCallback callback2;
3321
[email protected]13c8a092010-07-29 06:15:443322 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423323 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233324
3325 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423326 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233327
3328 response = trans->GetResponseInfo();
3329 EXPECT_FALSE(response == NULL);
3330 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3331 EXPECT_EQ(100, response->headers->GetContentLength());
3332 }
3333
3334 // ------------------------------------------------------------------------
3335
3336 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3337 {
[email protected]5695b8c2009-09-30 21:36:433338 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233339
[email protected]1c773ea12009-04-28 19:58:423340 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233341 request.method = "GET";
3342 // Note that Transaction 1 was at /x/y/z, so this is in the same
3343 // protection space as MyRealm1.
3344 request.url = GURL("http://www.google.com/x/y/a/b");
3345 request.load_flags = 0;
3346
3347 MockWrite data_writes1[] = {
3348 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3349 "Host: www.google.com\r\n"
3350 "Connection: keep-alive\r\n"
3351 // Send preemptive authorization for MyRealm1
3352 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3353 };
3354
3355 // The server didn't like the preemptive authorization, and
3356 // challenges us for a different realm (MyRealm2).
3357 MockRead data_reads1[] = {
3358 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3359 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3360 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423361 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233362 };
3363
3364 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3365 MockWrite data_writes2[] = {
3366 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3367 "Host: www.google.com\r\n"
3368 "Connection: keep-alive\r\n"
3369 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3370 };
3371
3372 // Sever accepts the authorization.
3373 MockRead data_reads2[] = {
3374 MockRead("HTTP/1.0 200 OK\r\n"),
3375 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423376 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233377 };
3378
[email protected]31a2bfe2010-02-09 08:03:393379 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3380 data_writes1, arraysize(data_writes1));
3381 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3382 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593383 session_deps.socket_factory.AddSocketDataProvider(&data1);
3384 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233385
3386 TestCompletionCallback callback1;
3387
[email protected]5a1d7ca2010-04-28 20:12:273388 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423389 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233390
3391 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423392 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233393
[email protected]1c773ea12009-04-28 19:58:423394 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233395 EXPECT_FALSE(response == NULL);
3396
3397 // The password prompt info should have been set in
3398 // response->auth_challenge.
3399 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3400
[email protected]71e4573a2009-05-21 22:03:003401 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233402 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3403 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3404
3405 TestCompletionCallback callback2;
3406
[email protected]13c8a092010-07-29 06:15:443407 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233409
3410 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423411 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233412
3413 response = trans->GetResponseInfo();
3414 EXPECT_FALSE(response == NULL);
3415 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3416 EXPECT_EQ(100, response->headers->GetContentLength());
3417 }
3418
3419 // ------------------------------------------------------------------------
3420
3421 // Transaction 3: Resend a request in MyRealm's protection space --
3422 // succeed with preemptive authorization.
3423 {
[email protected]5695b8c2009-09-30 21:36:433424 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233425
[email protected]1c773ea12009-04-28 19:58:423426 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233427 request.method = "GET";
3428 request.url = GURL("http://www.google.com/x/y/z2");
3429 request.load_flags = 0;
3430
3431 MockWrite data_writes1[] = {
3432 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3433 "Host: www.google.com\r\n"
3434 "Connection: keep-alive\r\n"
3435 // The authorization for MyRealm1 gets sent preemptively
3436 // (since the url is in the same protection space)
3437 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3438 };
3439
3440 // Sever accepts the preemptive authorization
3441 MockRead data_reads1[] = {
3442 MockRead("HTTP/1.0 200 OK\r\n"),
3443 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423444 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233445 };
3446
[email protected]31a2bfe2010-02-09 08:03:393447 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3448 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593449 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233450
3451 TestCompletionCallback callback1;
3452
[email protected]5a1d7ca2010-04-28 20:12:273453 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423454 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233455
3456 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423457 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233458
[email protected]1c773ea12009-04-28 19:58:423459 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233460 EXPECT_FALSE(response == NULL);
3461
3462 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3463 EXPECT_EQ(100, response->headers->GetContentLength());
3464 }
3465
3466 // ------------------------------------------------------------------------
3467
3468 // Transaction 4: request another URL in MyRealm (however the
3469 // url is not known to belong to the protection space, so no pre-auth).
3470 {
[email protected]5695b8c2009-09-30 21:36:433471 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233472
[email protected]1c773ea12009-04-28 19:58:423473 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233474 request.method = "GET";
3475 request.url = GURL("http://www.google.com/x/1");
3476 request.load_flags = 0;
3477
3478 MockWrite data_writes1[] = {
3479 MockWrite("GET /x/1 HTTP/1.1\r\n"
3480 "Host: www.google.com\r\n"
3481 "Connection: keep-alive\r\n\r\n"),
3482 };
3483
3484 MockRead data_reads1[] = {
3485 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3486 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3487 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423488 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233489 };
3490
3491 // Resend with authorization from MyRealm's cache.
3492 MockWrite data_writes2[] = {
3493 MockWrite("GET /x/1 HTTP/1.1\r\n"
3494 "Host: www.google.com\r\n"
3495 "Connection: keep-alive\r\n"
3496 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3497 };
3498
3499 // Sever accepts the authorization.
3500 MockRead data_reads2[] = {
3501 MockRead("HTTP/1.0 200 OK\r\n"),
3502 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423503 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233504 };
3505
[email protected]31a2bfe2010-02-09 08:03:393506 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3507 data_writes1, arraysize(data_writes1));
3508 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3509 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593510 session_deps.socket_factory.AddSocketDataProvider(&data1);
3511 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233512
3513 TestCompletionCallback callback1;
3514
[email protected]5a1d7ca2010-04-28 20:12:273515 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423516 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233517
3518 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423519 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233520
[email protected]0757e7702009-03-27 04:00:223521 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3522 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443523 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423524 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223525 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423526 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223527 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3528
[email protected]1c773ea12009-04-28 19:58:423529 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233530 EXPECT_FALSE(response == NULL);
3531 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3532 EXPECT_EQ(100, response->headers->GetContentLength());
3533 }
3534
3535 // ------------------------------------------------------------------------
3536
3537 // Transaction 5: request a URL in MyRealm, but the server rejects the
3538 // cached identity. Should invalidate and re-prompt.
3539 {
[email protected]5695b8c2009-09-30 21:36:433540 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233541
[email protected]1c773ea12009-04-28 19:58:423542 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233543 request.method = "GET";
3544 request.url = GURL("http://www.google.com/p/q/t");
3545 request.load_flags = 0;
3546
3547 MockWrite data_writes1[] = {
3548 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3549 "Host: www.google.com\r\n"
3550 "Connection: keep-alive\r\n\r\n"),
3551 };
3552
3553 MockRead data_reads1[] = {
3554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3556 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423557 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233558 };
3559
3560 // Resend with authorization from cache for MyRealm.
3561 MockWrite data_writes2[] = {
3562 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3563 "Host: www.google.com\r\n"
3564 "Connection: keep-alive\r\n"
3565 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3566 };
3567
3568 // Sever rejects the authorization.
3569 MockRead data_reads2[] = {
3570 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3571 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3572 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423573 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233574 };
3575
3576 // At this point we should prompt for new credentials for MyRealm.
3577 // Restart with username=foo3, password=foo4.
3578 MockWrite data_writes3[] = {
3579 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3580 "Host: www.google.com\r\n"
3581 "Connection: keep-alive\r\n"
3582 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3583 };
3584
3585 // Sever accepts the authorization.
3586 MockRead data_reads3[] = {
3587 MockRead("HTTP/1.0 200 OK\r\n"),
3588 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423589 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233590 };
3591
[email protected]31a2bfe2010-02-09 08:03:393592 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3593 data_writes1, arraysize(data_writes1));
3594 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3595 data_writes2, arraysize(data_writes2));
3596 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3597 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593598 session_deps.socket_factory.AddSocketDataProvider(&data1);
3599 session_deps.socket_factory.AddSocketDataProvider(&data2);
3600 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233601
3602 TestCompletionCallback callback1;
3603
[email protected]5a1d7ca2010-04-28 20:12:273604 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423605 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233606
3607 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423608 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233609
[email protected]0757e7702009-03-27 04:00:223610 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3611 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443612 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423613 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223614 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423615 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223616 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3617
[email protected]1c773ea12009-04-28 19:58:423618 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233619 EXPECT_FALSE(response == NULL);
3620
3621 // The password prompt info should have been set in
3622 // response->auth_challenge.
3623 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3624
[email protected]71e4573a2009-05-21 22:03:003625 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233626 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3627 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3628
[email protected]0757e7702009-03-27 04:00:223629 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233630
[email protected]13c8a092010-07-29 06:15:443631 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423632 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233633
[email protected]0757e7702009-03-27 04:00:223634 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423635 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233636
3637 response = trans->GetResponseInfo();
3638 EXPECT_FALSE(response == NULL);
3639 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3640 EXPECT_EQ(100, response->headers->GetContentLength());
3641 }
3642}
[email protected]89ceba9a2009-03-21 03:46:063643
[email protected]3c32c5f2010-05-18 15:18:123644// Tests that nonce count increments when multiple auth attempts
3645// are started with the same nonce.
3646TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3647 SessionDependencies session_deps;
3648 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3649 HttpAuthHandlerDigest::SetFixedCnonce(true);
3650
3651 // Transaction 1: authenticate (foo, bar) on MyRealm1
3652 {
3653 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3654
3655 HttpRequestInfo request;
3656 request.method = "GET";
3657 request.url = GURL("http://www.google.com/x/y/z");
3658 request.load_flags = 0;
3659
3660 MockWrite data_writes1[] = {
3661 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3662 "Host: www.google.com\r\n"
3663 "Connection: keep-alive\r\n\r\n"),
3664 };
3665
3666 MockRead data_reads1[] = {
3667 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3668 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3669 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3670 MockRead(false, OK),
3671 };
3672
3673 // Resend with authorization (username=foo, password=bar)
3674 MockWrite data_writes2[] = {
3675 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3676 "Host: www.google.com\r\n"
3677 "Connection: keep-alive\r\n"
3678 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3679 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3680 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3681 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3682 };
3683
3684 // Sever accepts the authorization.
3685 MockRead data_reads2[] = {
3686 MockRead("HTTP/1.0 200 OK\r\n"),
3687 MockRead(false, OK),
3688 };
3689
3690 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3691 data_writes1, arraysize(data_writes1));
3692 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3693 data_writes2, arraysize(data_writes2));
3694 session_deps.socket_factory.AddSocketDataProvider(&data1);
3695 session_deps.socket_factory.AddSocketDataProvider(&data2);
3696
3697 TestCompletionCallback callback1;
3698
3699 int rv = trans->Start(&request, &callback1, BoundNetLog());
3700 EXPECT_EQ(ERR_IO_PENDING, rv);
3701
3702 rv = callback1.WaitForResult();
3703 EXPECT_EQ(OK, rv);
3704
3705 const HttpResponseInfo* response = trans->GetResponseInfo();
3706 ASSERT_FALSE(response == NULL);
3707
3708 // The password prompt info should have been set in
3709 // response->auth_challenge.
3710 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3711
3712 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3713 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3714 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3715
3716 TestCompletionCallback callback2;
3717
[email protected]13c8a092010-07-29 06:15:443718 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123719 EXPECT_EQ(ERR_IO_PENDING, rv);
3720
3721 rv = callback2.WaitForResult();
3722 EXPECT_EQ(OK, rv);
3723
3724 response = trans->GetResponseInfo();
3725 ASSERT_FALSE(response == NULL);
3726 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3727 }
3728
3729 // ------------------------------------------------------------------------
3730
3731 // Transaction 2: Request another resource in digestive's protection space.
3732 // This will preemptively add an Authorization header which should have an
3733 // "nc" value of 2 (as compared to 1 in the first use.
3734 {
3735 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3736
3737 HttpRequestInfo request;
3738 request.method = "GET";
3739 // Note that Transaction 1 was at /x/y/z, so this is in the same
3740 // protection space as digest.
3741 request.url = GURL("http://www.google.com/x/y/a/b");
3742 request.load_flags = 0;
3743
3744 MockWrite data_writes1[] = {
3745 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3746 "Host: www.google.com\r\n"
3747 "Connection: keep-alive\r\n"
3748 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3749 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3750 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3751 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3752 };
3753
3754 // Sever accepts the authorization.
3755 MockRead data_reads1[] = {
3756 MockRead("HTTP/1.0 200 OK\r\n"),
3757 MockRead("Content-Length: 100\r\n\r\n"),
3758 MockRead(false, OK),
3759 };
3760
3761 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3762 data_writes1, arraysize(data_writes1));
3763 session_deps.socket_factory.AddSocketDataProvider(&data1);
3764
3765 TestCompletionCallback callback1;
3766
3767 int rv = trans->Start(&request, &callback1, BoundNetLog());
3768 EXPECT_EQ(ERR_IO_PENDING, rv);
3769
3770 rv = callback1.WaitForResult();
3771 EXPECT_EQ(OK, rv);
3772
3773 const HttpResponseInfo* response = trans->GetResponseInfo();
3774 ASSERT_FALSE(response == NULL);
3775 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3776 }
3777}
3778
[email protected]89ceba9a2009-03-21 03:46:063779// Test the ResetStateForRestart() private method.
3780TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3781 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593782 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403783 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433784 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063785
3786 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063787 trans->read_buf_ = new IOBuffer(15);
3788 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573789 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063790
3791 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143792 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573793 response->auth_challenge = new AuthChallengeInfo();
3794 response->ssl_info.cert_status = -15;
3795 response->response_time = base::Time::Now();
3796 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063797
3798 { // Setup state for response_.vary_data
3799 HttpRequestInfo request;
3800 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3801 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573802 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433803 request.extra_headers.SetHeader("Foo", "1");
3804 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573805 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063806 }
3807
3808 // Cause the above state to be reset.
3809 trans->ResetStateForRestart();
3810
3811 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073812 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063813 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573814 EXPECT_EQ(0U, trans->request_headers_.size());
3815 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3816 EXPECT_TRUE(response->headers.get() == NULL);
3817 EXPECT_EQ(false, response->was_cached);
3818 EXPECT_EQ(0, response->ssl_info.cert_status);
3819 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063820}
3821
[email protected]bacff652009-03-31 17:50:333822// Test HTTPS connections to a site with a bad certificate
3823TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593824 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403825 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433826 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333827
3828 HttpRequestInfo request;
3829 request.method = "GET";
3830 request.url = GURL("https://www.google.com/");
3831 request.load_flags = 0;
3832
3833 MockWrite data_writes[] = {
3834 MockWrite("GET / HTTP/1.1\r\n"
3835 "Host: www.google.com\r\n"
3836 "Connection: keep-alive\r\n\r\n"),
3837 };
3838
3839 MockRead data_reads[] = {
3840 MockRead("HTTP/1.0 200 OK\r\n"),
3841 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3842 MockRead("Content-Length: 100\r\n\r\n"),
3843 MockRead(false, OK),
3844 };
3845
[email protected]5ecc992a42009-11-11 01:41:593846 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393847 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3848 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593849 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3850 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333851
[email protected]5ecc992a42009-11-11 01:41:593852 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3853 session_deps.socket_factory.AddSocketDataProvider(&data);
3854 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3855 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333856
3857 TestCompletionCallback callback;
3858
[email protected]5a1d7ca2010-04-28 20:12:273859 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333860 EXPECT_EQ(ERR_IO_PENDING, rv);
3861
3862 rv = callback.WaitForResult();
3863 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3864
3865 rv = trans->RestartIgnoringLastError(&callback);
3866 EXPECT_EQ(ERR_IO_PENDING, rv);
3867
3868 rv = callback.WaitForResult();
3869 EXPECT_EQ(OK, rv);
3870
3871 const HttpResponseInfo* response = trans->GetResponseInfo();
3872
3873 EXPECT_FALSE(response == NULL);
3874 EXPECT_EQ(100, response->headers->GetContentLength());
3875}
3876
3877// Test HTTPS connections to a site with a bad certificate, going through a
3878// proxy
3879TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593880 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333881
3882 HttpRequestInfo request;
3883 request.method = "GET";
3884 request.url = GURL("https://www.google.com/");
3885 request.load_flags = 0;
3886
3887 MockWrite proxy_writes[] = {
3888 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453889 "Host: www.google.com\r\n"
3890 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333891 };
3892
3893 MockRead proxy_reads[] = {
3894 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423895 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333896 };
3897
3898 MockWrite data_writes[] = {
3899 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453900 "Host: www.google.com\r\n"
3901 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333902 MockWrite("GET / HTTP/1.1\r\n"
3903 "Host: www.google.com\r\n"
3904 "Connection: keep-alive\r\n\r\n"),
3905 };
3906
3907 MockRead data_reads[] = {
3908 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3909 MockRead("HTTP/1.0 200 OK\r\n"),
3910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3911 MockRead("Content-Length: 100\r\n\r\n"),
3912 MockRead(false, OK),
3913 };
3914
[email protected]31a2bfe2010-02-09 08:03:393915 StaticSocketDataProvider ssl_bad_certificate(
3916 proxy_reads, arraysize(proxy_reads),
3917 proxy_writes, arraysize(proxy_writes));
3918 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3919 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593920 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3921 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333922
[email protected]5ecc992a42009-11-11 01:41:593923 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3924 session_deps.socket_factory.AddSocketDataProvider(&data);
3925 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3926 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333927
3928 TestCompletionCallback callback;
3929
3930 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593931 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333932
[email protected]d207a5f2009-06-04 05:28:403933 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433934 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333935
[email protected]5a1d7ca2010-04-28 20:12:273936 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333937 EXPECT_EQ(ERR_IO_PENDING, rv);
3938
3939 rv = callback.WaitForResult();
3940 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3941
3942 rv = trans->RestartIgnoringLastError(&callback);
3943 EXPECT_EQ(ERR_IO_PENDING, rv);
3944
3945 rv = callback.WaitForResult();
3946 EXPECT_EQ(OK, rv);
3947
3948 const HttpResponseInfo* response = trans->GetResponseInfo();
3949
3950 EXPECT_FALSE(response == NULL);
3951 EXPECT_EQ(100, response->headers->GetContentLength());
3952 }
3953}
3954
[email protected]2df19bb2010-08-25 20:13:463955
3956// Test HTTPS connections to a site, going through an HTTPS proxy
3957TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
3958 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
3959
3960 HttpRequestInfo request;
3961 request.method = "GET";
3962 request.url = GURL("https://www.google.com/");
3963 request.load_flags = 0;
3964
3965 MockWrite data_writes[] = {
3966 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3967 "Host: www.google.com\r\n"
3968 "Proxy-Connection: keep-alive\r\n\r\n"),
3969 MockWrite("GET / HTTP/1.1\r\n"
3970 "Host: www.google.com\r\n"
3971 "Connection: keep-alive\r\n\r\n"),
3972 };
3973
3974 MockRead data_reads[] = {
3975 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3976 MockRead("HTTP/1.1 200 OK\r\n"),
3977 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3978 MockRead("Content-Length: 100\r\n\r\n"),
3979 MockRead(false, OK),
3980 };
3981
3982 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3983 data_writes, arraysize(data_writes));
3984 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
3985 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
3986
3987 session_deps.socket_factory.AddSocketDataProvider(&data);
3988 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
3989 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
3990
3991 TestCompletionCallback callback;
3992
3993 scoped_ptr<HttpTransaction> trans(
3994 new HttpNetworkTransaction(CreateSession(&session_deps)));
3995
3996 int rv = trans->Start(&request, &callback, BoundNetLog());
3997 EXPECT_EQ(ERR_IO_PENDING, rv);
3998
3999 rv = callback.WaitForResult();
4000 EXPECT_EQ(OK, rv);
4001 const HttpResponseInfo* response = trans->GetResponseInfo();
4002
4003 ASSERT_FALSE(response == NULL);
4004
4005 EXPECT_TRUE(response->headers->IsKeepAlive());
4006 EXPECT_EQ(200, response->headers->response_code());
4007 EXPECT_EQ(100, response->headers->GetContentLength());
4008 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4009}
4010
4011// Test HTTPS connections to a site with a bad certificate, going through an
4012// HTTPS proxy
4013TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
4014 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
4015
4016 HttpRequestInfo request;
4017 request.method = "GET";
4018 request.url = GURL("https://www.google.com/");
4019 request.load_flags = 0;
4020
4021 // Attempt to fetch the URL from a server with a bad cert
4022 MockWrite bad_cert_writes[] = {
4023 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4024 "Host: www.google.com\r\n"
4025 "Proxy-Connection: keep-alive\r\n\r\n"),
4026 };
4027
4028 MockRead bad_cert_reads[] = {
4029 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4030 MockRead(false, OK)
4031 };
4032
4033 // Attempt to fetch the URL with a good cert
4034 MockWrite good_data_writes[] = {
4035 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4036 "Host: www.google.com\r\n"
4037 "Proxy-Connection: keep-alive\r\n\r\n"),
4038 MockWrite("GET / HTTP/1.1\r\n"
4039 "Host: www.google.com\r\n"
4040 "Connection: keep-alive\r\n\r\n"),
4041 };
4042
4043 MockRead good_cert_reads[] = {
4044 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4045 MockRead("HTTP/1.0 200 OK\r\n"),
4046 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4047 MockRead("Content-Length: 100\r\n\r\n"),
4048 MockRead(false, OK),
4049 };
4050
4051 StaticSocketDataProvider ssl_bad_certificate(
4052 bad_cert_reads, arraysize(bad_cert_reads),
4053 bad_cert_writes, arraysize(bad_cert_writes));
4054 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4055 good_data_writes, arraysize(good_data_writes));
4056 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4057 SSLSocketDataProvider ssl(true, OK);
4058
4059 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4060 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4061 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4062 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4063
4064 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4065 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4066 session_deps.socket_factory.AddSocketDataProvider(&data);
4067 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4068
4069 TestCompletionCallback callback;
4070
4071 scoped_ptr<HttpTransaction> trans(
4072 new HttpNetworkTransaction(CreateSession(&session_deps)));
4073
4074 int rv = trans->Start(&request, &callback, BoundNetLog());
4075 EXPECT_EQ(ERR_IO_PENDING, rv);
4076
4077 rv = callback.WaitForResult();
4078 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4079
4080 rv = trans->RestartIgnoringLastError(&callback);
4081 EXPECT_EQ(ERR_IO_PENDING, rv);
4082
4083 rv = callback.WaitForResult();
4084 EXPECT_EQ(OK, rv);
4085
4086 const HttpResponseInfo* response = trans->GetResponseInfo();
4087
4088 EXPECT_FALSE(response == NULL);
4089 EXPECT_EQ(100, response->headers->GetContentLength());
4090}
4091
[email protected]1c773ea12009-04-28 19:58:424092TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594093 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404094 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434095 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424096
4097 HttpRequestInfo request;
4098 request.method = "GET";
4099 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434100 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4101 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424102
4103 MockWrite data_writes[] = {
4104 MockWrite("GET / HTTP/1.1\r\n"
4105 "Host: www.google.com\r\n"
4106 "Connection: keep-alive\r\n"
4107 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4108 };
4109
4110 // Lastly, the server responds with the actual content.
4111 MockRead data_reads[] = {
4112 MockRead("HTTP/1.0 200 OK\r\n"),
4113 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4114 MockRead("Content-Length: 100\r\n\r\n"),
4115 MockRead(false, OK),
4116 };
4117
[email protected]31a2bfe2010-02-09 08:03:394118 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4119 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594120 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424121
4122 TestCompletionCallback callback;
4123
[email protected]5a1d7ca2010-04-28 20:12:274124 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424125 EXPECT_EQ(ERR_IO_PENDING, rv);
4126
4127 rv = callback.WaitForResult();
4128 EXPECT_EQ(OK, rv);
4129}
4130
[email protected]da81f132010-08-18 23:39:294131TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
4132 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4133 scoped_ptr<HttpTransaction> trans(
4134 new HttpNetworkTransaction(CreateSession(&session_deps)));
4135
4136 HttpRequestInfo request;
4137 request.method = "GET";
4138 request.url = GURL("https://www.google.com/");
4139 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4140 "Chromium Ultra Awesome X Edition");
4141
4142 MockWrite data_writes[] = {
4143 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4144 "Host: www.google.com\r\n"
4145 "Proxy-Connection: keep-alive\r\n"
4146 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4147 };
4148 MockRead data_reads[] = {
4149 // Return an error, so the transaction stops here (this test isn't
4150 // interested in the rest).
4151 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4152 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4153 MockRead("Proxy-Connection: close\r\n\r\n"),
4154 };
4155
4156 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4157 data_writes, arraysize(data_writes));
4158 session_deps.socket_factory.AddSocketDataProvider(&data);
4159
4160 TestCompletionCallback callback;
4161
4162 int rv = trans->Start(&request, &callback, BoundNetLog());
4163 EXPECT_EQ(ERR_IO_PENDING, rv);
4164
4165 rv = callback.WaitForResult();
4166 EXPECT_EQ(OK, rv);
4167}
4168
[email protected]1c773ea12009-04-28 19:58:424169TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594170 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404171 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434172 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424173
4174 HttpRequestInfo request;
4175 request.method = "GET";
4176 request.url = GURL("http://www.google.com/");
4177 request.load_flags = 0;
4178 request.referrer = GURL("http://the.previous.site.com/");
4179
4180 MockWrite data_writes[] = {
4181 MockWrite("GET / HTTP/1.1\r\n"
4182 "Host: www.google.com\r\n"
4183 "Connection: keep-alive\r\n"
4184 "Referer: http://the.previous.site.com/\r\n\r\n"),
4185 };
4186
4187 // Lastly, the server responds with the actual content.
4188 MockRead data_reads[] = {
4189 MockRead("HTTP/1.0 200 OK\r\n"),
4190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4191 MockRead("Content-Length: 100\r\n\r\n"),
4192 MockRead(false, OK),
4193 };
4194
[email protected]31a2bfe2010-02-09 08:03:394195 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4196 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594197 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424198
4199 TestCompletionCallback callback;
4200
[email protected]5a1d7ca2010-04-28 20:12:274201 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424202 EXPECT_EQ(ERR_IO_PENDING, rv);
4203
4204 rv = callback.WaitForResult();
4205 EXPECT_EQ(OK, rv);
4206}
4207
4208TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594209 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404210 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434211 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424212
4213 HttpRequestInfo request;
4214 request.method = "POST";
4215 request.url = GURL("http://www.google.com/");
4216
4217 MockWrite data_writes[] = {
4218 MockWrite("POST / HTTP/1.1\r\n"
4219 "Host: www.google.com\r\n"
4220 "Connection: keep-alive\r\n"
4221 "Content-Length: 0\r\n\r\n"),
4222 };
4223
4224 // Lastly, the server responds with the actual content.
4225 MockRead data_reads[] = {
4226 MockRead("HTTP/1.0 200 OK\r\n"),
4227 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4228 MockRead("Content-Length: 100\r\n\r\n"),
4229 MockRead(false, OK),
4230 };
4231
[email protected]31a2bfe2010-02-09 08:03:394232 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4233 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594234 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424235
4236 TestCompletionCallback callback;
4237
[email protected]5a1d7ca2010-04-28 20:12:274238 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424239 EXPECT_EQ(ERR_IO_PENDING, rv);
4240
4241 rv = callback.WaitForResult();
4242 EXPECT_EQ(OK, rv);
4243}
4244
4245TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594246 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404247 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434248 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424249
4250 HttpRequestInfo request;
4251 request.method = "PUT";
4252 request.url = GURL("http://www.google.com/");
4253
4254 MockWrite data_writes[] = {
4255 MockWrite("PUT / HTTP/1.1\r\n"
4256 "Host: www.google.com\r\n"
4257 "Connection: keep-alive\r\n"
4258 "Content-Length: 0\r\n\r\n"),
4259 };
4260
4261 // Lastly, the server responds with the actual content.
4262 MockRead data_reads[] = {
4263 MockRead("HTTP/1.0 200 OK\r\n"),
4264 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4265 MockRead("Content-Length: 100\r\n\r\n"),
4266 MockRead(false, OK),
4267 };
4268
[email protected]31a2bfe2010-02-09 08:03:394269 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4270 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594271 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424272
4273 TestCompletionCallback callback;
4274
[email protected]5a1d7ca2010-04-28 20:12:274275 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424276 EXPECT_EQ(ERR_IO_PENDING, rv);
4277
4278 rv = callback.WaitForResult();
4279 EXPECT_EQ(OK, rv);
4280}
4281
4282TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594283 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404284 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434285 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424286
4287 HttpRequestInfo request;
4288 request.method = "HEAD";
4289 request.url = GURL("http://www.google.com/");
4290
4291 MockWrite data_writes[] = {
4292 MockWrite("HEAD / HTTP/1.1\r\n"
4293 "Host: www.google.com\r\n"
4294 "Connection: keep-alive\r\n"
4295 "Content-Length: 0\r\n\r\n"),
4296 };
4297
4298 // Lastly, the server responds with the actual content.
4299 MockRead data_reads[] = {
4300 MockRead("HTTP/1.0 200 OK\r\n"),
4301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4302 MockRead("Content-Length: 100\r\n\r\n"),
4303 MockRead(false, OK),
4304 };
4305
[email protected]31a2bfe2010-02-09 08:03:394306 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4307 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594308 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424309
4310 TestCompletionCallback callback;
4311
[email protected]5a1d7ca2010-04-28 20:12:274312 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424313 EXPECT_EQ(ERR_IO_PENDING, rv);
4314
4315 rv = callback.WaitForResult();
4316 EXPECT_EQ(OK, rv);
4317}
4318
4319TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594320 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404321 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434322 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424323
4324 HttpRequestInfo request;
4325 request.method = "GET";
4326 request.url = GURL("http://www.google.com/");
4327 request.load_flags = LOAD_BYPASS_CACHE;
4328
4329 MockWrite data_writes[] = {
4330 MockWrite("GET / HTTP/1.1\r\n"
4331 "Host: www.google.com\r\n"
4332 "Connection: keep-alive\r\n"
4333 "Pragma: no-cache\r\n"
4334 "Cache-Control: no-cache\r\n\r\n"),
4335 };
4336
4337 // Lastly, the server responds with the actual content.
4338 MockRead data_reads[] = {
4339 MockRead("HTTP/1.0 200 OK\r\n"),
4340 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4341 MockRead("Content-Length: 100\r\n\r\n"),
4342 MockRead(false, OK),
4343 };
4344
[email protected]31a2bfe2010-02-09 08:03:394345 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4346 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594347 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424348
4349 TestCompletionCallback callback;
4350
[email protected]5a1d7ca2010-04-28 20:12:274351 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424352 EXPECT_EQ(ERR_IO_PENDING, rv);
4353
4354 rv = callback.WaitForResult();
4355 EXPECT_EQ(OK, rv);
4356}
4357
4358TEST_F(HttpNetworkTransactionTest,
4359 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594360 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404361 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434362 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424363
4364 HttpRequestInfo request;
4365 request.method = "GET";
4366 request.url = GURL("http://www.google.com/");
4367 request.load_flags = LOAD_VALIDATE_CACHE;
4368
4369 MockWrite data_writes[] = {
4370 MockWrite("GET / HTTP/1.1\r\n"
4371 "Host: www.google.com\r\n"
4372 "Connection: keep-alive\r\n"
4373 "Cache-Control: max-age=0\r\n\r\n"),
4374 };
4375
4376 // Lastly, the server responds with the actual content.
4377 MockRead data_reads[] = {
4378 MockRead("HTTP/1.0 200 OK\r\n"),
4379 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4380 MockRead("Content-Length: 100\r\n\r\n"),
4381 MockRead(false, OK),
4382 };
4383
[email protected]31a2bfe2010-02-09 08:03:394384 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4385 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594386 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424387
4388 TestCompletionCallback callback;
4389
[email protected]5a1d7ca2010-04-28 20:12:274390 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424391 EXPECT_EQ(ERR_IO_PENDING, rv);
4392
4393 rv = callback.WaitForResult();
4394 EXPECT_EQ(OK, rv);
4395}
4396
4397TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594398 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404399 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434400 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424401
4402 HttpRequestInfo request;
4403 request.method = "GET";
4404 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434405 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424406
4407 MockWrite data_writes[] = {
4408 MockWrite("GET / HTTP/1.1\r\n"
4409 "Host: www.google.com\r\n"
4410 "Connection: keep-alive\r\n"
4411 "FooHeader: Bar\r\n\r\n"),
4412 };
4413
4414 // Lastly, the server responds with the actual content.
4415 MockRead data_reads[] = {
4416 MockRead("HTTP/1.0 200 OK\r\n"),
4417 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4418 MockRead("Content-Length: 100\r\n\r\n"),
4419 MockRead(false, OK),
4420 };
4421
[email protected]31a2bfe2010-02-09 08:03:394422 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4423 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594424 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424425
4426 TestCompletionCallback callback;
4427
[email protected]5a1d7ca2010-04-28 20:12:274428 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424429 EXPECT_EQ(ERR_IO_PENDING, rv);
4430
4431 rv = callback.WaitForResult();
4432 EXPECT_EQ(OK, rv);
4433}
4434
[email protected]270c6412010-03-29 22:02:474435TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4436 SessionDependencies session_deps;
4437 scoped_ptr<HttpTransaction> trans(
4438 new HttpNetworkTransaction(CreateSession(&session_deps)));
4439
4440 HttpRequestInfo request;
4441 request.method = "GET";
4442 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434443 request.extra_headers.SetHeader("referer", "www.foo.com");
4444 request.extra_headers.SetHeader("hEllo", "Kitty");
4445 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474446
4447 MockWrite data_writes[] = {
4448 MockWrite("GET / HTTP/1.1\r\n"
4449 "Host: www.google.com\r\n"
4450 "Connection: keep-alive\r\n"
4451 "hEllo: Kitty\r\n"
4452 "FoO: bar\r\n\r\n"),
4453 };
4454
4455 // Lastly, the server responds with the actual content.
4456 MockRead data_reads[] = {
4457 MockRead("HTTP/1.0 200 OK\r\n"),
4458 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4459 MockRead("Content-Length: 100\r\n\r\n"),
4460 MockRead(false, OK),
4461 };
4462
4463 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4464 data_writes, arraysize(data_writes));
4465 session_deps.socket_factory.AddSocketDataProvider(&data);
4466
4467 TestCompletionCallback callback;
4468
[email protected]5a1d7ca2010-04-28 20:12:274469 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474470 EXPECT_EQ(ERR_IO_PENDING, rv);
4471
4472 rv = callback.WaitForResult();
4473 EXPECT_EQ(OK, rv);
4474}
4475
[email protected]3cd17242009-06-23 02:59:024476TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094477 SessionDependencies session_deps(
4478 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024479
4480 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434481 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024482
4483 HttpRequestInfo request;
4484 request.method = "GET";
4485 request.url = GURL("http://www.google.com/");
4486 request.load_flags = 0;
4487
4488 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4489 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4490
4491 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354492 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024493 MockWrite("GET / HTTP/1.1\r\n"
4494 "Host: www.google.com\r\n"
4495 "Connection: keep-alive\r\n\r\n")
4496 };
4497
4498 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594499 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024500 MockRead("HTTP/1.0 200 OK\r\n"),
4501 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4502 MockRead("Payload"),
4503 MockRead(false, OK)
4504 };
4505
[email protected]31a2bfe2010-02-09 08:03:394506 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4507 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594508 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024509
4510 TestCompletionCallback callback;
4511
[email protected]5a1d7ca2010-04-28 20:12:274512 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024513 EXPECT_EQ(ERR_IO_PENDING, rv);
4514
4515 rv = callback.WaitForResult();
4516 EXPECT_EQ(OK, rv);
4517
4518 const HttpResponseInfo* response = trans->GetResponseInfo();
4519 EXPECT_FALSE(response == NULL);
4520
4521 std::string response_text;
4522 rv = ReadTransaction(trans.get(), &response_text);
4523 EXPECT_EQ(OK, rv);
4524 EXPECT_EQ("Payload", response_text);
4525}
4526
4527TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094528 SessionDependencies session_deps(
4529 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024530
4531 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434532 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024533
4534 HttpRequestInfo request;
4535 request.method = "GET";
4536 request.url = GURL("https://www.google.com/");
4537 request.load_flags = 0;
4538
4539 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4540 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4541
4542 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354543 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4544 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024545 MockWrite("GET / HTTP/1.1\r\n"
4546 "Host: www.google.com\r\n"
4547 "Connection: keep-alive\r\n\r\n")
4548 };
4549
4550 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354551 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4552 arraysize(read_buffer)),
4553 MockRead("HTTP/1.0 200 OK\r\n"),
4554 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4555 MockRead("Payload"),
4556 MockRead(false, OK)
4557 };
4558
[email protected]31a2bfe2010-02-09 08:03:394559 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4560 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594561 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354562
[email protected]5ecc992a42009-11-11 01:41:594563 SSLSocketDataProvider ssl(true, OK);
4564 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354565
4566 TestCompletionCallback callback;
4567
[email protected]5a1d7ca2010-04-28 20:12:274568 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354569 EXPECT_EQ(ERR_IO_PENDING, rv);
4570
4571 rv = callback.WaitForResult();
4572 EXPECT_EQ(OK, rv);
4573
4574 const HttpResponseInfo* response = trans->GetResponseInfo();
4575 EXPECT_FALSE(response == NULL);
4576
4577 std::string response_text;
4578 rv = ReadTransaction(trans.get(), &response_text);
4579 EXPECT_EQ(OK, rv);
4580 EXPECT_EQ("Payload", response_text);
4581}
4582
4583TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094584 SessionDependencies session_deps(
4585 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354586
4587 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434588 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354589
4590 HttpRequestInfo request;
4591 request.method = "GET";
4592 request.url = GURL("http://www.google.com/");
4593 request.load_flags = 0;
4594
4595 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4596 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374597 const char kSOCKS5OkRequest[] = {
4598 0x05, // Version
4599 0x01, // Command (CONNECT)
4600 0x00, // Reserved.
4601 0x03, // Address type (DOMAINNAME).
4602 0x0E, // Length of domain (14)
4603 // Domain string:
4604 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4605 0x00, 0x50, // 16-bit port (80)
4606 };
[email protected]e0c27be2009-07-15 13:09:354607 const char kSOCKS5OkResponse[] =
4608 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4609
4610 MockWrite data_writes[] = {
4611 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4612 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4613 MockWrite("GET / HTTP/1.1\r\n"
4614 "Host: www.google.com\r\n"
4615 "Connection: keep-alive\r\n\r\n")
4616 };
4617
4618 MockRead data_reads[] = {
4619 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4620 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4621 MockRead("HTTP/1.0 200 OK\r\n"),
4622 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4623 MockRead("Payload"),
4624 MockRead(false, OK)
4625 };
4626
[email protected]31a2bfe2010-02-09 08:03:394627 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4628 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594629 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354630
4631 TestCompletionCallback callback;
4632
[email protected]5a1d7ca2010-04-28 20:12:274633 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354634 EXPECT_EQ(ERR_IO_PENDING, rv);
4635
4636 rv = callback.WaitForResult();
4637 EXPECT_EQ(OK, rv);
4638
4639 const HttpResponseInfo* response = trans->GetResponseInfo();
4640 EXPECT_FALSE(response == NULL);
4641
4642 std::string response_text;
4643 rv = ReadTransaction(trans.get(), &response_text);
4644 EXPECT_EQ(OK, rv);
4645 EXPECT_EQ("Payload", response_text);
4646}
4647
4648TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094649 SessionDependencies session_deps(
4650 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354651
4652 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434653 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354654
4655 HttpRequestInfo request;
4656 request.method = "GET";
4657 request.url = GURL("https://www.google.com/");
4658 request.load_flags = 0;
4659
4660 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4661 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374662 const unsigned char kSOCKS5OkRequest[] = {
4663 0x05, // Version
4664 0x01, // Command (CONNECT)
4665 0x00, // Reserved.
4666 0x03, // Address type (DOMAINNAME).
4667 0x0E, // Length of domain (14)
4668 // Domain string:
4669 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4670 0x01, 0xBB, // 16-bit port (443)
4671 };
4672
[email protected]e0c27be2009-07-15 13:09:354673 const char kSOCKS5OkResponse[] =
4674 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4675
4676 MockWrite data_writes[] = {
4677 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4678 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4679 arraysize(kSOCKS5OkRequest)),
4680 MockWrite("GET / HTTP/1.1\r\n"
4681 "Host: www.google.com\r\n"
4682 "Connection: keep-alive\r\n\r\n")
4683 };
4684
4685 MockRead data_reads[] = {
4686 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4687 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024688 MockRead("HTTP/1.0 200 OK\r\n"),
4689 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4690 MockRead("Payload"),
4691 MockRead(false, OK)
4692 };
4693
[email protected]31a2bfe2010-02-09 08:03:394694 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4695 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594696 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024697
[email protected]5ecc992a42009-11-11 01:41:594698 SSLSocketDataProvider ssl(true, OK);
4699 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024700
4701 TestCompletionCallback callback;
4702
[email protected]5a1d7ca2010-04-28 20:12:274703 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024704 EXPECT_EQ(ERR_IO_PENDING, rv);
4705
4706 rv = callback.WaitForResult();
4707 EXPECT_EQ(OK, rv);
4708
4709 const HttpResponseInfo* response = trans->GetResponseInfo();
4710 EXPECT_FALSE(response == NULL);
4711
4712 std::string response_text;
4713 rv = ReadTransaction(trans.get(), &response_text);
4714 EXPECT_EQ(OK, rv);
4715 EXPECT_EQ("Payload", response_text);
4716}
4717
[email protected]04e5be32009-06-26 20:00:314718// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064719
4720struct GroupNameTest {
4721 std::string proxy_server;
4722 std::string url;
4723 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184724 bool ssl;
[email protected]2d731a32010-04-29 01:04:064725};
4726
4727scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4728 const std::string& proxy_server) {
4729 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4730 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4731
4732 HttpAlternateProtocols* alternate_protocols =
4733 session->mutable_alternate_protocols();
4734 alternate_protocols->SetAlternateProtocolFor(
4735 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354736 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064737
4738 return session;
4739}
4740
4741int GroupNameTransactionHelper(
4742 const std::string& url,
4743 const scoped_refptr<HttpNetworkSession>& session) {
4744 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4745
4746 HttpRequestInfo request;
4747 request.method = "GET";
4748 request.url = GURL(url);
4749 request.load_flags = 0;
4750
4751 TestCompletionCallback callback;
4752
4753 // We do not complete this request, the dtor will clean the transaction up.
4754 return trans->Start(&request, &callback, BoundNetLog());
4755}
4756
4757TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4758 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314759 {
[email protected]2d731a32010-04-29 01:04:064760 "", // unused
[email protected]04e5be32009-06-26 20:00:314761 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544762 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184763 false,
[email protected]2ff8b312010-04-26 22:20:544764 },
4765 {
[email protected]2d731a32010-04-29 01:04:064766 "", // unused
[email protected]2ff8b312010-04-26 22:20:544767 "http://[2001:1418:13:1::25]/direct",
4768 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184769 false,
[email protected]04e5be32009-06-26 20:00:314770 },
[email protected]04e5be32009-06-26 20:00:314771
4772 // SSL Tests
4773 {
[email protected]2d731a32010-04-29 01:04:064774 "", // unused
[email protected]04e5be32009-06-26 20:00:314775 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024776 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184777 true,
[email protected]04e5be32009-06-26 20:00:314778 },
4779 {
[email protected]2d731a32010-04-29 01:04:064780 "", // unused
4781 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024782 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184783 true,
[email protected]04e5be32009-06-26 20:00:314784 },
4785 {
[email protected]2d731a32010-04-29 01:04:064786 "", // unused
[email protected]2ff8b312010-04-26 22:20:544787 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024788 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184789 true,
[email protected]2ff8b312010-04-26 22:20:544790 },
[email protected]2d731a32010-04-29 01:04:064791 };
[email protected]2ff8b312010-04-26 22:20:544792
[email protected]8e6441ca2010-08-19 05:56:384793 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064794
4795 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4796 scoped_refptr<HttpNetworkSession> session(
4797 SetupSessionForGroupNameTests(tests[i].proxy_server));
4798
4799 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:134800 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
4801 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:064802 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:134803 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
4804 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:184805 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064806
4807 EXPECT_EQ(ERR_IO_PENDING,
4808 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184809 if (tests[i].ssl)
4810 EXPECT_EQ(tests[i].expected_group_name,
4811 ssl_conn_pool->last_group_name_received());
4812 else
4813 EXPECT_EQ(tests[i].expected_group_name,
4814 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064815 }
4816
[email protected]8e6441ca2010-08-19 05:56:384817 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064818}
4819
4820TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4821 const GroupNameTest tests[] = {
4822 {
4823 "http_proxy",
4824 "http://www.google.com/http_proxy_normal",
4825 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184826 false,
[email protected]2d731a32010-04-29 01:04:064827 },
4828
4829 // SSL Tests
4830 {
4831 "http_proxy",
4832 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024833 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184834 true,
[email protected]2d731a32010-04-29 01:04:064835 },
4836
[email protected]9faeded92010-04-29 20:03:054837 {
4838 "http_proxy",
4839 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024840 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184841 true,
[email protected]9faeded92010-04-29 20:03:054842 },
[email protected]2d731a32010-04-29 01:04:064843 };
4844
[email protected]8e6441ca2010-08-19 05:56:384845 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064846
4847 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4848 scoped_refptr<HttpNetworkSession> session(
4849 SetupSessionForGroupNameTests(tests[i].proxy_server));
4850
4851 HttpNetworkSessionPeer peer(session);
4852
[email protected]e60e47a2010-07-14 03:37:184853 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:134854 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
4855 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184856 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:134857 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
4858 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184859 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064860
4861 EXPECT_EQ(ERR_IO_PENDING,
4862 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184863 if (tests[i].ssl)
4864 EXPECT_EQ(tests[i].expected_group_name,
4865 ssl_conn_pool->last_group_name_received());
4866 else
4867 EXPECT_EQ(tests[i].expected_group_name,
4868 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064869 }
4870
[email protected]8e6441ca2010-08-19 05:56:384871 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064872}
4873
4874TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4875 const GroupNameTest tests[] = {
4876 {
4877 "socks4://socks_proxy:1080",
4878 "http://www.google.com/socks4_direct",
4879 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184880 false,
[email protected]2d731a32010-04-29 01:04:064881 },
4882 {
4883 "socks5://socks_proxy:1080",
4884 "http://www.google.com/socks5_direct",
4885 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184886 false,
[email protected]2d731a32010-04-29 01:04:064887 },
4888
4889 // SSL Tests
4890 {
4891 "socks4://socks_proxy:1080",
4892 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024893 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184894 true,
[email protected]2d731a32010-04-29 01:04:064895 },
4896 {
4897 "socks5://socks_proxy:1080",
4898 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024899 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184900 true,
[email protected]2d731a32010-04-29 01:04:064901 },
4902
[email protected]9faeded92010-04-29 20:03:054903 {
4904 "socks4://socks_proxy:1080",
4905 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024906 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184907 true,
[email protected]9faeded92010-04-29 20:03:054908 },
[email protected]04e5be32009-06-26 20:00:314909 };
4910
[email protected]8e6441ca2010-08-19 05:56:384911 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:544912
[email protected]04e5be32009-06-26 20:00:314913 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064914 scoped_refptr<HttpNetworkSession> session(
4915 SetupSessionForGroupNameTests(tests[i].proxy_server));
4916 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314917
[email protected]e60e47a2010-07-14 03:37:184918 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:134919 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
4920 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184921 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:134922 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
4923 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184924 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314925
[email protected]5695b8c2009-09-30 21:36:434926 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314927
[email protected]2d731a32010-04-29 01:04:064928 EXPECT_EQ(ERR_IO_PENDING,
4929 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184930 if (tests[i].ssl)
4931 EXPECT_EQ(tests[i].expected_group_name,
4932 ssl_conn_pool->last_group_name_received());
4933 else
4934 EXPECT_EQ(tests[i].expected_group_name,
4935 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314936 }
[email protected]2ff8b312010-04-26 22:20:544937
[email protected]8e6441ca2010-08-19 05:56:384938 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:314939}
4940
[email protected]9172a982009-06-06 00:30:254941TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544942 SessionDependencies session_deps(
4943 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324944
[email protected]69719062010-01-05 20:09:214945 // This simulates failure resolving all hostnames; that means we will fail
4946 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324947 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4948
[email protected]9172a982009-06-06 00:30:254949 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434950 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254951
4952 HttpRequestInfo request;
4953 request.method = "GET";
4954 request.url = GURL("http://www.google.com/");
4955
4956 TestCompletionCallback callback;
4957
[email protected]5a1d7ca2010-04-28 20:12:274958 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254959 EXPECT_EQ(ERR_IO_PENDING, rv);
4960
[email protected]9172a982009-06-06 00:30:254961 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:014962 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:254963}
4964
[email protected]f3e6c1e2009-06-15 20:52:124965// Host resolution observer used by
4966// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4967// resovle requests are issued with a referrer of |expected_referrer|.
4968class ResolutionReferrerObserver : public HostResolver::Observer {
4969 public:
4970 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4971 : expected_referrer_(expected_referrer),
4972 called_start_with_referrer_(false),
4973 called_finish_with_referrer_(false) {
4974 }
4975
4976 virtual void OnStartResolution(int id,
4977 const HostResolver::RequestInfo& info) {
4978 if (info.referrer() == expected_referrer_)
4979 called_start_with_referrer_ = true;
4980 }
4981
4982 virtual void OnFinishResolutionWithStatus(
4983 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4984 if (info.referrer() == expected_referrer_)
4985 called_finish_with_referrer_ = true;
4986 }
4987
[email protected]eb255d32009-06-17 02:11:034988 virtual void OnCancelResolution(int id,
4989 const HostResolver::RequestInfo& info ) {
4990 FAIL() << "Should not be cancelling any requests!";
4991 }
4992
[email protected]f3e6c1e2009-06-15 20:52:124993 bool did_complete_with_expected_referrer() const {
4994 return called_start_with_referrer_ && called_finish_with_referrer_;
4995 }
4996
4997 private:
4998 GURL expected_referrer_;
4999 bool called_start_with_referrer_;
5000 bool called_finish_with_referrer_;
5001
5002 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5003};
5004
5005// Make sure that when HostResolver::Resolve() is invoked, it passes through
5006// the "referrer". This is depended on by the DNS prefetch observer.
5007TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5008 GURL referrer = GURL("http://expected-referrer/");
5009 EXPECT_TRUE(referrer.is_valid());
5010 ResolutionReferrerObserver resolution_observer(referrer);
5011
5012 SessionDependencies session_deps;
5013 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435014 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125015
5016 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145017 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125018
5019 // Connect up a mock socket which will fail when reading.
5020 MockRead data_reads[] = {
5021 MockRead(false, ERR_FAILED),
5022 };
[email protected]31a2bfe2010-02-09 08:03:395023 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595024 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125025
5026 // Issue a request, containing an HTTP referrer.
5027 HttpRequestInfo request;
5028 request.method = "GET";
5029 request.referrer = referrer;
5030 request.url = GURL("http://www.google.com/");
5031
5032 // Run the request until it fails reading from the socket.
5033 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275034 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125035 EXPECT_EQ(ERR_IO_PENDING, rv);
5036 rv = callback.WaitForResult();
5037 EXPECT_EQ(ERR_FAILED, rv);
5038
5039 // Check that the host resolution observer saw |referrer|.
5040 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5041}
5042
[email protected]685af592010-05-11 19:31:245043// Base test to make sure that when the load flags for a request specify to
5044// bypass the cache, the DNS cache is not used.
5045void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285046 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325047
[email protected]a2c2fb92009-07-18 07:31:045048 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545049 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325050
[email protected]3b9cca42009-06-16 01:08:285051 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435052 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285053
5054 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5055 // a synchronous lookup.)
5056 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145057 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105058 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275059 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285060 EXPECT_EQ(OK, rv);
5061
5062 // Verify that it was added to host cache, by doing a subsequent async lookup
5063 // and confirming it completes synchronously.
5064 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465065 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105066 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275067 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325068 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285069
5070 // Inject a failure the next time that "www.google.com" is resolved. This way
5071 // we can tell if the next lookup hit the cache, or the "network".
5072 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325073 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285074
5075 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5076 // first read -- this won't be reached as the host resolution will fail first.
5077 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395078 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595079 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285080
5081 // Issue a request, asking to bypass the cache(s).
5082 HttpRequestInfo request;
5083 request.method = "GET";
[email protected]685af592010-05-11 19:31:245084 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285085 request.url = GURL("http://www.google.com/");
5086
5087 // Run the request.
5088 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275089 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285090 ASSERT_EQ(ERR_IO_PENDING, rv);
5091 rv = callback.WaitForResult();
5092
5093 // If we bypassed the cache, we would have gotten a failure while resolving
5094 // "www.google.com".
5095 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5096}
5097
[email protected]685af592010-05-11 19:31:245098// There are multiple load flags that should trigger the host cache bypass.
5099// Test each in isolation:
5100TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5101 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5102}
5103
5104TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5105 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5106}
5107
5108TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5109 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5110}
5111
[email protected]0877e3d2009-10-17 22:29:575112// Make sure we can handle an error when writing the request.
5113TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5114 SessionDependencies session_deps;
5115 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5116
5117 HttpRequestInfo request;
5118 request.method = "GET";
5119 request.url = GURL("http://www.foo.com/");
5120 request.load_flags = 0;
5121
5122 MockWrite write_failure[] = {
5123 MockWrite(true, ERR_CONNECTION_RESET),
5124 };
[email protected]31a2bfe2010-02-09 08:03:395125 StaticSocketDataProvider data(NULL, 0,
5126 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595127 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575128
5129 TestCompletionCallback callback;
5130
5131 scoped_ptr<HttpTransaction> trans(
5132 new HttpNetworkTransaction(CreateSession(&session_deps)));
5133
[email protected]5a1d7ca2010-04-28 20:12:275134 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575135 EXPECT_EQ(ERR_IO_PENDING, rv);
5136
5137 rv = callback.WaitForResult();
5138 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5139}
5140
5141// Check that a connection closed after the start of the headers finishes ok.
5142TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5143 SessionDependencies session_deps;
5144 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5145
5146 HttpRequestInfo request;
5147 request.method = "GET";
5148 request.url = GURL("http://www.foo.com/");
5149 request.load_flags = 0;
5150
5151 MockRead data_reads[] = {
5152 MockRead("HTTP/1."),
5153 MockRead(false, OK),
5154 };
5155
[email protected]31a2bfe2010-02-09 08:03:395156 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595157 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575158
5159 TestCompletionCallback callback;
5160
5161 scoped_ptr<HttpTransaction> trans(
5162 new HttpNetworkTransaction(CreateSession(&session_deps)));
5163
[email protected]5a1d7ca2010-04-28 20:12:275164 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575165 EXPECT_EQ(ERR_IO_PENDING, rv);
5166
5167 rv = callback.WaitForResult();
5168 EXPECT_EQ(OK, rv);
5169
5170 const HttpResponseInfo* response = trans->GetResponseInfo();
5171 EXPECT_TRUE(response != NULL);
5172
5173 EXPECT_TRUE(response->headers != NULL);
5174 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5175
5176 std::string response_data;
5177 rv = ReadTransaction(trans.get(), &response_data);
5178 EXPECT_EQ(OK, rv);
5179 EXPECT_EQ("", response_data);
5180}
5181
5182// Make sure that a dropped connection while draining the body for auth
5183// restart does the right thing.
5184TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5185 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:505186 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]0877e3d2009-10-17 22:29:575187
5188 HttpRequestInfo request;
5189 request.method = "GET";
5190 request.url = GURL("http://www.google.com/");
5191 request.load_flags = 0;
5192
5193 MockWrite data_writes1[] = {
5194 MockWrite("GET / HTTP/1.1\r\n"
5195 "Host: www.google.com\r\n"
5196 "Connection: keep-alive\r\n\r\n"),
5197 };
5198
5199 MockRead data_reads1[] = {
5200 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5201 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5202 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5203 MockRead("Content-Length: 14\r\n\r\n"),
5204 MockRead("Unauth"),
5205 MockRead(true, ERR_CONNECTION_RESET),
5206 };
5207
[email protected]31a2bfe2010-02-09 08:03:395208 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5209 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595210 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575211
5212 // After calling trans->RestartWithAuth(), this is the request we should
5213 // be issuing -- the final header line contains the credentials.
5214 MockWrite data_writes2[] = {
5215 MockWrite("GET / HTTP/1.1\r\n"
5216 "Host: www.google.com\r\n"
5217 "Connection: keep-alive\r\n"
5218 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5219 };
5220
5221 // Lastly, the server responds with the actual content.
5222 MockRead data_reads2[] = {
5223 MockRead("HTTP/1.1 200 OK\r\n"),
5224 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5225 MockRead("Content-Length: 100\r\n\r\n"),
5226 MockRead(false, OK),
5227 };
5228
[email protected]31a2bfe2010-02-09 08:03:395229 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5230 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595231 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575232
5233 TestCompletionCallback callback1;
5234
[email protected]0b0bf032010-09-21 18:08:505235 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5236
[email protected]5a1d7ca2010-04-28 20:12:275237 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575238 EXPECT_EQ(ERR_IO_PENDING, rv);
5239
5240 rv = callback1.WaitForResult();
5241 EXPECT_EQ(OK, rv);
5242
5243 const HttpResponseInfo* response = trans->GetResponseInfo();
5244 EXPECT_FALSE(response == NULL);
5245
5246 // The password prompt info should have been set in response->auth_challenge.
5247 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5248
5249 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5250 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5251 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5252
5253 TestCompletionCallback callback2;
5254
[email protected]13c8a092010-07-29 06:15:445255 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575256 EXPECT_EQ(ERR_IO_PENDING, rv);
5257
5258 rv = callback2.WaitForResult();
5259 EXPECT_EQ(OK, rv);
5260
5261 response = trans->GetResponseInfo();
5262 EXPECT_FALSE(response == NULL);
5263 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5264 EXPECT_EQ(100, response->headers->GetContentLength());
5265}
5266
5267// Test HTTPS connections going through a proxy that sends extra data.
5268TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
5269 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
5270
5271 HttpRequestInfo request;
5272 request.method = "GET";
5273 request.url = GURL("https://www.google.com/");
5274 request.load_flags = 0;
5275
5276 MockRead proxy_reads[] = {
5277 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5278 MockRead(false, OK)
5279 };
5280
[email protected]31a2bfe2010-02-09 08:03:395281 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595282 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575283
[email protected]5ecc992a42009-11-11 01:41:595284 session_deps.socket_factory.AddSocketDataProvider(&data);
5285 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575286
5287 TestCompletionCallback callback;
5288
5289 session_deps.socket_factory.ResetNextMockIndexes();
5290
5291 scoped_ptr<HttpTransaction> trans(
5292 new HttpNetworkTransaction(CreateSession(&session_deps)));
5293
[email protected]5a1d7ca2010-04-28 20:12:275294 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575295 EXPECT_EQ(ERR_IO_PENDING, rv);
5296
5297 rv = callback.WaitForResult();
5298 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5299}
5300
[email protected]e22e1362009-11-23 21:31:125301TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465302 SessionDependencies session_deps;
5303 scoped_ptr<HttpTransaction> trans(
5304 new HttpNetworkTransaction(CreateSession(&session_deps)));
5305
5306 HttpRequestInfo request;
5307 request.method = "GET";
5308 request.url = GURL("http://www.google.com/");
5309 request.load_flags = 0;
5310
[email protected]e22e1362009-11-23 21:31:125311 MockRead data_reads[] = {
5312 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5313 MockRead(false, OK),
5314 };
[email protected]9492e4a2010-02-24 00:58:465315
5316 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5317 session_deps.socket_factory.AddSocketDataProvider(&data);
5318
5319 TestCompletionCallback callback;
5320
[email protected]5a1d7ca2010-04-28 20:12:275321 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465322 EXPECT_EQ(ERR_IO_PENDING, rv);
5323
5324 EXPECT_EQ(OK, callback.WaitForResult());
5325
5326 const HttpResponseInfo* response = trans->GetResponseInfo();
5327 EXPECT_TRUE(response != NULL);
5328
5329 EXPECT_TRUE(response->headers != NULL);
5330 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5331
5332 std::string response_data;
5333 rv = ReadTransaction(trans.get(), &response_data);
5334 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125335}
5336
[email protected]95d88ffe2010-02-04 21:25:335337TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5338 SessionDependencies session_deps;
5339 scoped_ptr<HttpTransaction> trans(
5340 new HttpNetworkTransaction(CreateSession(&session_deps)));
5341
5342 HttpRequestInfo request;
5343 request.method = "POST";
5344 request.url = GURL("http://www.google.com/upload");
5345 request.upload_data = new UploadData;
5346 request.load_flags = 0;
5347
5348 FilePath temp_file_path;
5349 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5350 const uint64 kFakeSize = 100000; // file is actually blank
5351
5352 std::vector<UploadData::Element> elements;
5353 UploadData::Element element;
5354 element.SetToFilePath(temp_file_path);
5355 element.SetContentLength(kFakeSize);
5356 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535357 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335358 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5359
5360 MockRead data_reads[] = {
5361 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5362 MockRead("hello world"),
5363 MockRead(false, OK),
5364 };
[email protected]31a2bfe2010-02-09 08:03:395365 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335366 session_deps.socket_factory.AddSocketDataProvider(&data);
5367
5368 TestCompletionCallback callback;
5369
[email protected]5a1d7ca2010-04-28 20:12:275370 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335371 EXPECT_EQ(ERR_IO_PENDING, rv);
5372
5373 rv = callback.WaitForResult();
5374 EXPECT_EQ(OK, rv);
5375
5376 const HttpResponseInfo* response = trans->GetResponseInfo();
5377 EXPECT_TRUE(response != NULL);
5378
5379 EXPECT_TRUE(response->headers != NULL);
5380 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5381
5382 std::string response_data;
5383 rv = ReadTransaction(trans.get(), &response_data);
5384 EXPECT_EQ(OK, rv);
5385 EXPECT_EQ("hello world", response_data);
5386
5387 file_util::Delete(temp_file_path, false);
5388}
5389
[email protected]6624b4622010-03-29 19:58:365390TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5391 // If we try to upload an unreadable file, the network stack should report
5392 // the file size as zero and upload zero bytes for that file.
5393 SessionDependencies session_deps;
5394 scoped_ptr<HttpTransaction> trans(
5395 new HttpNetworkTransaction(CreateSession(&session_deps)));
5396
5397 FilePath temp_file;
5398 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5399 std::string temp_file_content("Unreadable file.");
5400 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5401 temp_file_content.length()));
5402 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5403
5404 HttpRequestInfo request;
5405 request.method = "POST";
5406 request.url = GURL("http://www.google.com/upload");
5407 request.upload_data = new UploadData;
5408 request.load_flags = 0;
5409
5410 std::vector<UploadData::Element> elements;
5411 UploadData::Element element;
5412 element.SetToFilePath(temp_file);
5413 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535414 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365415
5416 MockRead data_reads[] = {
5417 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5418 MockRead(false, OK),
5419 };
5420 MockWrite data_writes[] = {
5421 MockWrite("POST /upload HTTP/1.1\r\n"
5422 "Host: www.google.com\r\n"
5423 "Connection: keep-alive\r\n"
5424 "Content-Length: 0\r\n\r\n"),
5425 MockWrite(false, OK),
5426 };
5427 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5428 arraysize(data_writes));
5429 session_deps.socket_factory.AddSocketDataProvider(&data);
5430
5431 TestCompletionCallback callback;
5432
[email protected]5a1d7ca2010-04-28 20:12:275433 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365434 EXPECT_EQ(ERR_IO_PENDING, rv);
5435
5436 rv = callback.WaitForResult();
5437 EXPECT_EQ(OK, rv);
5438
5439 const HttpResponseInfo* response = trans->GetResponseInfo();
5440 EXPECT_TRUE(response != NULL);
5441 EXPECT_TRUE(response->headers != NULL);
5442 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5443
5444 file_util::Delete(temp_file, false);
5445}
5446
5447TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5448 SessionDependencies session_deps;
5449 scoped_ptr<HttpTransaction> trans(
5450 new HttpNetworkTransaction(CreateSession(&session_deps)));
5451
5452 FilePath temp_file;
5453 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5454 std::string temp_file_contents("Unreadable file.");
5455 std::string unreadable_contents(temp_file_contents.length(), '\0');
5456 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5457 temp_file_contents.length()));
5458
5459 HttpRequestInfo request;
5460 request.method = "POST";
5461 request.url = GURL("http://www.google.com/upload");
5462 request.upload_data = new UploadData;
5463 request.load_flags = 0;
5464
5465 std::vector<UploadData::Element> elements;
5466 UploadData::Element element;
5467 element.SetToFilePath(temp_file);
5468 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535469 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365470
5471 MockRead data_reads[] = {
5472 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5474 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5475
5476 MockRead("HTTP/1.1 200 OK\r\n"),
5477 MockRead("Content-Length: 0\r\n\r\n"),
5478 MockRead(false, OK),
5479 };
5480 MockWrite data_writes[] = {
5481 MockWrite("POST /upload HTTP/1.1\r\n"
5482 "Host: www.google.com\r\n"
5483 "Connection: keep-alive\r\n"
5484 "Content-Length: 16\r\n\r\n"),
5485 MockWrite(false, temp_file_contents.c_str()),
5486
5487 MockWrite("POST /upload HTTP/1.1\r\n"
5488 "Host: www.google.com\r\n"
5489 "Connection: keep-alive\r\n"
5490 "Content-Length: 16\r\n"
5491 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5492 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5493 MockWrite(false, OK),
5494 };
5495 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5496 arraysize(data_writes));
5497 session_deps.socket_factory.AddSocketDataProvider(&data);
5498
5499 TestCompletionCallback callback1;
5500
[email protected]5a1d7ca2010-04-28 20:12:275501 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365502 EXPECT_EQ(ERR_IO_PENDING, rv);
5503
5504 rv = callback1.WaitForResult();
5505 EXPECT_EQ(OK, rv);
5506
5507 const HttpResponseInfo* response = trans->GetResponseInfo();
5508 EXPECT_TRUE(response != NULL);
5509 EXPECT_TRUE(response->headers != NULL);
5510 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5511
5512 // The password prompt info should have been set in response->auth_challenge.
5513 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5514 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5515 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5516 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5517
5518 // Now make the file unreadable and try again.
5519 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5520
5521 TestCompletionCallback callback2;
5522
[email protected]13c8a092010-07-29 06:15:445523 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365524 EXPECT_EQ(ERR_IO_PENDING, rv);
5525
5526 rv = callback2.WaitForResult();
5527 EXPECT_EQ(OK, rv);
5528
5529 response = trans->GetResponseInfo();
5530 EXPECT_TRUE(response != NULL);
5531 EXPECT_TRUE(response->headers != NULL);
5532 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5533 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5534
5535 file_util::Delete(temp_file, false);
5536}
5537
[email protected]aeefc9e82010-02-19 16:18:275538// Tests that changes to Auth realms are treated like auth rejections.
5539TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5540 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275541
5542 HttpRequestInfo request;
5543 request.method = "GET";
5544 request.url = GURL("http://www.google.com/");
5545 request.load_flags = 0;
5546
5547 // First transaction will request a resource and receive a Basic challenge
5548 // with realm="first_realm".
5549 MockWrite data_writes1[] = {
5550 MockWrite("GET / HTTP/1.1\r\n"
5551 "Host: www.google.com\r\n"
5552 "Connection: keep-alive\r\n"
5553 "\r\n"),
5554 };
5555 MockRead data_reads1[] = {
5556 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5557 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5558 "\r\n"),
5559 };
5560
5561 // After calling trans->RestartWithAuth(), provide an Authentication header
5562 // for first_realm. The server will reject and provide a challenge with
5563 // second_realm.
5564 MockWrite data_writes2[] = {
5565 MockWrite("GET / HTTP/1.1\r\n"
5566 "Host: www.google.com\r\n"
5567 "Connection: keep-alive\r\n"
5568 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5569 "\r\n"),
5570 };
5571 MockRead data_reads2[] = {
5572 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5573 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5574 "\r\n"),
5575 };
5576
5577 // This again fails, and goes back to first_realm. Make sure that the
5578 // entry is removed from cache.
5579 MockWrite data_writes3[] = {
5580 MockWrite("GET / HTTP/1.1\r\n"
5581 "Host: www.google.com\r\n"
5582 "Connection: keep-alive\r\n"
5583 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5584 "\r\n"),
5585 };
5586 MockRead data_reads3[] = {
5587 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5588 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5589 "\r\n"),
5590 };
5591
5592 // Try one last time (with the correct password) and get the resource.
5593 MockWrite data_writes4[] = {
5594 MockWrite("GET / HTTP/1.1\r\n"
5595 "Host: www.google.com\r\n"
5596 "Connection: keep-alive\r\n"
5597 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5598 "\r\n"),
5599 };
5600 MockRead data_reads4[] = {
5601 MockRead("HTTP/1.1 200 OK\r\n"
5602 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:505603 "Content-Length: 5\r\n"
5604 "\r\n"
5605 "hello"),
[email protected]aeefc9e82010-02-19 16:18:275606 };
5607
5608 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5609 data_writes1, arraysize(data_writes1));
5610 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5611 data_writes2, arraysize(data_writes2));
5612 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5613 data_writes3, arraysize(data_writes3));
5614 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5615 data_writes4, arraysize(data_writes4));
5616 session_deps.socket_factory.AddSocketDataProvider(&data1);
5617 session_deps.socket_factory.AddSocketDataProvider(&data2);
5618 session_deps.socket_factory.AddSocketDataProvider(&data3);
5619 session_deps.socket_factory.AddSocketDataProvider(&data4);
5620
5621 TestCompletionCallback callback1;
5622
[email protected]0b0bf032010-09-21 18:08:505623 scoped_ptr<HttpTransaction> trans(
5624 new HttpNetworkTransaction(CreateSession(&session_deps)));
5625
[email protected]aeefc9e82010-02-19 16:18:275626 // Issue the first request with Authorize headers. There should be a
5627 // password prompt for first_realm waiting to be filled in after the
5628 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275629 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275630 EXPECT_EQ(ERR_IO_PENDING, rv);
5631 rv = callback1.WaitForResult();
5632 EXPECT_EQ(OK, rv);
5633 const HttpResponseInfo* response = trans->GetResponseInfo();
5634 ASSERT_FALSE(response == NULL);
5635 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5636 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5637 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5638 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5639
5640 // Issue the second request with an incorrect password. There should be a
5641 // password prompt for second_realm waiting to be filled in after the
5642 // transaction completes.
5643 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445644 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275645 EXPECT_EQ(ERR_IO_PENDING, rv);
5646 rv = callback2.WaitForResult();
5647 EXPECT_EQ(OK, rv);
5648 response = trans->GetResponseInfo();
5649 ASSERT_FALSE(response == NULL);
5650 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5651 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5652 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5653 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5654
5655 // Issue the third request with another incorrect password. There should be
5656 // a password prompt for first_realm waiting to be filled in. If the password
5657 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5658 // first_realm was not correctly removed.
5659 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445660 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275661 EXPECT_EQ(ERR_IO_PENDING, rv);
5662 rv = callback3.WaitForResult();
5663 EXPECT_EQ(OK, rv);
5664 response = trans->GetResponseInfo();
5665 ASSERT_FALSE(response == NULL);
5666 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5667 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5668 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5669 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5670
5671 // Issue the fourth request with the correct password and username.
5672 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445673 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275674 EXPECT_EQ(ERR_IO_PENDING, rv);
5675 rv = callback4.WaitForResult();
5676 EXPECT_EQ(OK, rv);
5677 response = trans->GetResponseInfo();
5678 ASSERT_FALSE(response == NULL);
5679 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5680}
5681
[email protected]564b4912010-03-09 16:30:425682TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385683 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5684 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425685
[email protected]564b4912010-03-09 16:30:425686 SessionDependencies session_deps;
5687
5688 MockRead data_reads[] = {
5689 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355690 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425691 MockRead("hello world"),
5692 MockRead(false, OK),
5693 };
5694
5695 HttpRequestInfo request;
5696 request.method = "GET";
5697 request.url = GURL("http://www.google.com/");
5698 request.load_flags = 0;
5699
5700 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5701
5702 session_deps.socket_factory.AddSocketDataProvider(&data);
5703
5704 TestCompletionCallback callback;
5705
5706 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5707 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5708
[email protected]5a1d7ca2010-04-28 20:12:275709 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535711
[email protected]2fbaecf22010-07-22 22:20:355712 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425713 const HttpAlternateProtocols& alternate_protocols =
5714 session->alternate_protocols();
5715 EXPECT_FALSE(
5716 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5717
5718 EXPECT_EQ(OK, callback.WaitForResult());
5719
5720 const HttpResponseInfo* response = trans->GetResponseInfo();
5721 ASSERT_TRUE(response != NULL);
5722 ASSERT_TRUE(response->headers != NULL);
5723 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535724 EXPECT_FALSE(response->was_fetched_via_spdy);
5725 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575726 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425727
5728 std::string response_data;
5729 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5730 EXPECT_EQ("hello world", response_data);
5731
5732 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5733 const HttpAlternateProtocols::PortProtocolPair alternate =
5734 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5735 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5736 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355737 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425738 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425739
[email protected]8e6441ca2010-08-19 05:56:385740 HttpStreamFactory::set_use_alternate_protocols(false);
5741 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:425742}
5743
5744TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:385745 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:425746 SessionDependencies session_deps;
5747
5748 HttpRequestInfo request;
5749 request.method = "GET";
5750 request.url = GURL("http://www.google.com/");
5751 request.load_flags = 0;
5752
5753 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5754 StaticSocketDataProvider first_data;
5755 first_data.set_connect_data(mock_connect);
5756 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5757
5758 MockRead data_reads[] = {
5759 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5760 MockRead("hello world"),
5761 MockRead(true, OK),
5762 };
5763 StaticSocketDataProvider second_data(
5764 data_reads, arraysize(data_reads), NULL, 0);
5765 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5766
5767 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5768 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5769 // http://crbug.com/37454.
5770 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5771
5772 TestCompletionCallback callback;
5773
5774 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5775
[email protected]2fbaecf22010-07-22 22:20:355776 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425777 HttpAlternateProtocols* alternate_protocols =
5778 session->mutable_alternate_protocols();
5779 alternate_protocols->SetAlternateProtocolFor(
5780 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355781 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425782
5783 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5784
[email protected]5a1d7ca2010-04-28 20:12:275785 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425786 EXPECT_EQ(ERR_IO_PENDING, rv);
5787 EXPECT_EQ(OK, callback.WaitForResult());
5788
5789 const HttpResponseInfo* response = trans->GetResponseInfo();
5790 ASSERT_TRUE(response != NULL);
5791 ASSERT_TRUE(response->headers != NULL);
5792 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5793
5794 std::string response_data;
5795 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5796 EXPECT_EQ("hello world", response_data);
5797
5798 ASSERT_TRUE(
5799 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5800 const HttpAlternateProtocols::PortProtocolPair alternate =
5801 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5802 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:385803 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:425804}
5805
5806// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5807// says that it does SPDY, but it just does the TLS handshake, but the NPN
5808// response does not indicate SPDY, so we just do standard HTTPS over the port.
5809// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5810// on the original port.
[email protected]a2cb8122010-03-10 17:22:425811// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5812// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535813//
[email protected]a2cb8122010-03-10 17:22:425814// HttpRequestInfo request;
5815// request.method = "GET";
5816// request.url = GURL("http://www.google.com/");
5817// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535818//
[email protected]a2cb8122010-03-10 17:22:425819// MockRead data_reads[] = {
5820// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5821// MockRead("hello world"),
5822// MockRead(true, OK),
5823// };
5824// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5825// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535826//
[email protected]a2cb8122010-03-10 17:22:425827// SSLSocketDataProvider ssl(true, OK);
5828// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535829//
[email protected]a2cb8122010-03-10 17:22:425830// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535831//
[email protected]a2cb8122010-03-10 17:22:425832// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535833//
[email protected]a2cb8122010-03-10 17:22:425834// HostPortPair http_host_port_pair;
5835// http_host_port_pair.host = "www.google.com";
5836// http_host_port_pair.port = 80;
5837// HttpAlternateProtocols* alternate_protocols =
5838// session->mutable_alternate_protocols();
5839// alternate_protocols->SetAlternateProtocolFor(
5840// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065841// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535842//
[email protected]a2cb8122010-03-10 17:22:425843// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535844//
[email protected]5a1d7ca2010-04-28 20:12:275845// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425846// EXPECT_EQ(ERR_IO_PENDING, rv);
5847// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535848//
[email protected]a2cb8122010-03-10 17:22:425849// const HttpResponseInfo* response = trans->GetResponseInfo();
5850// ASSERT_TRUE(response != NULL);
5851// ASSERT_TRUE(response->headers != NULL);
5852// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535853//
[email protected]a2cb8122010-03-10 17:22:425854// std::string response_data;
5855// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5856// EXPECT_EQ("hello world", response_data);
5857// }
5858
5859TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:385860 HttpStreamFactory::set_use_alternate_protocols(true);
5861 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425862 SessionDependencies session_deps;
5863
5864 HttpRequestInfo request;
5865 request.method = "GET";
5866 request.url = GURL("http://www.google.com/");
5867 request.load_flags = 0;
5868
[email protected]a2cb8122010-03-10 17:22:425869 StaticSocketDataProvider first_tcp_connect;
5870 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5871
5872 SSLSocketDataProvider ssl(true, OK);
5873 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5874
[email protected]564b4912010-03-09 16:30:425875 MockRead data_reads[] = {
5876 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5877 MockRead("hello world"),
5878 MockRead(true, OK),
5879 };
[email protected]a2cb8122010-03-10 17:22:425880 StaticSocketDataProvider fallback_data(
5881 data_reads, arraysize(data_reads), NULL, 0);
5882 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425883
5884 TestCompletionCallback callback;
5885
5886 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5887
[email protected]2fbaecf22010-07-22 22:20:355888 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425889 HttpAlternateProtocols* alternate_protocols =
5890 session->mutable_alternate_protocols();
5891 alternate_protocols->SetAlternateProtocolFor(
5892 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355893 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425894
5895 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5896
[email protected]5a1d7ca2010-04-28 20:12:275897 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425898 EXPECT_EQ(ERR_IO_PENDING, rv);
5899 EXPECT_EQ(OK, callback.WaitForResult());
5900
5901 const HttpResponseInfo* response = trans->GetResponseInfo();
5902 ASSERT_TRUE(response != NULL);
5903 ASSERT_TRUE(response->headers != NULL);
5904 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5905
5906 std::string response_data;
5907 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5908 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:385909 HttpStreamFactory::set_next_protos("");
5910 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545911}
5912
5913TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:385914 HttpStreamFactory::set_use_alternate_protocols(true);
5915 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545916 SessionDependencies session_deps;
5917
5918 HttpRequestInfo request;
5919 request.method = "GET";
5920 request.url = GURL("http://www.google.com/");
5921 request.load_flags = 0;
5922
5923 MockRead data_reads[] = {
5924 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355925 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545926 MockRead("hello world"),
5927 MockRead(true, OK),
5928 };
5929
5930 StaticSocketDataProvider first_transaction(
5931 data_reads, arraysize(data_reads), NULL, 0);
5932 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5933
5934 SSLSocketDataProvider ssl(true, OK);
5935 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355936 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535937 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545938 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5939
[email protected]2bd93022010-07-17 00:58:445940 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135941 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545942
[email protected]2bd93022010-07-17 00:58:445943 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5944 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545945 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135946 CreateMockRead(*resp),
5947 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545948 MockRead(true, 0, 0),
5949 };
5950
5951 scoped_refptr<DelayedSocketData> spdy_data(
5952 new DelayedSocketData(
5953 1, // wait for one write to finish before reading.
5954 spdy_reads, arraysize(spdy_reads),
5955 spdy_writes, arraysize(spdy_writes)));
5956 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5957
5958 TestCompletionCallback callback;
5959
5960 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5961 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5962
[email protected]5a1d7ca2010-04-28 20:12:275963 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545964 EXPECT_EQ(ERR_IO_PENDING, rv);
5965 EXPECT_EQ(OK, callback.WaitForResult());
5966
5967 const HttpResponseInfo* response = trans->GetResponseInfo();
5968 ASSERT_TRUE(response != NULL);
5969 ASSERT_TRUE(response->headers != NULL);
5970 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5971
5972 std::string response_data;
5973 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5974 EXPECT_EQ("hello world", response_data);
5975
5976 trans.reset(new HttpNetworkTransaction(session));
5977
[email protected]5a1d7ca2010-04-28 20:12:275978 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545979 EXPECT_EQ(ERR_IO_PENDING, rv);
5980 EXPECT_EQ(OK, callback.WaitForResult());
5981
5982 response = trans->GetResponseInfo();
5983 ASSERT_TRUE(response != NULL);
5984 ASSERT_TRUE(response->headers != NULL);
5985 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535986 EXPECT_TRUE(response->was_fetched_via_spdy);
5987 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575988 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545989
5990 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5991 EXPECT_EQ("hello!", response_data);
5992
[email protected]8e6441ca2010-08-19 05:56:385993 HttpStreamFactory::set_next_protos("");
5994 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545995}
5996
[email protected]631f1322010-04-30 17:59:115997class CapturingProxyResolver : public ProxyResolver {
5998 public:
5999 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6000 virtual ~CapturingProxyResolver() {}
6001
6002 virtual int GetProxyForURL(const GURL& url,
6003 ProxyInfo* results,
6004 CompletionCallback* callback,
6005 RequestHandle* request,
6006 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406007 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6008 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426009 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116010 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426011 return OK;
[email protected]631f1322010-04-30 17:59:116012 }
6013
6014 virtual void CancelRequest(RequestHandle request) {
6015 NOTREACHED();
6016 }
6017
[email protected]24476402010-07-20 20:55:176018 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116019 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426020 return OK;
[email protected]631f1322010-04-30 17:59:116021 }
6022
[email protected]24476402010-07-20 20:55:176023 const std::vector<GURL>& resolved() const { return resolved_; }
6024
6025 private:
[email protected]631f1322010-04-30 17:59:116026 std::vector<GURL> resolved_;
6027
6028 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6029};
6030
[email protected]631f1322010-04-30 17:59:116031TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386032 HttpStreamFactory::set_use_alternate_protocols(true);
6033 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116034
6035 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426036 proxy_config.set_auto_detect(true);
6037 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116038
[email protected]631f1322010-04-30 17:59:116039 CapturingProxyResolver* capturing_proxy_resolver =
6040 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386041 SessionDependencies session_deps(new ProxyService(
6042 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6043 NULL));
[email protected]631f1322010-04-30 17:59:116044
6045 HttpRequestInfo request;
6046 request.method = "GET";
6047 request.url = GURL("http://www.google.com/");
6048 request.load_flags = 0;
6049
6050 MockRead data_reads[] = {
6051 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356052 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116053 MockRead("hello world"),
6054 MockRead(true, OK),
6055 };
6056
6057 StaticSocketDataProvider first_transaction(
6058 data_reads, arraysize(data_reads), NULL, 0);
6059 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6060
6061 SSLSocketDataProvider ssl(true, OK);
6062 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356063 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536064 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116065 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6066
[email protected]2bd93022010-07-17 00:58:446067 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116068 MockWrite spdy_writes[] = {
6069 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6070 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426071 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136072 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116073 };
6074
[email protected]d911f1b2010-05-05 22:39:426075 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6076
[email protected]2bd93022010-07-17 00:58:446077 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6078 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116079 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426080 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136081 CreateMockRead(*resp.get(), 4), // 2, 4
6082 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426083 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116084 };
6085
[email protected]d911f1b2010-05-05 22:39:426086 scoped_refptr<OrderedSocketData> spdy_data(
6087 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116088 spdy_reads, arraysize(spdy_reads),
6089 spdy_writes, arraysize(spdy_writes)));
6090 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6091
6092 TestCompletionCallback callback;
6093
6094 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6095 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6096
6097 int rv = trans->Start(&request, &callback, BoundNetLog());
6098 EXPECT_EQ(ERR_IO_PENDING, rv);
6099 EXPECT_EQ(OK, callback.WaitForResult());
6100
6101 const HttpResponseInfo* response = trans->GetResponseInfo();
6102 ASSERT_TRUE(response != NULL);
6103 ASSERT_TRUE(response->headers != NULL);
6104 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536105 EXPECT_FALSE(response->was_fetched_via_spdy);
6106 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116107
6108 std::string response_data;
6109 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6110 EXPECT_EQ("hello world", response_data);
6111
6112 trans.reset(new HttpNetworkTransaction(session));
6113
6114 rv = trans->Start(&request, &callback, BoundNetLog());
6115 EXPECT_EQ(ERR_IO_PENDING, rv);
6116 EXPECT_EQ(OK, callback.WaitForResult());
6117
6118 response = trans->GetResponseInfo();
6119 ASSERT_TRUE(response != NULL);
6120 ASSERT_TRUE(response->headers != NULL);
6121 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536122 EXPECT_TRUE(response->was_fetched_via_spdy);
6123 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116124
6125 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6126 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426127 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6128 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116129 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426130 EXPECT_EQ("https://www.google.com/",
6131 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116132
[email protected]8e6441ca2010-08-19 05:56:386133 HttpStreamFactory::set_next_protos("");
6134 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116135}
[email protected]631f1322010-04-30 17:59:116136
[email protected]2ff8b312010-04-26 22:20:546137TEST_F(HttpNetworkTransactionTest,
6138 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386139 HttpStreamFactory::set_use_alternate_protocols(true);
6140 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546141 SessionDependencies session_deps;
6142
6143 HttpRequestInfo request;
6144 request.method = "GET";
6145 request.url = GURL("http://www.google.com/");
6146 request.load_flags = 0;
6147
6148 MockRead data_reads[] = {
6149 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356150 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546151 MockRead("hello world"),
6152 MockRead(true, OK),
6153 };
6154
6155 StaticSocketDataProvider first_transaction(
6156 data_reads, arraysize(data_reads), NULL, 0);
6157 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6158
6159 SSLSocketDataProvider ssl(true, OK);
6160 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356161 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536162 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546163 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536164 // Make sure we use ssl for spdy here.
6165 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546166
[email protected]2bd93022010-07-17 00:58:446167 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136168 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546169
[email protected]2bd93022010-07-17 00:58:446170 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6171 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546172 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136173 CreateMockRead(*resp),
6174 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546175 MockRead(true, 0, 0),
6176 };
6177
6178 scoped_refptr<DelayedSocketData> spdy_data(
6179 new DelayedSocketData(
6180 1, // wait for one write to finish before reading.
6181 spdy_reads, arraysize(spdy_reads),
6182 spdy_writes, arraysize(spdy_writes)));
6183 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6184
6185 TestCompletionCallback callback;
6186
6187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6188
6189 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6190
[email protected]5a1d7ca2010-04-28 20:12:276191 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546192 EXPECT_EQ(ERR_IO_PENDING, rv);
6193 EXPECT_EQ(OK, callback.WaitForResult());
6194
6195 const HttpResponseInfo* response = trans->GetResponseInfo();
6196 ASSERT_TRUE(response != NULL);
6197 ASSERT_TRUE(response->headers != NULL);
6198 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6199
6200 std::string response_data;
6201 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6202 EXPECT_EQ("hello world", response_data);
6203
6204 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386205 HostPortPair host_port_pair("www.google.com", 443);
6206 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546207 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276208 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6209 BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:216210 scoped_refptr<TCPSocketParams> tcp_params =
6211 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:386212
6213 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6214 EXPECT_EQ(ERR_IO_PENDING,
6215 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6216 &callback, session->tcp_socket_pool(),
6217 BoundNetLog()));
6218 EXPECT_EQ(OK, callback.WaitForResult());
6219
6220 SSLConfig ssl_config;
6221 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6222 ClientSocket* socket = connection->release_socket();
[email protected]563ee902010-09-27 16:16:176223 socket = session->socket_factory()->CreateSSLClientSocket(socket, "" ,
6224 ssl_config);
[email protected]02b0c342010-09-25 21:09:386225 connection->set_socket(socket);
6226 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6227 EXPECT_EQ(OK, callback.WaitForResult());
6228
6229 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6230 true, OK));
6231
[email protected]2ff8b312010-04-26 22:20:546232 trans.reset(new HttpNetworkTransaction(session));
6233
[email protected]5a1d7ca2010-04-28 20:12:276234 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546235 EXPECT_EQ(ERR_IO_PENDING, rv);
6236 EXPECT_EQ(OK, callback.WaitForResult());
6237
6238 response = trans->GetResponseInfo();
6239 ASSERT_TRUE(response != NULL);
6240 ASSERT_TRUE(response->headers != NULL);
6241 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536242 EXPECT_TRUE(response->was_fetched_via_spdy);
6243 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576244 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546245
6246 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6247 EXPECT_EQ("hello!", response_data);
6248
[email protected]8e6441ca2010-08-19 05:56:386249 HttpStreamFactory::set_next_protos("");
6250 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426251}
6252
[email protected]044de0642010-06-17 10:42:156253// GenerateAuthToken is a mighty big test.
6254// It tests all permutation of GenerateAuthToken behavior:
6255// - Synchronous and Asynchronous completion.
6256// - OK or error on completion.
6257// - Direct connection, non-authenticating proxy, and authenticating proxy.
6258// - HTTP or HTTPS backend (to include proxy tunneling).
6259// - Non-authenticating and authenticating backend.
6260//
6261// In all, there are 44 reasonable permuations (for example, if there are
6262// problems generating an auth token for an authenticating proxy, we don't
6263// need to test all permutations of the backend server).
6264//
6265// The test proceeds by going over each of the configuration cases, and
6266// potentially running up to three rounds in each of the tests. The TestConfig
6267// specifies both the configuration for the test as well as the expectations
6268// for the results.
6269TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506270 static const char kServer[] = "http://www.example.com";
6271 static const char kSecureServer[] = "https://www.example.com";
6272 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156273 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6274
6275 enum AuthTiming {
6276 AUTH_NONE,
6277 AUTH_SYNC,
6278 AUTH_ASYNC,
6279 };
6280
6281 const MockWrite kGet(
6282 "GET / HTTP/1.1\r\n"
6283 "Host: www.example.com\r\n"
6284 "Connection: keep-alive\r\n\r\n");
6285 const MockWrite kGetProxy(
6286 "GET http://www.example.com/ HTTP/1.1\r\n"
6287 "Host: www.example.com\r\n"
6288 "Proxy-Connection: keep-alive\r\n\r\n");
6289 const MockWrite kGetAuth(
6290 "GET / HTTP/1.1\r\n"
6291 "Host: www.example.com\r\n"
6292 "Connection: keep-alive\r\n"
6293 "Authorization: auth_token\r\n\r\n");
6294 const MockWrite kGetProxyAuth(
6295 "GET http://www.example.com/ HTTP/1.1\r\n"
6296 "Host: www.example.com\r\n"
6297 "Proxy-Connection: keep-alive\r\n"
6298 "Proxy-Authorization: auth_token\r\n\r\n");
6299 const MockWrite kGetAuthThroughProxy(
6300 "GET http://www.example.com/ HTTP/1.1\r\n"
6301 "Host: www.example.com\r\n"
6302 "Proxy-Connection: keep-alive\r\n"
6303 "Authorization: auth_token\r\n\r\n");
6304 const MockWrite kGetAuthWithProxyAuth(
6305 "GET http://www.example.com/ HTTP/1.1\r\n"
6306 "Host: www.example.com\r\n"
6307 "Proxy-Connection: keep-alive\r\n"
6308 "Proxy-Authorization: auth_token\r\n"
6309 "Authorization: auth_token\r\n\r\n");
6310 const MockWrite kConnect(
6311 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6312 "Host: www.example.com\r\n"
6313 "Proxy-Connection: keep-alive\r\n\r\n");
6314 const MockWrite kConnectProxyAuth(
6315 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6316 "Host: www.example.com\r\n"
6317 "Proxy-Connection: keep-alive\r\n"
6318 "Proxy-Authorization: auth_token\r\n\r\n");
6319
6320 const MockRead kSuccess(
6321 "HTTP/1.1 200 OK\r\n"
6322 "Content-Type: text/html; charset=iso-8859-1\r\n"
6323 "Content-Length: 3\r\n\r\n"
6324 "Yes");
6325 const MockRead kFailure(
6326 "Should not be called.");
6327 const MockRead kServerChallenge(
6328 "HTTP/1.1 401 Unauthorized\r\n"
6329 "WWW-Authenticate: Mock realm=server\r\n"
6330 "Content-Type: text/html; charset=iso-8859-1\r\n"
6331 "Content-Length: 14\r\n\r\n"
6332 "Unauthorized\r\n");
6333 const MockRead kProxyChallenge(
6334 "HTTP/1.1 407 Unauthorized\r\n"
6335 "Proxy-Authenticate: Mock realm=proxy\r\n"
6336 "Proxy-Connection: close\r\n"
6337 "Content-Type: text/html; charset=iso-8859-1\r\n"
6338 "Content-Length: 14\r\n\r\n"
6339 "Unauthorized\r\n");
6340 const MockRead kProxyConnected(
6341 "HTTP/1.1 200 Connection Established\r\n\r\n");
6342
6343 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6344 // no constructors, but the C++ compiler on Windows warns about
6345 // unspecified data in compound literals. So, moved to using constructors,
6346 // and TestRound's created with the default constructor should not be used.
6347 struct TestRound {
6348 TestRound()
6349 : expected_rv(ERR_UNEXPECTED),
6350 extra_write(NULL),
6351 extra_read(NULL) {
6352 }
6353 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6354 int expected_rv_arg)
6355 : write(write_arg),
6356 read(read_arg),
6357 expected_rv(expected_rv_arg),
6358 extra_write(NULL),
6359 extra_read(NULL) {
6360 }
6361 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6362 int expected_rv_arg, const MockWrite* extra_write_arg,
6363 const MockWrite* extra_read_arg)
6364 : write(write_arg),
6365 read(read_arg),
6366 expected_rv(expected_rv_arg),
6367 extra_write(extra_write_arg),
6368 extra_read(extra_read_arg) {
6369 }
6370 MockWrite write;
6371 MockRead read;
6372 int expected_rv;
6373 const MockWrite* extra_write;
6374 const MockRead* extra_read;
6375 };
6376
6377 static const int kNoSSL = 500;
6378
6379 struct TestConfig {
6380 const char* proxy_url;
6381 AuthTiming proxy_auth_timing;
6382 int proxy_auth_rv;
6383 const char* server_url;
6384 AuthTiming server_auth_timing;
6385 int server_auth_rv;
6386 int num_auth_rounds;
6387 int first_ssl_round;
6388 TestRound rounds[3];
6389 } test_configs[] = {
6390 // Non-authenticating HTTP server with a direct connection.
6391 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6392 { TestRound(kGet, kSuccess, OK)}},
6393 // Authenticating HTTP server with a direct connection.
6394 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6395 { TestRound(kGet, kServerChallenge, OK),
6396 TestRound(kGetAuth, kSuccess, OK)}},
6397 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6398 { TestRound(kGet, kServerChallenge, OK),
6399 TestRound(kGetAuth, kFailure, kAuthErr)}},
6400 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6401 { TestRound(kGet, kServerChallenge, OK),
6402 TestRound(kGetAuth, kSuccess, OK)}},
6403 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6404 { TestRound(kGet, kServerChallenge, OK),
6405 TestRound(kGetAuth, kFailure, kAuthErr)}},
6406 // Non-authenticating HTTP server through a non-authenticating proxy.
6407 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6408 { TestRound(kGetProxy, kSuccess, OK)}},
6409 // Authenticating HTTP server through a non-authenticating proxy.
6410 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6411 { TestRound(kGetProxy, kServerChallenge, OK),
6412 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6413 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6414 { TestRound(kGetProxy, kServerChallenge, OK),
6415 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6416 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6417 { TestRound(kGetProxy, kServerChallenge, OK),
6418 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6419 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6420 { TestRound(kGetProxy, kServerChallenge, OK),
6421 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6422 // Non-authenticating HTTP server through an authenticating proxy.
6423 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6424 { TestRound(kGetProxy, kProxyChallenge, OK),
6425 TestRound(kGetProxyAuth, kSuccess, OK)}},
6426 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6427 { TestRound(kGetProxy, kProxyChallenge, OK),
6428 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6429 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6430 { TestRound(kGetProxy, kProxyChallenge, OK),
6431 TestRound(kGetProxyAuth, kSuccess, OK)}},
6432 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6433 { TestRound(kGetProxy, kProxyChallenge, OK),
6434 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6435 // Authenticating HTTP server through an authenticating proxy.
6436 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6437 { TestRound(kGetProxy, kProxyChallenge, OK),
6438 TestRound(kGetProxyAuth, kServerChallenge, OK),
6439 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6440 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6441 { TestRound(kGetProxy, kProxyChallenge, OK),
6442 TestRound(kGetProxyAuth, kServerChallenge, OK),
6443 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6444 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6445 { TestRound(kGetProxy, kProxyChallenge, OK),
6446 TestRound(kGetProxyAuth, kServerChallenge, OK),
6447 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6448 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6449 { TestRound(kGetProxy, kProxyChallenge, OK),
6450 TestRound(kGetProxyAuth, kServerChallenge, OK),
6451 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6452 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6453 { TestRound(kGetProxy, kProxyChallenge, OK),
6454 TestRound(kGetProxyAuth, kServerChallenge, OK),
6455 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6456 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6457 { TestRound(kGetProxy, kProxyChallenge, OK),
6458 TestRound(kGetProxyAuth, kServerChallenge, OK),
6459 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6460 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6461 { TestRound(kGetProxy, kProxyChallenge, OK),
6462 TestRound(kGetProxyAuth, kServerChallenge, OK),
6463 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6464 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6465 { TestRound(kGetProxy, kProxyChallenge, OK),
6466 TestRound(kGetProxyAuth, kServerChallenge, OK),
6467 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6468 // Non-authenticating HTTPS server with a direct connection.
6469 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6470 { TestRound(kGet, kSuccess, OK)}},
6471 // Authenticating HTTPS server with a direct connection.
6472 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6473 { TestRound(kGet, kServerChallenge, OK),
6474 TestRound(kGetAuth, kSuccess, OK)}},
6475 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6476 { TestRound(kGet, kServerChallenge, OK),
6477 TestRound(kGetAuth, kFailure, kAuthErr)}},
6478 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6479 { TestRound(kGet, kServerChallenge, OK),
6480 TestRound(kGetAuth, kSuccess, OK)}},
6481 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6482 { TestRound(kGet, kServerChallenge, OK),
6483 TestRound(kGetAuth, kFailure, kAuthErr)}},
6484 // Non-authenticating HTTPS server with a non-authenticating proxy.
6485 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6486 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6487 // Authenticating HTTPS server through a non-authenticating proxy.
6488 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6489 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6490 TestRound(kGetAuth, kSuccess, OK)}},
6491 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6492 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6493 TestRound(kGetAuth, kFailure, kAuthErr)}},
6494 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6495 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6496 TestRound(kGetAuth, kSuccess, OK)}},
6497 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6498 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6499 TestRound(kGetAuth, kFailure, kAuthErr)}},
6500 // Non-Authenticating HTTPS server through an authenticating proxy.
6501 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6502 { TestRound(kConnect, kProxyChallenge, OK),
6503 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6504 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6505 { TestRound(kConnect, kProxyChallenge, OK),
6506 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6507 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6508 { TestRound(kConnect, kProxyChallenge, OK),
6509 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6510 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6511 { TestRound(kConnect, kProxyChallenge, OK),
6512 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6513 // Authenticating HTTPS server through an authenticating proxy.
6514 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6515 { TestRound(kConnect, kProxyChallenge, OK),
6516 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6517 &kGet, &kServerChallenge),
6518 TestRound(kGetAuth, kSuccess, OK)}},
6519 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6520 { TestRound(kConnect, kProxyChallenge, OK),
6521 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6522 &kGet, &kServerChallenge),
6523 TestRound(kGetAuth, kFailure, kAuthErr)}},
6524 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6525 { TestRound(kConnect, kProxyChallenge, OK),
6526 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6527 &kGet, &kServerChallenge),
6528 TestRound(kGetAuth, kSuccess, OK)}},
6529 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6530 { TestRound(kConnect, kProxyChallenge, OK),
6531 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6532 &kGet, &kServerChallenge),
6533 TestRound(kGetAuth, kFailure, kAuthErr)}},
6534 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6535 { TestRound(kConnect, kProxyChallenge, OK),
6536 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6537 &kGet, &kServerChallenge),
6538 TestRound(kGetAuth, kSuccess, OK)}},
6539 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6540 { TestRound(kConnect, kProxyChallenge, OK),
6541 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6542 &kGet, &kServerChallenge),
6543 TestRound(kGetAuth, kFailure, kAuthErr)}},
6544 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6545 { TestRound(kConnect, kProxyChallenge, OK),
6546 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6547 &kGet, &kServerChallenge),
6548 TestRound(kGetAuth, kSuccess, OK)}},
6549 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6550 { TestRound(kConnect, kProxyChallenge, OK),
6551 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6552 &kGet, &kServerChallenge),
6553 TestRound(kGetAuth, kFailure, kAuthErr)}},
6554 };
6555
6556 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:006557 HttpAuthHandlerMock::Factory* auth_factory(
6558 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156559 session_deps.http_auth_handler_factory.reset(auth_factory);
6560
6561 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6562 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266563
6564 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156565 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006566 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156567 std::string auth_challenge = "Mock realm=proxy";
6568 GURL origin(test_config.proxy_url);
6569 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6570 auth_challenge.end());
6571 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6572 origin, BoundNetLog());
6573 auth_handler->SetGenerateExpectation(
6574 test_config.proxy_auth_timing == AUTH_ASYNC,
6575 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156576 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6577 }
6578 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006579 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156580 std::string auth_challenge = "Mock realm=server";
6581 GURL origin(test_config.server_url);
6582 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6583 auth_challenge.end());
6584 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6585 origin, BoundNetLog());
6586 auth_handler->SetGenerateExpectation(
6587 test_config.server_auth_timing == AUTH_ASYNC,
6588 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156589 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6590 }
6591 if (test_config.proxy_url) {
6592 session_deps.proxy_service =
6593 CreateFixedProxyService(test_config.proxy_url);
6594 } else {
[email protected]ebeefff32010-09-15 05:10:026595 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:156596 }
6597
6598 HttpRequestInfo request;
6599 request.method = "GET";
6600 request.url = GURL(test_config.server_url);
6601 request.load_flags = 0;
6602
[email protected]0b0bf032010-09-21 18:08:506603 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6604 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:156605
6606 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6607 const TestRound& read_write_round = test_config.rounds[round];
6608
6609 // Set up expected reads and writes.
6610 MockRead reads[2];
6611 reads[0] = read_write_round.read;
6612 size_t length_reads = 1;
6613 if (read_write_round.extra_read) {
6614 reads[1] = *read_write_round.extra_read;
6615 length_reads = 2;
6616 }
6617
6618 MockWrite writes[2];
6619 writes[0] = read_write_round.write;
6620 size_t length_writes = 1;
6621 if (read_write_round.extra_write) {
6622 writes[1] = *read_write_round.extra_write;
6623 length_writes = 2;
6624 }
6625 StaticSocketDataProvider data_provider(
6626 reads, length_reads, writes, length_writes);
6627 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6628
6629 // Add an SSL sequence if necessary.
6630 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6631 if (round >= test_config.first_ssl_round)
6632 session_deps.socket_factory.AddSSLSocketDataProvider(
6633 &ssl_socket_data_provider);
6634
6635 // Start or restart the transaction.
6636 TestCompletionCallback callback;
6637 int rv;
6638 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:506639 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:156640 } else {
[email protected]0b0bf032010-09-21 18:08:506641 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156642 }
6643 if (rv == ERR_IO_PENDING)
6644 rv = callback.WaitForResult();
6645
6646 // Compare results with expected data.
6647 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:506648 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:156649 if (read_write_round.expected_rv == OK) {
6650 EXPECT_FALSE(response == NULL);
6651 } else {
6652 EXPECT_TRUE(response == NULL);
6653 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6654 continue;
6655 }
6656 if (round + 1 < test_config.num_auth_rounds) {
6657 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6658 } else {
6659 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6660 }
6661 }
[email protected]e5ae96a2010-04-14 20:12:456662 }
6663}
6664
[email protected]c871bce92010-07-15 21:51:146665TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6666 // Do multi-round authentication and make sure it works correctly.
6667 SessionDependencies session_deps;
6668 HttpAuthHandlerMock::Factory* auth_factory(
6669 new HttpAuthHandlerMock::Factory());
6670 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:026671 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:146672 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6673 session_deps.host_resolver->set_synchronous_mode(true);
6674
6675 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6676 auth_handler->set_connection_based(true);
6677 std::string auth_challenge = "Mock realm=server";
6678 GURL origin("http://www.example.com");
6679 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6680 auth_challenge.end());
6681 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6682 origin, BoundNetLog());
6683 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6684
6685 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6686 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6687
6688 int rv = OK;
6689 const HttpResponseInfo* response = NULL;
6690 HttpRequestInfo request;
6691 request.method = "GET";
6692 request.url = origin;
6693 request.load_flags = 0;
6694 TestCompletionCallback callback;
6695
6696 const MockWrite kGet(
6697 "GET / HTTP/1.1\r\n"
6698 "Host: www.example.com\r\n"
6699 "Connection: keep-alive\r\n\r\n");
6700 const MockWrite kGetAuth(
6701 "GET / HTTP/1.1\r\n"
6702 "Host: www.example.com\r\n"
6703 "Connection: keep-alive\r\n"
6704 "Authorization: auth_token\r\n\r\n");
6705
6706 const MockRead kServerChallenge(
6707 "HTTP/1.1 401 Unauthorized\r\n"
6708 "WWW-Authenticate: Mock realm=server\r\n"
6709 "Content-Type: text/html; charset=iso-8859-1\r\n"
6710 "Content-Length: 14\r\n\r\n"
6711 "Unauthorized\r\n");
6712 const MockRead kSuccess(
6713 "HTTP/1.1 200 OK\r\n"
6714 "Content-Type: text/html; charset=iso-8859-1\r\n"
6715 "Content-Length: 3\r\n\r\n"
6716 "Yes");
6717
6718 MockWrite writes[] = {
6719 // First round
6720 kGet,
6721 // Second round
6722 kGetAuth,
6723 // Third round
6724 kGetAuth,
[email protected]eca50e122010-09-11 14:03:306725 // Fourth round
6726 kGetAuth
[email protected]c871bce92010-07-15 21:51:146727 };
6728 MockRead reads[] = {
6729 // First round
6730 kServerChallenge,
6731 // Second round
6732 kServerChallenge,
6733 // Third round
[email protected]eca50e122010-09-11 14:03:306734 kServerChallenge,
6735 // Fourth round
[email protected]c871bce92010-07-15 21:51:146736 kSuccess,
6737 };
6738 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6739 writes, arraysize(writes));
6740 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6741
6742 // First round
6743 auth_handler->SetGenerateExpectation(false, OK);
6744 rv = trans->Start(&request, &callback, BoundNetLog());
6745 if (rv == ERR_IO_PENDING)
6746 rv = callback.WaitForResult();
6747 EXPECT_EQ(OK, rv);
6748 response = trans->GetResponseInfo();
6749 ASSERT_FALSE(response == NULL);
6750 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6751
6752 // Second round
6753 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446754 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146755 if (rv == ERR_IO_PENDING)
6756 rv = callback.WaitForResult();
6757 EXPECT_EQ(OK, rv);
6758 response = trans->GetResponseInfo();
6759 ASSERT_FALSE(response == NULL);
6760 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6761
6762 // Third round
6763 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446764 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146765 if (rv == ERR_IO_PENDING)
6766 rv = callback.WaitForResult();
6767 EXPECT_EQ(OK, rv);
6768 response = trans->GetResponseInfo();
6769 ASSERT_FALSE(response == NULL);
6770 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:306771
6772 // Fourth round
6773 auth_handler->SetGenerateExpectation(false, OK);
6774 rv = trans->RestartWithAuth(string16(), string16(), &callback);
6775 if (rv == ERR_IO_PENDING)
6776 rv = callback.WaitForResult();
6777 EXPECT_EQ(OK, rv);
6778 response = trans->GetResponseInfo();
6779 ASSERT_FALSE(response == NULL);
6780 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:146781}
6782
[email protected]aeaca1f2010-04-20 22:05:216783class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6784 public:
[email protected]06650c52010-06-03 00:49:176785 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216786 : fail_all_(fail_all) {
6787 }
6788
6789 virtual MockRead GetNextRead() {
6790 if (fail_all_)
6791 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6792
6793 return MockRead(false /* async */,
6794 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6795 }
6796
6797 virtual MockWriteResult OnWrite(const std::string& data) {
6798 return MockWriteResult(false /* async */, data.size());
6799 }
6800
6801 void Reset() {
6802 }
6803
6804 private:
6805 const bool fail_all_;
6806};
6807
6808// Test that we restart a connection when we see a decompression failure from
6809// the peer during the handshake. (In the real world we'll restart with SSLv3
6810// and we won't offer DEFLATE in that case.)
6811TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6812 HttpRequestInfo request;
6813 request.method = "GET";
6814 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6815 request.load_flags = 0;
6816
6817 SessionDependencies session_deps;
6818 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6819 false /* fail all reads */);
6820 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6821 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116822 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216823 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6824 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6825 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6826 session_deps.socket_factory.AddSSLSocketDataProvider(
6827 &ssl_socket_data_provider1);
6828 session_deps.socket_factory.AddSSLSocketDataProvider(
6829 &ssl_socket_data_provider2);
6830
[email protected]e60e47a2010-07-14 03:37:186831 // Work around http://crbug.com/37454
6832 StaticSocketDataProvider bug37454_connection;
6833 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6834 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6835
[email protected]aeaca1f2010-04-20 22:05:216836 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6837 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6838 TestCompletionCallback callback;
6839
[email protected]5a1d7ca2010-04-28 20:12:276840 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216841 EXPECT_EQ(ERR_IO_PENDING, rv);
6842 EXPECT_EQ(OK, callback.WaitForResult());
6843
6844 const HttpResponseInfo* response = trans->GetResponseInfo();
6845 ASSERT_TRUE(response != NULL);
6846 ASSERT_TRUE(response->headers != NULL);
6847 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6848
6849 std::string response_data;
6850 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6851 EXPECT_EQ("ok.", response_data);
6852}
6853
6854// Test that we restart a connection if we get a decompression failure from the
6855// peer while reading the first bytes from the connection. This occurs when the
6856// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6857// in the handshake.
6858TEST_F(HttpNetworkTransactionTest,
6859 RestartAfterTLSDecompressionFailureWithFalseStart) {
6860 HttpRequestInfo request;
6861 request.method = "GET";
6862 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6863 request.load_flags = 0;
6864
6865 SessionDependencies session_deps;
6866 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6867 true /* fail all reads */);
6868 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6869 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6870 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6871 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6872 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6873 session_deps.socket_factory.AddSSLSocketDataProvider(
6874 &ssl_socket_data_provider1);
6875 session_deps.socket_factory.AddSSLSocketDataProvider(
6876 &ssl_socket_data_provider2);
6877
6878 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6879 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6880 TestCompletionCallback callback;
6881
[email protected]5a1d7ca2010-04-28 20:12:276882 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216883 EXPECT_EQ(ERR_IO_PENDING, rv);
6884 EXPECT_EQ(OK, callback.WaitForResult());
6885
6886 const HttpResponseInfo* response = trans->GetResponseInfo();
6887 ASSERT_TRUE(response != NULL);
6888 ASSERT_TRUE(response->headers != NULL);
6889 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6890
6891 std::string response_data;
6892 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6893 EXPECT_EQ("ok.", response_data);
6894}
6895
[email protected]65041fa2010-05-21 06:56:536896// This tests the case that a request is issued via http instead of spdy after
6897// npn is negotiated.
6898TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:386899 HttpStreamFactory::set_use_alternate_protocols(true);
6900 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:536901 SessionDependencies session_deps;
6902 HttpRequestInfo request;
6903 request.method = "GET";
6904 request.url = GURL("https://www.google.com/");
6905 request.load_flags = 0;
6906
6907 MockWrite data_writes[] = {
6908 MockWrite("GET / HTTP/1.1\r\n"
6909 "Host: www.google.com\r\n"
6910 "Connection: keep-alive\r\n\r\n"),
6911 };
6912
6913 MockRead data_reads[] = {
6914 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356915 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536916 MockRead("hello world"),
6917 MockRead(false, OK),
6918 };
6919
6920 SSLSocketDataProvider ssl(true, OK);
6921 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6922 ssl.next_proto = "http/1.1";
6923
6924 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6925
6926 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6927 data_writes, arraysize(data_writes));
6928 session_deps.socket_factory.AddSocketDataProvider(&data);
6929
6930 TestCompletionCallback callback;
6931
6932 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6933 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6934
6935 int rv = trans->Start(&request, &callback, BoundNetLog());
6936
6937 EXPECT_EQ(ERR_IO_PENDING, rv);
6938 EXPECT_EQ(OK, callback.WaitForResult());
6939
6940 const HttpResponseInfo* response = trans->GetResponseInfo();
6941 ASSERT_TRUE(response != NULL);
6942 ASSERT_TRUE(response->headers != NULL);
6943 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6944
6945 std::string response_data;
6946 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6947 EXPECT_EQ("hello world", response_data);
6948
6949 EXPECT_FALSE(response->was_fetched_via_spdy);
6950 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576951 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536952
[email protected]8e6441ca2010-08-19 05:56:386953 HttpStreamFactory::set_next_protos("");
6954 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:536955}
[email protected]26ef6582010-06-24 02:30:476956
6957TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6958 // Simulate the SSL handshake completing with an NPN negotiation
6959 // followed by an immediate server closing of the socket.
6960 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:386961 HttpStreamFactory::set_use_alternate_protocols(true);
6962 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476963 SessionDependencies session_deps;
6964
6965 HttpRequestInfo request;
6966 request.method = "GET";
6967 request.url = GURL("https://www.google.com/");
6968 request.load_flags = 0;
6969
6970 SSLSocketDataProvider ssl(true, OK);
6971 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356972 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476973 ssl.was_npn_negotiated = true;
6974 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6975
[email protected]2bd93022010-07-17 00:58:446976 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136977 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476978
6979 MockRead spdy_reads[] = {
6980 MockRead(false, 0, 0) // Not async - return 0 immediately.
6981 };
6982
6983 scoped_refptr<DelayedSocketData> spdy_data(
6984 new DelayedSocketData(
6985 0, // don't wait in this case, immediate hangup.
6986 spdy_reads, arraysize(spdy_reads),
6987 spdy_writes, arraysize(spdy_writes)));
6988 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6989
6990 TestCompletionCallback callback;
6991
6992 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6993 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6994
6995 int rv = trans->Start(&request, &callback, BoundNetLog());
6996 EXPECT_EQ(ERR_IO_PENDING, rv);
6997 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6998
[email protected]8e6441ca2010-08-19 05:56:386999 HttpStreamFactory::set_next_protos("");
7000 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477001}
[email protected]65d34382010-07-01 18:12:267002
[email protected]f45c1ee2010-08-03 00:54:307003TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7004 // This test ensures that the URL passed into the proxy is upgraded
7005 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387006 HttpStreamFactory::set_use_alternate_protocols(true);
7007 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307008 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7009
7010 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7011 HttpAuthHandlerMock::Factory* auth_factory =
7012 new HttpAuthHandlerMock::Factory();
7013 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7014 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7015 auth_factory->set_do_init_from_challenge(true);
7016 session_deps.http_auth_handler_factory.reset(auth_factory);
7017
7018 HttpRequestInfo request;
7019 request.method = "GET";
7020 request.url = GURL("http://www.google.com");
7021 request.load_flags = 0;
7022
7023 // First round goes unauthenticated through the proxy.
7024 MockWrite data_writes_1[] = {
7025 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7026 "Host: www.google.com\r\n"
7027 "Proxy-Connection: keep-alive\r\n"
7028 "\r\n"),
7029 };
7030 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597031 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307032 MockRead("HTTP/1.1 200 OK\r\n"
7033 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7034 "Proxy-Connection: close\r\n"
7035 "\r\n"),
7036 };
7037 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7038 data_writes_1, arraysize(data_writes_1));
7039
7040 // Second round tries to tunnel to www.google.com due to the
7041 // Alternate-Protocol announcement in the first round. It fails due
7042 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597043 // After the failure, a tunnel is established to www.google.com using
7044 // Proxy-Authorization headers. There is then a SPDY request round.
7045 //
7046 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7047 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7048 // does a Disconnect and Connect on the same socket, rather than trying
7049 // to obtain a new one.
7050 //
7051 // NOTE: Originally, the proxy response to the second CONNECT request
7052 // simply returned another 407 so the unit test could skip the SSL connection
7053 // establishment and SPDY framing issues. Alas, the
7054 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307055 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597056
[email protected]f45c1ee2010-08-03 00:54:307057 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7058 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7059 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7060
[email protected]394816e92010-08-03 07:38:597061 MockWrite data_writes_2[] = {
7062 // First connection attempt without Proxy-Authorization.
7063 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7064 "Host: www.google.com\r\n"
7065 "Proxy-Connection: keep-alive\r\n"
7066 "\r\n"),
7067
7068 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307069 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7070 "Host: www.google.com\r\n"
7071 "Proxy-Connection: keep-alive\r\n"
7072 "Proxy-Authorization: auth_token\r\n"
7073 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307074
[email protected]394816e92010-08-03 07:38:597075 // SPDY request
7076 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307077 };
[email protected]394816e92010-08-03 07:38:597078 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7079 "Proxy-Authenticate: Mock\r\n"
7080 "Proxy-Connection: close\r\n"
7081 "\r\n");
7082 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7083 MockRead data_reads_2[] = {
7084 // First connection attempt fails
7085 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7086 MockRead(true, kRejectConnectResponse,
7087 arraysize(kRejectConnectResponse) - 1, 1),
7088
7089 // Second connection attempt passes
7090 MockRead(true, kAcceptConnectResponse,
7091 arraysize(kAcceptConnectResponse) -1, 4),
7092
7093 // SPDY response
7094 CreateMockRead(*resp.get(), 6),
7095 CreateMockRead(*data.get(), 6),
7096 MockRead(true, 0, 0, 6),
7097 };
7098 scoped_refptr<OrderedSocketData> data_2(
7099 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7100 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307101
7102 SSLSocketDataProvider ssl(true, OK);
7103 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7104 ssl.next_proto = "spdy/2";
7105 ssl.was_npn_negotiated = true;
7106
7107 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597108 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307109 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7110 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7111
7112 // First round should work and provide the Alternate-Protocol state.
7113 TestCompletionCallback callback_1;
7114 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7115 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7116 EXPECT_EQ(ERR_IO_PENDING, rv);
7117 EXPECT_EQ(OK, callback_1.WaitForResult());
7118
7119 // Second round should attempt a tunnel connect and get an auth challenge.
7120 TestCompletionCallback callback_2;
7121 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7122 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7123 EXPECT_EQ(ERR_IO_PENDING, rv);
7124 EXPECT_EQ(OK, callback_2.WaitForResult());
7125 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7126 ASSERT_FALSE(response == NULL);
7127 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7128
7129 // Restart with auth. Tunnel should work and response received.
7130 TestCompletionCallback callback_3;
7131 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7132 EXPECT_EQ(ERR_IO_PENDING, rv);
7133 EXPECT_EQ(OK, callback_3.WaitForResult());
7134
7135 // After all that work, these two lines (or actually, just the scheme) are
7136 // what this test is all about. Make sure it happens correctly.
7137 const GURL& request_url = auth_handler->request_url();
7138 EXPECT_EQ("https", request_url.scheme());
7139 EXPECT_EQ("www.google.com", request_url.host());
7140
[email protected]8e6441ca2010-08-19 05:56:387141 HttpStreamFactory::set_next_protos("");
7142 HttpStreamFactory::set_use_alternate_protocols(false);
7143}
7144
7145// Test that if we cancel the transaction as the connection is completing, that
7146// everything tears down correctly.
7147TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7148 // Setup everything about the connection to complete synchronously, so that
7149 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7150 // for is the callback from the HttpStreamRequest.
7151 // Then cancel the transaction.
7152 // Verify that we don't crash.
7153 MockConnect mock_connect(false, OK);
7154 MockRead data_reads[] = {
7155 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7156 MockRead(false, "hello world"),
7157 MockRead(false, OK),
7158 };
7159
7160 SessionDependencies session_deps;
7161 session_deps.host_resolver->set_synchronous_mode(true);
7162 scoped_ptr<HttpTransaction> trans(
7163 new HttpNetworkTransaction(CreateSession(&session_deps)));
7164
7165 HttpRequestInfo request;
7166 request.method = "GET";
7167 request.url = GURL("http://www.google.com/");
7168 request.load_flags = 0;
7169
7170 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7171 data.set_connect_data(mock_connect);
7172 session_deps.socket_factory.AddSocketDataProvider(&data);
7173
7174 TestCompletionCallback callback;
7175
7176 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7177 int rv = trans->Start(&request, &callback, log.bound());
7178 EXPECT_EQ(ERR_IO_PENDING, rv);
7179 trans.reset(); // Cancel the transaction here.
7180
7181 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307182}
7183
[email protected]76a505b2010-08-25 06:23:007184// Test a basic GET request through a proxy.
7185TEST_F(HttpNetworkTransactionTest, ProxyGet) {
7186 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7187 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7188 session_deps.net_log = log.bound().net_log();
7189 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7190
[email protected]76a505b2010-08-25 06:23:007191 HttpRequestInfo request;
7192 request.method = "GET";
7193 request.url = GURL("http://www.google.com/");
7194
7195 MockWrite data_writes1[] = {
7196 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7197 "Host: www.google.com\r\n"
7198 "Proxy-Connection: keep-alive\r\n\r\n"),
7199 };
7200
7201 MockRead data_reads1[] = {
7202 MockRead("HTTP/1.1 200 OK\r\n"),
7203 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7204 MockRead("Content-Length: 100\r\n\r\n"),
7205 MockRead(false, OK),
7206 };
7207
7208 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7209 data_writes1, arraysize(data_writes1));
7210 session_deps.socket_factory.AddSocketDataProvider(&data1);
7211
7212 TestCompletionCallback callback1;
7213
[email protected]0b0bf032010-09-21 18:08:507214 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7215
[email protected]76a505b2010-08-25 06:23:007216 int rv = trans->Start(&request, &callback1, log.bound());
7217 EXPECT_EQ(ERR_IO_PENDING, rv);
7218
7219 rv = callback1.WaitForResult();
7220 EXPECT_EQ(OK, rv);
7221
7222 const HttpResponseInfo* response = trans->GetResponseInfo();
7223 ASSERT_FALSE(response == NULL);
7224
7225 EXPECT_TRUE(response->headers->IsKeepAlive());
7226 EXPECT_EQ(200, response->headers->response_code());
7227 EXPECT_EQ(100, response->headers->GetContentLength());
7228 EXPECT_TRUE(response->was_fetched_via_proxy);
7229 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7230}
7231
7232// Test a basic HTTPS GET request through a proxy.
7233TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
7234 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7235 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7236 session_deps.net_log = log.bound().net_log();
7237 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7238
[email protected]76a505b2010-08-25 06:23:007239 HttpRequestInfo request;
7240 request.method = "GET";
7241 request.url = GURL("https://www.google.com/");
7242
7243 // Since we have proxy, should try to establish tunnel.
7244 MockWrite data_writes1[] = {
7245 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7246 "Host: www.google.com\r\n"
7247 "Proxy-Connection: keep-alive\r\n\r\n"),
7248
7249 MockWrite("GET / HTTP/1.1\r\n"
7250 "Host: www.google.com\r\n"
7251 "Connection: keep-alive\r\n\r\n"),
7252 };
7253
7254 MockRead data_reads1[] = {
7255 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7256
7257 MockRead("HTTP/1.1 200 OK\r\n"),
7258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7259 MockRead("Content-Length: 100\r\n\r\n"),
7260 MockRead(false, OK),
7261 };
7262
7263 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7264 data_writes1, arraysize(data_writes1));
7265 session_deps.socket_factory.AddSocketDataProvider(&data1);
7266 SSLSocketDataProvider ssl(true, OK);
7267 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7268
7269 TestCompletionCallback callback1;
7270
[email protected]0b0bf032010-09-21 18:08:507271 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7272
[email protected]76a505b2010-08-25 06:23:007273 int rv = trans->Start(&request, &callback1, log.bound());
7274 EXPECT_EQ(ERR_IO_PENDING, rv);
7275
7276 rv = callback1.WaitForResult();
7277 EXPECT_EQ(OK, rv);
7278 size_t pos = ExpectLogContainsSomewhere(
7279 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7280 NetLog::PHASE_NONE);
7281 ExpectLogContainsSomewhere(
7282 log.entries(), pos,
7283 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7284 NetLog::PHASE_NONE);
7285
7286 const HttpResponseInfo* response = trans->GetResponseInfo();
7287 ASSERT_FALSE(response == NULL);
7288
7289 EXPECT_TRUE(response->headers->IsKeepAlive());
7290 EXPECT_EQ(200, response->headers->response_code());
7291 EXPECT_EQ(100, response->headers->GetContentLength());
7292 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7293 EXPECT_TRUE(response->was_fetched_via_proxy);
7294}
7295
7296// Test a basic HTTPS GET request through a proxy, but the server hangs up
7297// while establishing the tunnel.
7298TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
7299 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7300 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7301 session_deps.net_log = log.bound().net_log();
7302 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7303
[email protected]76a505b2010-08-25 06:23:007304 HttpRequestInfo request;
7305 request.method = "GET";
7306 request.url = GURL("https://www.google.com/");
7307
7308 // Since we have proxy, should try to establish tunnel.
7309 MockWrite data_writes1[] = {
7310 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7311 "Host: www.google.com\r\n"
7312 "Proxy-Connection: keep-alive\r\n\r\n"),
7313
7314 MockWrite("GET / HTTP/1.1\r\n"
7315 "Host: www.google.com\r\n"
7316 "Connection: keep-alive\r\n\r\n"),
7317 };
7318
7319 MockRead data_reads1[] = {
7320 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7321 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7322 MockRead(true, 0, 0), // EOF
7323 };
7324
7325 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7326 data_writes1, arraysize(data_writes1));
7327 session_deps.socket_factory.AddSocketDataProvider(&data1);
7328 SSLSocketDataProvider ssl(true, OK);
7329 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7330
7331 TestCompletionCallback callback1;
7332
[email protected]0b0bf032010-09-21 18:08:507333 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7334
[email protected]76a505b2010-08-25 06:23:007335 int rv = trans->Start(&request, &callback1, log.bound());
7336 EXPECT_EQ(ERR_IO_PENDING, rv);
7337
7338 rv = callback1.WaitForResult();
7339 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7340 size_t pos = ExpectLogContainsSomewhere(
7341 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7342 NetLog::PHASE_NONE);
7343 ExpectLogContainsSomewhere(
7344 log.entries(), pos,
7345 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7346 NetLog::PHASE_NONE);
7347}
7348
[email protected]749eefa82010-09-13 22:14:037349// Test for crbug.com/55424.
7350TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7351 SessionDependencies session_deps;
7352
7353 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7354 "https://www.google.com", false, 1, LOWEST));
7355 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7356
7357 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7358 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7359 MockRead spdy_reads[] = {
7360 CreateMockRead(*resp),
7361 CreateMockRead(*data),
7362 MockRead(true, 0, 0),
7363 };
7364
7365 scoped_refptr<DelayedSocketData> spdy_data(
7366 new DelayedSocketData(
7367 1, // wait for one write to finish before reading.
7368 spdy_reads, arraysize(spdy_reads),
7369 spdy_writes, arraysize(spdy_writes)));
7370 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7371
7372 SSLSocketDataProvider ssl(true, OK);
7373 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7374 ssl.next_proto = "spdy/2";
7375 ssl.was_npn_negotiated = true;
7376 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7377
7378 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7379
7380 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387381 HostPortPair host_port_pair("www.google.com", 443);
7382 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037383 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277384 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7385 BoundNetLog());
[email protected]749eefa82010-09-13 22:14:037386 scoped_refptr<TCPSocketParams> tcp_params =
7387 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:387388 TestCompletionCallback callback;
7389
7390 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7391 EXPECT_EQ(ERR_IO_PENDING,
7392 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7393 &callback, session->tcp_socket_pool(),
7394 BoundNetLog()));
7395 EXPECT_EQ(OK, callback.WaitForResult());
7396 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037397
7398 HttpRequestInfo request;
7399 request.method = "GET";
7400 request.url = GURL("https://www.google.com/");
7401 request.load_flags = 0;
7402
7403 // This is the important line that marks this as a preconnect.
7404 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7405
7406 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7407
[email protected]749eefa82010-09-13 22:14:037408 int rv = trans->Start(&request, &callback, BoundNetLog());
7409 EXPECT_EQ(ERR_IO_PENDING, rv);
7410 EXPECT_EQ(OK, callback.WaitForResult());
7411}
7412
[email protected]89ceba9a2009-03-21 03:46:067413} // namespace net