blob: a935df963545e248cb830be53f99f7267471abe8 [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]228ff742009-06-05 01:19:5999HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54100 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]2db580532010-10-08 14:32:37101 NULL /* dnsrr_resolver */,
[email protected]80d6524d2009-08-18 03:58:09102 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42103 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10104 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56105 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17106 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44107 NULL,
[email protected]a7ea8832010-07-12 17:54:54108 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14109}
110
[email protected]89836e22008-09-25 20:33:42111class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52112 public:
[email protected]2ff8b312010-04-26 22:20:54113 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50114 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
115 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54116 spdy::SpdyFramer::set_enable_compression_default(false);
117 }
118
[email protected]0e75a732008-10-16 20:36:09119 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50120 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
121 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54122 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09123 // Empty the current queue.
124 MessageLoop::current()->RunAllPending();
125 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50126 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
127 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09128 }
129
[email protected]3d2a59b2008-09-26 19:44:25130 protected:
131 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52132
[email protected]ff007e162009-05-23 09:13:15133 struct SimpleGetHelperResult {
134 int rv;
135 std::string status_line;
136 std::string response_data;
137 };
initial.commit586acc5fe2008-07-26 22:42:52138
[email protected]31a2bfe2010-02-09 08:03:39139 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
140 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15141 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52142
[email protected]228ff742009-06-05 01:19:59143 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40144 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43145 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52146
[email protected]ff007e162009-05-23 09:13:15147 HttpRequestInfo request;
148 request.method = "GET";
149 request.url = GURL("http://www.google.com/");
150 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52151
[email protected]31a2bfe2010-02-09 08:03:39152 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59153 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52154
[email protected]ff007e162009-05-23 09:13:15155 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52156
[email protected]169d0012010-05-10 23:20:12157 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
158 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15159 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52160
[email protected]ff007e162009-05-23 09:13:15161 out.rv = callback.WaitForResult();
162 if (out.rv != OK)
163 return out;
164
165 const HttpResponseInfo* response = trans->GetResponseInfo();
166 EXPECT_TRUE(response != NULL);
167
168 EXPECT_TRUE(response->headers != NULL);
169 out.status_line = response->headers->GetStatusLine();
170
171 rv = ReadTransaction(trans.get(), &out.response_data);
172 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39173 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12174 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
175 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39176 ExpectLogContainsSomewhere(
177 log.entries(), pos,
178 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
179 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15180
[email protected]aecfbf22008-10-16 02:02:47181 return out;
[email protected]ff007e162009-05-23 09:13:15182 }
initial.commit586acc5fe2008-07-26 22:42:52183
[email protected]ff007e162009-05-23 09:13:15184 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
185 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52186
[email protected]ff007e162009-05-23 09:13:15187 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15188};
[email protected]231d5a32008-09-13 00:45:27189
[email protected]15a5ccf82008-10-23 19:57:43190// Fill |str| with a long header list that consumes >= |size| bytes.
191void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19192 const char* row =
193 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
194 const int sizeof_row = strlen(row);
195 const int num_rows = static_cast<int>(
196 ceil(static_cast<float>(size) / sizeof_row));
197 const int sizeof_data = num_rows * sizeof_row;
198 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43199 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51200
[email protected]4ddaf2502008-10-23 18:26:19201 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43202 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19203}
204
[email protected]385a4672009-03-11 22:21:29205// Alternative functions that eliminate randomness and dependency on the local
206// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20207void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29208 static const uint8 bytes[] = {
209 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
210 };
211 static size_t current_byte = 0;
212 for (size_t i = 0; i < n; ++i) {
213 output[i] = bytes[current_byte++];
214 current_byte %= arraysize(bytes);
215 }
216}
217
[email protected]fe2bc6a2009-03-23 16:52:20218void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29219 static const uint8 bytes[] = {
220 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
221 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
222 };
223 static size_t current_byte = 0;
224 for (size_t i = 0; i < n; ++i) {
225 output[i] = bytes[current_byte++];
226 current_byte %= arraysize(bytes);
227 }
228}
229
[email protected]fe2bc6a2009-03-23 16:52:20230std::string MockGetHostName() {
231 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29232}
233
[email protected]e60e47a2010-07-14 03:37:18234template<typename ParentPool>
235class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31236 public:
[email protected]e60e47a2010-07-14 03:37:18237 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
238
[email protected]d80a4322009-08-14 07:07:49239 const std::string last_group_name_received() const {
240 return last_group_name_;
241 }
242
[email protected]684970b2009-08-14 04:54:46243 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49244 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31245 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31246 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46247 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53248 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31249 last_group_name_ = group_name;
250 return ERR_IO_PENDING;
251 }
[email protected]04e5be32009-06-26 20:00:31252 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21253 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31254 virtual void ReleaseSocket(const std::string& group_name,
255 ClientSocket* socket) {}
256 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31257 virtual int IdleSocketCount() const {
258 return 0;
259 }
260 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
261 return 0;
262 }
263 virtual LoadState GetLoadState(const std::string& group_name,
264 const ClientSocketHandle* handle) const {
265 return LOAD_STATE_IDLE;
266 }
[email protected]a796bcec2010-03-22 17:17:26267 virtual base::TimeDelta ConnectionTimeout() const {
268 return base::TimeDelta();
269 }
[email protected]d80a4322009-08-14 07:07:49270
271 private:
[email protected]04e5be32009-06-26 20:00:31272 std::string last_group_name_;
273};
274
[email protected]2d731a32010-04-29 01:04:06275typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11276CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13277typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
278CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06279typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11280CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18281typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
282CaptureGroupNameSSLSocketPool;
283
284template<typename ParentPool>
285CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
286 HttpNetworkSession* session)
287 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
288
289template<>
[email protected]2df19bb2010-08-25 20:13:46290CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
291 HttpNetworkSession* session)
292 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
293 NULL, NULL) {}
294
295template<>
[email protected]e60e47a2010-07-14 03:37:18296CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
297 HttpNetworkSession* session)
298 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
[email protected]2db580532010-10-08 14:32:37299 NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11300
[email protected]231d5a32008-09-13 00:45:27301//-----------------------------------------------------------------------------
302
[email protected]dae22c52010-07-30 02:16:35303// This is the expected list of advertised protocols from the browser's NPN
304// list.
305static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
306
307// This is the expected return from a current server advertising SPDY.
308static const char kAlternateProtocolHttpHeader[] =
309 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
310
[email protected]231d5a32008-09-13 00:45:27311TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59312 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40313 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43314 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27315}
316
317TEST_F(HttpNetworkTransactionTest, SimpleGET) {
318 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35319 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
320 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42321 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27322 };
[email protected]31a2bfe2010-02-09 08:03:39323 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
324 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42325 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27326 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
327 EXPECT_EQ("hello world", out.response_data);
328}
329
330// Response with no status line.
331TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
332 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35333 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42334 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27335 };
[email protected]31a2bfe2010-02-09 08:03:39336 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
337 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42338 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27339 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
340 EXPECT_EQ("hello world", out.response_data);
341}
342
343// Allow up to 4 bytes of junk to precede status line.
344TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
345 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35346 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42347 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27348 };
[email protected]31a2bfe2010-02-09 08:03:39349 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
350 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42351 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27352 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
353 EXPECT_EQ("DATA", out.response_data);
354}
355
356// Allow up to 4 bytes of junk to precede status line.
357TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
358 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35359 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42360 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27361 };
[email protected]31a2bfe2010-02-09 08:03:39362 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
363 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42364 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27365 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
366 EXPECT_EQ("DATA", out.response_data);
367}
368
369// Beyond 4 bytes of slop and it should fail to find a status line.
370TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
371 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35372 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42373 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27374 };
[email protected]31a2bfe2010-02-09 08:03:39375 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
376 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42377 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25378 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
379 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27380}
381
382// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
383TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
384 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35385 MockRead("\n"),
386 MockRead("\n"),
387 MockRead("Q"),
388 MockRead("J"),
389 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42390 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27391 };
[email protected]31a2bfe2010-02-09 08:03:39392 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
393 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42394 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27395 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
396 EXPECT_EQ("DATA", out.response_data);
397}
398
399// Close the connection before enough bytes to have a status line.
400TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
401 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35402 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42403 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27404 };
[email protected]31a2bfe2010-02-09 08:03:39405 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
406 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42407 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27408 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
409 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52410}
411
[email protected]f9d44aa2008-09-23 23:57:17412// Simulate a 204 response, lacking a Content-Length header, sent over a
413// persistent connection. The response should still terminate since a 204
414// cannot have a response body.
415TEST_F(HttpNetworkTransactionTest, StopsReading204) {
416 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35417 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
418 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42419 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17420 };
[email protected]31a2bfe2010-02-09 08:03:39421 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
422 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42423 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17424 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
425 EXPECT_EQ("", out.response_data);
426}
427
[email protected]0877e3d2009-10-17 22:29:57428// A simple request using chunked encoding with some extra data after.
429// (Like might be seen in a pipelined response.)
430TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
431 MockRead data_reads[] = {
432 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
433 MockRead("5\r\nHello\r\n"),
434 MockRead("1\r\n"),
435 MockRead(" \r\n"),
436 MockRead("5\r\nworld\r\n"),
437 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
438 MockRead(false, OK),
439 };
[email protected]31a2bfe2010-02-09 08:03:39440 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
441 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57442 EXPECT_EQ(OK, out.rv);
443 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
444 EXPECT_EQ("Hello world", out.response_data);
445}
446
[email protected]9fe44f52010-09-23 18:36:00447// Next tests deal with http://crbug.com/56344.
448
449TEST_F(HttpNetworkTransactionTest,
450 MultipleContentLengthHeadersNoTransferEncoding) {
451 MockRead data_reads[] = {
452 MockRead("HTTP/1.1 200 OK\r\n"),
453 MockRead("Content-Length: 10\r\n"),
454 MockRead("Content-Length: 5\r\n\r\n"),
455 };
456 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
457 arraysize(data_reads));
458 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
459}
460
461TEST_F(HttpNetworkTransactionTest,
462 MultipleContentLengthHeadersTransferEncoding) {
463 MockRead data_reads[] = {
464 MockRead("HTTP/1.1 200 OK\r\n"),
465 MockRead("Content-Length: 666\r\n"),
466 MockRead("Content-Length: 1337\r\n"),
467 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
468 MockRead("5\r\nHello\r\n"),
469 MockRead("1\r\n"),
470 MockRead(" \r\n"),
471 MockRead("5\r\nworld\r\n"),
472 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
473 MockRead(false, OK),
474 };
475 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
476 arraysize(data_reads));
477 EXPECT_EQ(OK, out.rv);
478 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
479 EXPECT_EQ("Hello world", out.response_data);
480}
481
[email protected]ef0faf2e72009-03-05 23:27:23482// Do a request using the HEAD method. Verify that we don't try to read the
483// message body (since HEAD has none).
484TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59485 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40486 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43487 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23488
[email protected]1c773ea12009-04-28 19:58:42489 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23490 request.method = "HEAD";
491 request.url = GURL("http://www.google.com/");
492 request.load_flags = 0;
493
494 MockWrite data_writes1[] = {
495 MockWrite("HEAD / HTTP/1.1\r\n"
496 "Host: www.google.com\r\n"
497 "Connection: keep-alive\r\n"
498 "Content-Length: 0\r\n\r\n"),
499 };
500 MockRead data_reads1[] = {
501 MockRead("HTTP/1.1 404 Not Found\r\n"),
502 MockRead("Server: Blah\r\n"),
503 MockRead("Content-Length: 1234\r\n\r\n"),
504
505 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42506 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23507 };
508
[email protected]31a2bfe2010-02-09 08:03:39509 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
510 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59511 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23512
513 TestCompletionCallback callback1;
514
[email protected]5a1d7ca2010-04-28 20:12:27515 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42516 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23517
518 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42519 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23520
[email protected]1c773ea12009-04-28 19:58:42521 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23522 EXPECT_FALSE(response == NULL);
523
524 // Check that the headers got parsed.
525 EXPECT_TRUE(response->headers != NULL);
526 EXPECT_EQ(1234, response->headers->GetContentLength());
527 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
528
529 std::string server_header;
530 void* iter = NULL;
531 bool has_server_header = response->headers->EnumerateHeader(
532 &iter, "Server", &server_header);
533 EXPECT_TRUE(has_server_header);
534 EXPECT_EQ("Blah", server_header);
535
536 // Reading should give EOF right away, since there is no message body
537 // (despite non-zero content-length).
538 std::string response_data;
539 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42540 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23541 EXPECT_EQ("", response_data);
542}
543
initial.commit586acc5fe2008-07-26 22:42:52544TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59545 SessionDependencies session_deps;
546 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52547
548 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35549 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
550 MockRead("hello"),
551 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
552 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42553 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52554 };
[email protected]31a2bfe2010-02-09 08:03:39555 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59556 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52557
[email protected]0b0bf032010-09-21 18:08:50558 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52559 "hello", "world"
560 };
561
562 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43563 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52564
[email protected]1c773ea12009-04-28 19:58:42565 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52566 request.method = "GET";
567 request.url = GURL("http://www.google.com/");
568 request.load_flags = 0;
569
570 TestCompletionCallback callback;
571
[email protected]5a1d7ca2010-04-28 20:12:27572 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42573 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52574
575 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42576 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52577
[email protected]1c773ea12009-04-28 19:58:42578 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52579 EXPECT_TRUE(response != NULL);
580
581 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25582 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52583
584 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57585 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42586 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25587 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52588 }
589}
590
591TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59592 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40593 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43594 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52595
[email protected]1c773ea12009-04-28 19:58:42596 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52597 request.method = "POST";
598 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42599 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52600 request.upload_data->AppendBytes("foo", 3);
601 request.load_flags = 0;
602
603 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35604 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
605 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
606 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42607 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52608 };
[email protected]31a2bfe2010-02-09 08:03:39609 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59610 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52611
612 TestCompletionCallback callback;
613
[email protected]5a1d7ca2010-04-28 20:12:27614 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42615 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52616
617 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42618 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52619
[email protected]1c773ea12009-04-28 19:58:42620 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52621 EXPECT_TRUE(response != NULL);
622
623 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25624 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52625
626 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57627 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42628 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25629 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52630}
631
[email protected]3a2d3662009-03-27 03:49:14632// This test is almost the same as Ignores100 above, but the response contains
633// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57634// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14635TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59636 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40637 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43638 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14639
[email protected]1c773ea12009-04-28 19:58:42640 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14641 request.method = "GET";
642 request.url = GURL("http://www.foo.com/");
643 request.load_flags = 0;
644
645 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57646 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
647 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14648 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42649 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14650 };
[email protected]31a2bfe2010-02-09 08:03:39651 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59652 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14653
654 TestCompletionCallback callback;
655
[email protected]5a1d7ca2010-04-28 20:12:27656 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42657 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14658
659 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42660 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14661
[email protected]1c773ea12009-04-28 19:58:42662 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14663 EXPECT_TRUE(response != NULL);
664
665 EXPECT_TRUE(response->headers != NULL);
666 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
667
668 std::string response_data;
669 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42670 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14671 EXPECT_EQ("hello world", response_data);
672}
673
[email protected]ee9410e72010-01-07 01:42:38674TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
675 SessionDependencies session_deps;
676 scoped_ptr<HttpTransaction> trans(
677 new HttpNetworkTransaction(CreateSession(&session_deps)));
678
679 HttpRequestInfo request;
680 request.method = "POST";
681 request.url = GURL("http://www.foo.com/");
682 request.load_flags = 0;
683
684 MockRead data_reads[] = {
685 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
686 MockRead(true, 0),
687 };
[email protected]31a2bfe2010-02-09 08:03:39688 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38689 session_deps.socket_factory.AddSocketDataProvider(&data);
690
691 TestCompletionCallback callback;
692
[email protected]5a1d7ca2010-04-28 20:12:27693 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38694 EXPECT_EQ(ERR_IO_PENDING, rv);
695
696 rv = callback.WaitForResult();
697 EXPECT_EQ(OK, rv);
698
699 std::string response_data;
700 rv = ReadTransaction(trans.get(), &response_data);
701 EXPECT_EQ(OK, rv);
702 EXPECT_EQ("", response_data);
703}
704
705TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
706 SessionDependencies session_deps;
707 scoped_ptr<HttpTransaction> trans(
708 new HttpNetworkTransaction(CreateSession(&session_deps)));
709
710 HttpRequestInfo request;
711 request.method = "POST";
712 request.url = GURL("http://www.foo.com/");
713 request.load_flags = 0;
714
715 MockRead data_reads[] = {
716 MockRead(true, 0),
717 };
[email protected]31a2bfe2010-02-09 08:03:39718 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38719 session_deps.socket_factory.AddSocketDataProvider(&data);
720
721 TestCompletionCallback callback;
722
[email protected]5a1d7ca2010-04-28 20:12:27723 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38724 EXPECT_EQ(ERR_IO_PENDING, rv);
725
726 rv = callback.WaitForResult();
727 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
728}
729
[email protected]3d2a59b2008-09-26 19:44:25730// read_failure specifies a read failure that should cause the network
731// transaction to resend the request.
732void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
733 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59734 SessionDependencies session_deps;
735 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52736
[email protected]1c773ea12009-04-28 19:58:42737 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52738 request.method = "GET";
739 request.url = GURL("http://www.foo.com/");
740 request.load_flags = 0;
741
742 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35743 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
744 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25745 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52746 };
[email protected]31a2bfe2010-02-09 08:03:39747 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59748 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52749
750 MockRead data2_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("world"),
[email protected]1c773ea12009-04-28 19:58:42753 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52754 };
[email protected]31a2bfe2010-02-09 08:03:39755 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59756 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52757
758 const char* kExpectedResponseData[] = {
759 "hello", "world"
760 };
761
762 for (int i = 0; i < 2; ++i) {
763 TestCompletionCallback callback;
764
[email protected]5695b8c2009-09-30 21:36:43765 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52766
[email protected]5a1d7ca2010-04-28 20:12:27767 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42768 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52769
770 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42771 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52772
[email protected]1c773ea12009-04-28 19:58:42773 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52774 EXPECT_TRUE(response != NULL);
775
776 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25777 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52778
779 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57780 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42781 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25782 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52783 }
784}
[email protected]3d2a59b2008-09-26 19:44:25785
786TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42787 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25788 KeepAliveConnectionResendRequestTest(read_failure);
789}
790
791TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42792 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25793 KeepAliveConnectionResendRequestTest(read_failure);
794}
795
796TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59797 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40798 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43799 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25800
[email protected]1c773ea12009-04-28 19:58:42801 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25802 request.method = "GET";
803 request.url = GURL("http://www.google.com/");
804 request.load_flags = 0;
805
806 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42807 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35808 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
809 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42810 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25811 };
[email protected]31a2bfe2010-02-09 08:03:39812 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59813 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25814
815 TestCompletionCallback callback;
816
[email protected]5a1d7ca2010-04-28 20:12:27817 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42818 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25819
820 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42821 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25822
[email protected]1c773ea12009-04-28 19:58:42823 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25824 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25825}
826
827// What do various browsers do when the server closes a non-keepalive
828// connection without sending any response header or body?
829//
830// IE7: error page
831// Safari 3.1.2 (Windows): error page
832// Firefox 3.0.1: blank page
833// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42834// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
835// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25836TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
837 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42838 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35839 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
840 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42841 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25842 };
[email protected]31a2bfe2010-02-09 08:03:39843 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
844 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42845 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25846}
[email protected]038e9a32008-10-08 22:40:16847
[email protected]0b0bf032010-09-21 18:08:50848// Test that we correctly reuse a keep-alive connection after not explicitly
849// reading the body.
850TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13851 SessionDependencies session_deps;
852 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
853
854 HttpRequestInfo request;
855 request.method = "GET";
856 request.url = GURL("http://www.foo.com/");
857 request.load_flags = 0;
858
[email protected]0b0bf032010-09-21 18:08:50859 // Note that because all these reads happen in the same
860 // StaticSocketDataProvider, it shows that the same socket is being reused for
861 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13862 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50863 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
864 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13865 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50866 MockRead("HTTP/1.1 302 Found\r\n"
867 "Content-Length: 0\r\n\r\n"),
868 MockRead("HTTP/1.1 302 Found\r\n"
869 "Content-Length: 5\r\n\r\n"
870 "hello"),
871 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
872 "Content-Length: 0\r\n\r\n"),
873 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
874 "Content-Length: 5\r\n\r\n"
875 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13876 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
877 MockRead("hello"),
878 };
879 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
880 session_deps.socket_factory.AddSocketDataProvider(&data1);
881
882 MockRead data2_reads[] = {
883 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
884 };
885 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
886 session_deps.socket_factory.AddSocketDataProvider(&data2);
887
[email protected]0b0bf032010-09-21 18:08:50888 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
889 std::string response_lines[kNumUnreadBodies];
890
891 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13892 TestCompletionCallback callback;
893
894 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
895
896 int rv = trans->Start(&request, &callback, BoundNetLog());
897 EXPECT_EQ(ERR_IO_PENDING, rv);
898
899 rv = callback.WaitForResult();
900 EXPECT_EQ(OK, rv);
901
902 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50903 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13904
[email protected]0b0bf032010-09-21 18:08:50905 ASSERT_TRUE(response->headers != NULL);
906 response_lines[i] = response->headers->GetStatusLine();
907
908 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13909 }
[email protected]0b0bf032010-09-21 18:08:50910
911 const char* const kStatusLines[] = {
912 "HTTP/1.1 204 No Content",
913 "HTTP/1.1 205 Reset Content",
914 "HTTP/1.1 304 Not Modified",
915 "HTTP/1.1 302 Found",
916 "HTTP/1.1 302 Found",
917 "HTTP/1.1 301 Moved Permanently",
918 "HTTP/1.1 301 Moved Permanently",
919 };
920
921 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
922 forgot_to_update_kStatusLines);
923
924 for (int i = 0; i < kNumUnreadBodies; ++i)
925 EXPECT_EQ(kStatusLines[i], response_lines[i]);
926
927 TestCompletionCallback callback;
928 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
929 int rv = trans->Start(&request, &callback, BoundNetLog());
930 EXPECT_EQ(ERR_IO_PENDING, rv);
931 rv = callback.WaitForResult();
932 EXPECT_EQ(OK, rv);
933 const HttpResponseInfo* response = trans->GetResponseInfo();
934 ASSERT_TRUE(response != NULL);
935 ASSERT_TRUE(response->headers != NULL);
936 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
937 std::string response_data;
938 rv = ReadTransaction(trans.get(), &response_data);
939 EXPECT_EQ(OK, rv);
940 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:13941}
942
[email protected]038e9a32008-10-08 22:40:16943// Test the request-challenge-retry sequence for basic auth.
944// (basic auth is the easiest to mock, because it has no randomness).
945TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59946 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40947 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43948 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16949
[email protected]1c773ea12009-04-28 19:58:42950 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16951 request.method = "GET";
952 request.url = GURL("http://www.google.com/");
953 request.load_flags = 0;
954
[email protected]f9ee6b52008-11-08 06:46:23955 MockWrite data_writes1[] = {
956 MockWrite("GET / HTTP/1.1\r\n"
957 "Host: www.google.com\r\n"
958 "Connection: keep-alive\r\n\r\n"),
959 };
960
[email protected]038e9a32008-10-08 22:40:16961 MockRead data_reads1[] = {
962 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
963 // Give a couple authenticate options (only the middle one is actually
964 // supported).
[email protected]22927ad2009-09-21 19:56:19965 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16966 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
967 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
969 // Large content-length -- won't matter, as connection will be reset.
970 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42971 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16972 };
973
974 // After calling trans->RestartWithAuth(), this is the request we should
975 // be issuing -- the final header line contains the credentials.
976 MockWrite data_writes2[] = {
977 MockWrite("GET / HTTP/1.1\r\n"
978 "Host: www.google.com\r\n"
979 "Connection: keep-alive\r\n"
980 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
981 };
982
983 // Lastly, the server responds with the actual content.
984 MockRead data_reads2[] = {
985 MockRead("HTTP/1.0 200 OK\r\n"),
986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
987 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42988 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16989 };
990
[email protected]31a2bfe2010-02-09 08:03:39991 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
992 data_writes1, arraysize(data_writes1));
993 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
994 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59995 session_deps.socket_factory.AddSocketDataProvider(&data1);
996 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16997
998 TestCompletionCallback callback1;
999
[email protected]5a1d7ca2010-04-28 20:12:271000 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421001 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161002
1003 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421004 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161005
[email protected]1c773ea12009-04-28 19:58:421006 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161007 EXPECT_FALSE(response == NULL);
1008
1009 // The password prompt info should have been set in response->auth_challenge.
1010 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1011
[email protected]71e4573a2009-05-21 22:03:001012 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161013 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1014 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1015
1016 TestCompletionCallback callback2;
1017
[email protected]13c8a092010-07-29 06:15:441018 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421019 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161020
1021 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421022 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161023
1024 response = trans->GetResponseInfo();
1025 EXPECT_FALSE(response == NULL);
1026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1027 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161028}
1029
[email protected]861fcd52009-08-26 02:33:461030TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1031 SessionDependencies session_deps;
1032 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431033 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461034
1035 HttpRequestInfo request;
1036 request.method = "GET";
1037 request.url = GURL("http://www.google.com/");
1038 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1039
1040 MockWrite data_writes[] = {
1041 MockWrite("GET / HTTP/1.1\r\n"
1042 "Host: www.google.com\r\n"
1043 "Connection: keep-alive\r\n\r\n"),
1044 };
1045
1046 MockRead data_reads[] = {
1047 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1050 // Large content-length -- won't matter, as connection will be reset.
1051 MockRead("Content-Length: 10000\r\n\r\n"),
1052 MockRead(false, ERR_FAILED),
1053 };
1054
[email protected]31a2bfe2010-02-09 08:03:391055 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1056 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591057 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461058 TestCompletionCallback callback;
1059
[email protected]5a1d7ca2010-04-28 20:12:271060 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461061 EXPECT_EQ(ERR_IO_PENDING, rv);
1062
1063 rv = callback.WaitForResult();
1064 EXPECT_EQ(0, rv);
1065
1066 const HttpResponseInfo* response = trans->GetResponseInfo();
1067 ASSERT_FALSE(response == NULL);
1068 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1069}
1070
[email protected]2d2697f92009-02-18 21:00:321071// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1072// connection.
1073TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591074 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501075 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321076
[email protected]1c773ea12009-04-28 19:58:421077 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321078 request.method = "GET";
1079 request.url = GURL("http://www.google.com/");
1080 request.load_flags = 0;
1081
1082 MockWrite data_writes1[] = {
1083 MockWrite("GET / HTTP/1.1\r\n"
1084 "Host: www.google.com\r\n"
1085 "Connection: keep-alive\r\n\r\n"),
1086
1087 // After calling trans->RestartWithAuth(), this is the request we should
1088 // be issuing -- the final header line contains the credentials.
1089 MockWrite("GET / HTTP/1.1\r\n"
1090 "Host: www.google.com\r\n"
1091 "Connection: keep-alive\r\n"
1092 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1093 };
1094
1095 MockRead data_reads1[] = {
1096 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1097 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1098 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1099 MockRead("Content-Length: 14\r\n\r\n"),
1100 MockRead("Unauthorized\r\n"),
1101
1102 // Lastly, the server responds with the actual content.
1103 MockRead("HTTP/1.1 200 OK\r\n"),
1104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501105 MockRead("Content-Length: 5\r\n\r\n"),
1106 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321107 };
1108
[email protected]31a2bfe2010-02-09 08:03:391109 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1110 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591111 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321112
1113 TestCompletionCallback callback1;
1114
[email protected]0b0bf032010-09-21 18:08:501115 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271116 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421117 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321118
1119 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421120 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321121
[email protected]1c773ea12009-04-28 19:58:421122 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321123 EXPECT_FALSE(response == NULL);
1124
1125 // The password prompt info should have been set in response->auth_challenge.
1126 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1127
[email protected]71e4573a2009-05-21 22:03:001128 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321129 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1130 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1131
1132 TestCompletionCallback callback2;
1133
[email protected]13c8a092010-07-29 06:15:441134 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421135 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321136
1137 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421138 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321139
1140 response = trans->GetResponseInfo();
1141 EXPECT_FALSE(response == NULL);
1142 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501143 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321144}
1145
1146// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1147// connection and with no response body to drain.
1148TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591149 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501150 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321151
[email protected]1c773ea12009-04-28 19:58:421152 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321153 request.method = "GET";
1154 request.url = GURL("http://www.google.com/");
1155 request.load_flags = 0;
1156
1157 MockWrite data_writes1[] = {
1158 MockWrite("GET / HTTP/1.1\r\n"
1159 "Host: www.google.com\r\n"
1160 "Connection: keep-alive\r\n\r\n"),
1161
1162 // After calling trans->RestartWithAuth(), this is the request we should
1163 // be issuing -- the final header line contains the credentials.
1164 MockWrite("GET / HTTP/1.1\r\n"
1165 "Host: www.google.com\r\n"
1166 "Connection: keep-alive\r\n"
1167 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1168 };
1169
[email protected]2d2697f92009-02-18 21:00:321170 MockRead data_reads1[] = {
1171 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1172 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311173 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321174
1175 // Lastly, the server responds with the actual content.
1176 MockRead("HTTP/1.1 200 OK\r\n"),
1177 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501178 MockRead("Content-Length: 5\r\n\r\n"),
1179 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321180 };
1181
[email protected]31a2bfe2010-02-09 08:03:391182 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1183 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591184 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321185
1186 TestCompletionCallback callback1;
1187
[email protected]0b0bf032010-09-21 18:08:501188 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271189 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421190 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321191
1192 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421193 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321194
[email protected]1c773ea12009-04-28 19:58:421195 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321196 EXPECT_FALSE(response == NULL);
1197
1198 // The password prompt info should have been set in response->auth_challenge.
1199 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1200
[email protected]71e4573a2009-05-21 22:03:001201 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321202 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1203 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1204
1205 TestCompletionCallback callback2;
1206
[email protected]13c8a092010-07-29 06:15:441207 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421208 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321209
1210 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421211 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321212
1213 response = trans->GetResponseInfo();
1214 EXPECT_FALSE(response == NULL);
1215 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501216 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321217}
1218
1219// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1220// connection and with a large response body to drain.
1221TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591222 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501223 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321224
[email protected]1c773ea12009-04-28 19:58:421225 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321226 request.method = "GET";
1227 request.url = GURL("http://www.google.com/");
1228 request.load_flags = 0;
1229
1230 MockWrite data_writes1[] = {
1231 MockWrite("GET / HTTP/1.1\r\n"
1232 "Host: www.google.com\r\n"
1233 "Connection: keep-alive\r\n\r\n"),
1234
1235 // After calling trans->RestartWithAuth(), this is the request we should
1236 // be issuing -- the final header line contains the credentials.
1237 MockWrite("GET / HTTP/1.1\r\n"
1238 "Host: www.google.com\r\n"
1239 "Connection: keep-alive\r\n"
1240 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1241 };
1242
1243 // Respond with 5 kb of response body.
1244 std::string large_body_string("Unauthorized");
1245 large_body_string.append(5 * 1024, ' ');
1246 large_body_string.append("\r\n");
1247
1248 MockRead data_reads1[] = {
1249 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1250 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1252 // 5134 = 12 + 5 * 1024 + 2
1253 MockRead("Content-Length: 5134\r\n\r\n"),
1254 MockRead(true, large_body_string.data(), large_body_string.size()),
1255
1256 // Lastly, the server responds with the actual content.
1257 MockRead("HTTP/1.1 200 OK\r\n"),
1258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501259 MockRead("Content-Length: 5\r\n\r\n"),
1260 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321261 };
1262
[email protected]31a2bfe2010-02-09 08:03:391263 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1264 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591265 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321266
1267 TestCompletionCallback callback1;
1268
[email protected]0b0bf032010-09-21 18:08:501269 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271270 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421271 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321272
1273 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421274 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321275
[email protected]1c773ea12009-04-28 19:58:421276 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321277 EXPECT_FALSE(response == NULL);
1278
1279 // The password prompt info should have been set in response->auth_challenge.
1280 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1281
[email protected]71e4573a2009-05-21 22:03:001282 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321283 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1284 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1285
1286 TestCompletionCallback callback2;
1287
[email protected]13c8a092010-07-29 06:15:441288 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421289 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321290
1291 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421292 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321293
1294 response = trans->GetResponseInfo();
1295 EXPECT_FALSE(response == NULL);
1296 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501297 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321298}
1299
1300// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311301// connection, but the server gets impatient and closes the connection.
1302TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1303 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311305
1306 HttpRequestInfo request;
1307 request.method = "GET";
1308 request.url = GURL("http://www.google.com/");
1309 request.load_flags = 0;
1310
1311 MockWrite data_writes1[] = {
1312 MockWrite("GET / HTTP/1.1\r\n"
1313 "Host: www.google.com\r\n"
1314 "Connection: keep-alive\r\n\r\n"),
1315 // This simulates the seemingly successful write to a closed connection
1316 // if the bug is not fixed.
1317 MockWrite("GET / HTTP/1.1\r\n"
1318 "Host: www.google.com\r\n"
1319 "Connection: keep-alive\r\n"
1320 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1321 };
1322
1323 MockRead data_reads1[] = {
1324 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1325 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1326 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1327 MockRead("Content-Length: 14\r\n\r\n"),
1328 // Tell MockTCPClientSocket to simulate the server closing the connection.
1329 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1330 MockRead("Unauthorized\r\n"),
1331 MockRead(false, OK), // The server closes the connection.
1332 };
1333
1334 // After calling trans->RestartWithAuth(), this is the request we should
1335 // be issuing -- the final header line contains the credentials.
1336 MockWrite data_writes2[] = {
1337 MockWrite("GET / HTTP/1.1\r\n"
1338 "Host: www.google.com\r\n"
1339 "Connection: keep-alive\r\n"
1340 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1341 };
1342
1343 // Lastly, the server responds with the actual content.
1344 MockRead data_reads2[] = {
1345 MockRead("HTTP/1.1 200 OK\r\n"),
1346 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501347 MockRead("Content-Length: 5\r\n\r\n"),
1348 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311349 };
1350
[email protected]31a2bfe2010-02-09 08:03:391351 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1352 data_writes1, arraysize(data_writes1));
1353 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1354 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311355 session_deps.socket_factory.AddSocketDataProvider(&data1);
1356 session_deps.socket_factory.AddSocketDataProvider(&data2);
1357
1358 TestCompletionCallback callback1;
1359
[email protected]0b0bf032010-09-21 18:08:501360 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271361 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311362 EXPECT_EQ(ERR_IO_PENDING, rv);
1363
1364 rv = callback1.WaitForResult();
1365 EXPECT_EQ(OK, rv);
1366
1367 const HttpResponseInfo* response = trans->GetResponseInfo();
1368 EXPECT_FALSE(response == NULL);
1369
1370 // The password prompt info should have been set in response->auth_challenge.
1371 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1372
1373 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1374 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1375 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1376
1377 TestCompletionCallback callback2;
1378
[email protected]13c8a092010-07-29 06:15:441379 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311380 EXPECT_EQ(ERR_IO_PENDING, rv);
1381
1382 rv = callback2.WaitForResult();
1383 EXPECT_EQ(OK, rv);
1384
1385 response = trans->GetResponseInfo();
1386 ASSERT_FALSE(response == NULL);
1387 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501388 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311389}
1390
[email protected]394816e92010-08-03 07:38:591391// Test the request-challenge-retry sequence for basic auth, over a connection
1392// that requires a restart when setting up an SSL tunnel.
1393TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1394 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001395 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]394816e92010-08-03 07:38:591396 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1397 session_deps.net_log = log.bound().net_log();
1398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1399
[email protected]394816e92010-08-03 07:38:591400 HttpRequestInfo request;
1401 request.method = "GET";
1402 request.url = GURL("https://www.google.com/");
1403 // when the no authentication data flag is set.
1404 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1405
1406 // Since we have proxy, should try to establish tunnel.
1407 MockWrite data_writes1[] = {
1408 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1409 "Host: www.google.com\r\n"
1410 "Proxy-Connection: keep-alive\r\n\r\n"),
1411
1412 // After calling trans->RestartWithAuth(), this is the request we should
1413 // be issuing -- the final header line contains the credentials.
1414 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1415 "Host: www.google.com\r\n"
1416 "Proxy-Connection: keep-alive\r\n"
1417 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1418
1419 MockWrite("GET / HTTP/1.1\r\n"
1420 "Host: www.google.com\r\n"
1421 "Connection: keep-alive\r\n\r\n"),
1422 };
1423
1424 // The proxy responds to the connect with a 407, using a persistent
1425 // connection.
1426 MockRead data_reads1[] = {
1427 // No credentials.
1428 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1429 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1430 MockRead("Proxy-Connection: close\r\n\r\n"),
1431
1432 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1433
1434 MockRead("HTTP/1.1 200 OK\r\n"),
1435 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501436 MockRead("Content-Length: 5\r\n\r\n"),
1437 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591438 };
1439
1440 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1441 data_writes1, arraysize(data_writes1));
1442 session_deps.socket_factory.AddSocketDataProvider(&data1);
1443 SSLSocketDataProvider ssl(true, OK);
1444 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1445
1446 TestCompletionCallback callback1;
1447
[email protected]0b0bf032010-09-21 18:08:501448 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1449
[email protected]394816e92010-08-03 07:38:591450 int rv = trans->Start(&request, &callback1, log.bound());
1451 EXPECT_EQ(ERR_IO_PENDING, rv);
1452
1453 rv = callback1.WaitForResult();
1454 EXPECT_EQ(OK, rv);
1455 size_t pos = ExpectLogContainsSomewhere(
1456 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1457 NetLog::PHASE_NONE);
1458 ExpectLogContainsSomewhere(
1459 log.entries(), pos,
1460 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1461 NetLog::PHASE_NONE);
1462
1463 const HttpResponseInfo* response = trans->GetResponseInfo();
1464 ASSERT_FALSE(response == NULL);
1465
1466 EXPECT_EQ(407, response->headers->response_code());
1467 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1468
1469 // The password prompt info should have been set in response->auth_challenge.
1470 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1471
1472 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1473 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1474 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1475
1476 TestCompletionCallback callback2;
1477
1478 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1479 EXPECT_EQ(ERR_IO_PENDING, rv);
1480
1481 rv = callback2.WaitForResult();
1482 EXPECT_EQ(OK, rv);
1483
1484 response = trans->GetResponseInfo();
1485 ASSERT_FALSE(response == NULL);
1486
1487 EXPECT_TRUE(response->headers->IsKeepAlive());
1488 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501489 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591490 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1491
1492 // The password prompt info should not be set.
1493 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501494
1495 trans.reset();
1496 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591497}
1498
[email protected]11203f012009-11-12 23:02:311499// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321500// proxy connection, when setting up an SSL tunnel.
1501TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1502 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001503 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541504 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1505 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591506 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321507
[email protected]5695b8c2009-09-30 21:36:431508 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321509
[email protected]1c773ea12009-04-28 19:58:421510 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321511 request.method = "GET";
1512 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461513 // Ensure that proxy authentication is attempted even
1514 // when the no authentication data flag is set.
1515 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321516
1517 // Since we have proxy, should try to establish tunnel.
1518 MockWrite data_writes1[] = {
1519 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451520 "Host: www.google.com\r\n"
1521 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321522
1523 // After calling trans->RestartWithAuth(), this is the request we should
1524 // be issuing -- the final header line contains the credentials.
1525 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1526 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451527 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321528 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1529 };
1530
1531 // The proxy responds to the connect with a 407, using a persistent
1532 // connection.
1533 MockRead data_reads1[] = {
1534 // No credentials.
1535 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1536 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1537 MockRead("Content-Length: 10\r\n\r\n"),
1538 MockRead("0123456789"),
1539
1540 // Wrong credentials (wrong password).
1541 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1542 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1543 MockRead("Content-Length: 10\r\n\r\n"),
1544 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421545 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321546 };
1547
[email protected]31a2bfe2010-02-09 08:03:391548 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1549 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591550 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321551
1552 TestCompletionCallback callback1;
1553
[email protected]dbb83db2010-05-11 18:13:391554 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421555 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321556
1557 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421558 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391559 size_t pos = ExpectLogContainsSomewhere(
1560 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1561 NetLog::PHASE_NONE);
1562 ExpectLogContainsSomewhere(
1563 log.entries(), pos,
1564 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1565 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321566
[email protected]1c773ea12009-04-28 19:58:421567 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321568 EXPECT_FALSE(response == NULL);
1569
1570 EXPECT_TRUE(response->headers->IsKeepAlive());
1571 EXPECT_EQ(407, response->headers->response_code());
1572 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421573 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321574
1575 // The password prompt info should have been set in response->auth_challenge.
1576 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1577
[email protected]71e4573a2009-05-21 22:03:001578 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321579 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1580 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1581
1582 TestCompletionCallback callback2;
1583
1584 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441585 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421586 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321587
1588 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421589 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321590
1591 response = trans->GetResponseInfo();
1592 EXPECT_FALSE(response == NULL);
1593
1594 EXPECT_TRUE(response->headers->IsKeepAlive());
1595 EXPECT_EQ(407, response->headers->response_code());
1596 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421597 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321598
1599 // The password prompt info should have been set in response->auth_challenge.
1600 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1601
[email protected]71e4573a2009-05-21 22:03:001602 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321603 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1604 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131605
[email protected]e60e47a2010-07-14 03:37:181606 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1607 // out of scope.
1608 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321609}
1610
[email protected]a8e9b162009-03-12 00:06:441611// Test that we don't read the response body when we fail to establish a tunnel,
1612// even if the user cancels the proxy's auth attempt.
1613TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1614 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001615 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441616
[email protected]e44de5d2009-06-05 20:12:451617 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441618
[email protected]5695b8c2009-09-30 21:36:431619 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441620
[email protected]1c773ea12009-04-28 19:58:421621 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441622 request.method = "GET";
1623 request.url = GURL("https://www.google.com/");
1624 request.load_flags = 0;
1625
1626 // Since we have proxy, should try to establish tunnel.
1627 MockWrite data_writes[] = {
1628 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451629 "Host: www.google.com\r\n"
1630 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441631 };
1632
1633 // The proxy responds to the connect with a 407.
1634 MockRead data_reads[] = {
1635 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1636 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1637 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421638 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441639 };
1640
[email protected]31a2bfe2010-02-09 08:03:391641 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1642 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591643 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441644
1645 TestCompletionCallback callback;
1646
[email protected]5a1d7ca2010-04-28 20:12:271647 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421648 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441649
1650 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421651 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441652
[email protected]1c773ea12009-04-28 19:58:421653 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441654 EXPECT_FALSE(response == NULL);
1655
1656 EXPECT_TRUE(response->headers->IsKeepAlive());
1657 EXPECT_EQ(407, response->headers->response_code());
1658 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421659 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441660
1661 std::string response_data;
1662 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421663 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181664
1665 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1666 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441667}
1668
[email protected]8fdbcd22010-05-05 02:54:521669// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1670// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1671TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1672 // We are using a DIRECT connection (i.e. no proxy) for this session.
1673 SessionDependencies session_deps;
1674 scoped_ptr<HttpTransaction> trans(
1675 new HttpNetworkTransaction(CreateSession(&session_deps)));
1676
1677 HttpRequestInfo request;
1678 request.method = "GET";
1679 request.url = GURL("http://www.google.com/");
1680 request.load_flags = 0;
1681
1682 MockWrite data_writes1[] = {
1683 MockWrite("GET / HTTP/1.1\r\n"
1684 "Host: www.google.com\r\n"
1685 "Connection: keep-alive\r\n\r\n"),
1686 };
1687
1688 MockRead data_reads1[] = {
1689 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1690 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1691 // Large content-length -- won't matter, as connection will be reset.
1692 MockRead("Content-Length: 10000\r\n\r\n"),
1693 MockRead(false, ERR_FAILED),
1694 };
1695
1696 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1697 data_writes1, arraysize(data_writes1));
1698 session_deps.socket_factory.AddSocketDataProvider(&data1);
1699
1700 TestCompletionCallback callback;
1701
1702 int rv = trans->Start(&request, &callback, BoundNetLog());
1703 EXPECT_EQ(ERR_IO_PENDING, rv);
1704
1705 rv = callback.WaitForResult();
1706 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1707}
1708
[email protected]2df19bb2010-08-25 20:13:461709
1710// Test a simple get through an HTTPS Proxy.
1711TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1712 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001713 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461714 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1715 session_deps.net_log = log.bound().net_log();
1716 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1717
[email protected]2df19bb2010-08-25 20:13:461718 HttpRequestInfo request;
1719 request.method = "GET";
1720 request.url = GURL("http://www.google.com/");
1721
1722 // Since we have proxy, should use full url
1723 MockWrite data_writes1[] = {
1724 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1725 "Host: www.google.com\r\n"
1726 "Proxy-Connection: keep-alive\r\n\r\n"),
1727 };
1728
1729 MockRead data_reads1[] = {
1730 MockRead("HTTP/1.1 200 OK\r\n"),
1731 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1732 MockRead("Content-Length: 100\r\n\r\n"),
1733 MockRead(false, OK),
1734 };
1735
1736 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1737 data_writes1, arraysize(data_writes1));
1738 session_deps.socket_factory.AddSocketDataProvider(&data1);
1739 SSLSocketDataProvider ssl(true, OK);
1740 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1741
1742 TestCompletionCallback callback1;
1743
[email protected]0b0bf032010-09-21 18:08:501744 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1745
[email protected]2df19bb2010-08-25 20:13:461746 int rv = trans->Start(&request, &callback1, log.bound());
1747 EXPECT_EQ(ERR_IO_PENDING, rv);
1748
1749 rv = callback1.WaitForResult();
1750 EXPECT_EQ(OK, rv);
1751
1752 const HttpResponseInfo* response = trans->GetResponseInfo();
1753 ASSERT_FALSE(response == NULL);
1754
1755 EXPECT_TRUE(response->headers->IsKeepAlive());
1756 EXPECT_EQ(200, response->headers->response_code());
1757 EXPECT_EQ(100, response->headers->GetContentLength());
1758 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1759
1760 // The password prompt info should not be set.
1761 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1762}
1763
[email protected]7642b5ae2010-09-01 20:55:171764// Test a SPDY get through an HTTPS Proxy.
1765TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1766 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001767 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171768 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1769 session_deps.net_log = log.bound().net_log();
1770 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1771
[email protected]7642b5ae2010-09-01 20:55:171772 HttpRequestInfo request;
1773 request.method = "GET";
1774 request.url = GURL("http://www.google.com/");
1775 request.load_flags = 0;
1776
1777 // fetch http://www.google.com/ via SPDY
1778 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1779 false));
1780 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1781
1782 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1783 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1784 MockRead spdy_reads[] = {
1785 CreateMockRead(*resp),
1786 CreateMockRead(*data),
1787 MockRead(true, 0, 0),
1788 };
1789
1790 scoped_refptr<DelayedSocketData> spdy_data(
1791 new DelayedSocketData(
1792 1, // wait for one write to finish before reading.
1793 spdy_reads, arraysize(spdy_reads),
1794 spdy_writes, arraysize(spdy_writes)));
1795 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1796
1797 SSLSocketDataProvider ssl(true, OK);
1798 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1799 ssl.next_proto = "spdy/2";
1800 ssl.was_npn_negotiated = true;
1801 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1802
1803 TestCompletionCallback callback1;
1804
[email protected]0b0bf032010-09-21 18:08:501805 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1806
[email protected]7642b5ae2010-09-01 20:55:171807 int rv = trans->Start(&request, &callback1, log.bound());
1808 EXPECT_EQ(ERR_IO_PENDING, rv);
1809
1810 rv = callback1.WaitForResult();
1811 EXPECT_EQ(OK, rv);
1812
1813 const HttpResponseInfo* response = trans->GetResponseInfo();
1814 ASSERT_TRUE(response != NULL);
1815 ASSERT_TRUE(response->headers != NULL);
1816 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1817
1818 std::string response_data;
1819 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1820 EXPECT_EQ(net::kUploadData, response_data);
1821}
1822
[email protected]d9da5fe2010-10-13 22:37:161823// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
1824TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
1825 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001826 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:161827 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1828 session_deps.net_log = log.bound().net_log();
1829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1830
1831 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1832
1833 HttpRequestInfo request;
1834 request.method = "GET";
1835 request.url = GURL("https://www.google.com/");
1836 request.load_flags = 0;
1837
1838 // CONNECT to www.google.com:443 via SPDY
1839 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
1840 // fetch https://www.google.com/ via HTTP
1841
1842 const char get[] = "GET / HTTP/1.1\r\n"
1843 "Host: www.google.com\r\n"
1844 "Connection: keep-alive\r\n\r\n";
1845 scoped_ptr<spdy::SpdyFrame> wrapped_get(
1846 ConstructSpdyBodyFrame(1, get, strlen(get), false));
1847 MockWrite spdy_writes[] = {
1848 CreateMockWrite(*connect, 1),
1849 CreateMockWrite(*wrapped_get, 3)
1850 };
1851
1852 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1853 const char resp[] = "HTTP/1.1 200 OK\r\n"
1854 "Content-Length: 10\r\n\r\n";
1855
1856 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
1857 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
1858 scoped_ptr<spdy::SpdyFrame> wrapped_body(
1859 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
1860 MockRead spdy_reads[] = {
1861 CreateMockRead(*conn_resp, 2, true),
1862 CreateMockRead(*wrapped_get_resp, 4, true),
1863 CreateMockRead(*wrapped_body, 5, true),
1864 CreateMockRead(*wrapped_body, 6, true),
1865 MockRead(true, 0, 7),
1866 };
1867
1868 scoped_refptr<OrderedSocketData> spdy_data(
1869 new OrderedSocketData(
1870 spdy_reads, arraysize(spdy_reads),
1871 spdy_writes, arraysize(spdy_writes)));
1872 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1873
1874 SSLSocketDataProvider ssl(true, OK);
1875 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1876 ssl.next_proto = "spdy/2";
1877 ssl.was_npn_negotiated = true;
1878 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1879 SSLSocketDataProvider ssl2(true, OK);
1880 ssl2.was_npn_negotiated = false;
1881 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
1882
1883 TestCompletionCallback callback1;
1884
1885 int rv = trans->Start(&request, &callback1, log.bound());
1886 EXPECT_EQ(ERR_IO_PENDING, rv);
1887
1888 rv = callback1.WaitForResult();
1889 EXPECT_EQ(OK, rv);
1890
1891 const HttpResponseInfo* response = trans->GetResponseInfo();
1892 ASSERT_TRUE(response != NULL);
1893 ASSERT_TRUE(response->headers != NULL);
1894 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1895
1896 std::string response_data;
1897 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1898 EXPECT_EQ("1234567890", response_data);
1899}
1900
1901// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
1902TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
1903 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001904 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:161905 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1906 session_deps.net_log = log.bound().net_log();
1907 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1908
1909 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1910
1911 HttpRequestInfo request;
1912 request.method = "GET";
1913 request.url = GURL("https://www.google.com/");
1914 request.load_flags = 0;
1915
1916 // CONNECT to www.google.com:443 via SPDY
1917 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
1918 // fetch https://www.google.com/ via SPDY
1919 const char* const kMyUrl = "https://www.google.com/";
1920 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
1921 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
1922 MockWrite spdy_writes[] = {
1923 CreateMockWrite(*connect, 1),
1924 CreateMockWrite(*wrapped_get, 3)
1925 };
1926
1927 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1928 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1929 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
1930 ConstructWrappedSpdyFrame(get_resp, 1));
1931 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1932 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
1933 MockRead spdy_reads[] = {
1934 CreateMockRead(*conn_resp, 2, true),
1935 CreateMockRead(*wrapped_get_resp, 4, true),
1936 CreateMockRead(*wrapped_body, 5, true),
1937 MockRead(true, 0, 1),
1938 };
1939
1940 scoped_refptr<OrderedSocketData> spdy_data(
1941 new OrderedSocketData(
1942 spdy_reads, arraysize(spdy_reads),
1943 spdy_writes, arraysize(spdy_writes)));
1944 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1945
1946 SSLSocketDataProvider ssl(true, OK);
1947 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1948 ssl.next_proto = "spdy/2";
1949 ssl.was_npn_negotiated = true;
1950 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1951 SSLSocketDataProvider ssl2(true, OK);
1952 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1953 ssl2.next_proto = "spdy/2";
1954 ssl2.was_npn_negotiated = true;
1955 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
1956
1957 TestCompletionCallback callback1;
1958
1959 int rv = trans->Start(&request, &callback1, log.bound());
1960 EXPECT_EQ(ERR_IO_PENDING, rv);
1961
1962 rv = callback1.WaitForResult();
1963 EXPECT_EQ(OK, rv);
1964
1965 const HttpResponseInfo* response = trans->GetResponseInfo();
1966 ASSERT_TRUE(response != NULL);
1967 ASSERT_TRUE(response->headers != NULL);
1968 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1969
1970 std::string response_data;
1971 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1972 EXPECT_EQ(net::kUploadData, response_data);
1973}
1974
1975// Test a SPDY CONNECT failure through an HTTPS Proxy.
1976TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
1977 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001978 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:161979 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1980 session_deps.net_log = log.bound().net_log();
1981 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1982
1983 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1984
1985 HttpRequestInfo request;
1986 request.method = "GET";
1987 request.url = GURL("https://www.google.com/");
1988 request.load_flags = 0;
1989
1990 // CONNECT to www.google.com:443 via SPDY
1991 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
1992 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
1993
1994 MockWrite spdy_writes[] = {
1995 CreateMockWrite(*connect, 1),
1996 CreateMockWrite(*get, 3),
1997 };
1998
1999 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2000 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2001 MockRead spdy_reads[] = {
2002 CreateMockRead(*resp, 2, true),
2003 MockRead(true, 0, 4),
2004 };
2005
2006 scoped_refptr<OrderedSocketData> spdy_data(
2007 new OrderedSocketData(
2008 spdy_reads, arraysize(spdy_reads),
2009 spdy_writes, arraysize(spdy_writes)));
2010 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2011
2012 SSLSocketDataProvider ssl(true, OK);
2013 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2014 ssl.next_proto = "spdy/2";
2015 ssl.was_npn_negotiated = true;
2016 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2017 SSLSocketDataProvider ssl2(true, OK);
2018 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2019 ssl2.next_proto = "spdy/2";
2020 ssl2.was_npn_negotiated = true;
2021 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2022
2023 TestCompletionCallback callback1;
2024
2025 int rv = trans->Start(&request, &callback1, log.bound());
2026 EXPECT_EQ(ERR_IO_PENDING, rv);
2027
2028 rv = callback1.WaitForResult();
2029 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2030
2031 const HttpResponseInfo* response = trans->GetResponseInfo();
2032 ASSERT_TRUE(response == NULL);
2033}
2034
[email protected]2df19bb2010-08-25 20:13:462035// Test the challenge-response-retry sequence through an HTTPS Proxy
2036TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
2037 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002038 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462039 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2040 session_deps.net_log = log.bound().net_log();
2041 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2042
[email protected]2df19bb2010-08-25 20:13:462043 HttpRequestInfo request;
2044 request.method = "GET";
2045 request.url = GURL("http://www.google.com/");
2046 // when the no authentication data flag is set.
2047 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2048
2049 // Since we have proxy, should use full url
2050 MockWrite data_writes1[] = {
2051 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2052 "Host: www.google.com\r\n"
2053 "Proxy-Connection: keep-alive\r\n\r\n"),
2054
2055 // After calling trans->RestartWithAuth(), this is the request we should
2056 // be issuing -- the final header line contains the credentials.
2057 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2058 "Host: www.google.com\r\n"
2059 "Proxy-Connection: keep-alive\r\n"
2060 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2061 };
2062
2063 // The proxy responds to the GET with a 407, using a persistent
2064 // connection.
2065 MockRead data_reads1[] = {
2066 // No credentials.
2067 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2068 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2069 MockRead("Proxy-Connection: keep-alive\r\n"),
2070 MockRead("Content-Length: 0\r\n\r\n"),
2071
2072 MockRead("HTTP/1.1 200 OK\r\n"),
2073 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2074 MockRead("Content-Length: 100\r\n\r\n"),
2075 MockRead(false, OK),
2076 };
2077
2078 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2079 data_writes1, arraysize(data_writes1));
2080 session_deps.socket_factory.AddSocketDataProvider(&data1);
2081 SSLSocketDataProvider ssl(true, OK);
2082 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2083
2084 TestCompletionCallback callback1;
2085
[email protected]0b0bf032010-09-21 18:08:502086 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2087
[email protected]2df19bb2010-08-25 20:13:462088 int rv = trans->Start(&request, &callback1, log.bound());
2089 EXPECT_EQ(ERR_IO_PENDING, rv);
2090
2091 rv = callback1.WaitForResult();
2092 EXPECT_EQ(OK, rv);
2093
2094 const HttpResponseInfo* response = trans->GetResponseInfo();
2095 ASSERT_FALSE(response == NULL);
2096
2097 EXPECT_EQ(407, response->headers->response_code());
2098 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2099
2100 // The password prompt info should have been set in response->auth_challenge.
2101 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2102
2103 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2104 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2105 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2106
2107 TestCompletionCallback callback2;
2108
2109 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2110 EXPECT_EQ(ERR_IO_PENDING, rv);
2111
2112 rv = callback2.WaitForResult();
2113 EXPECT_EQ(OK, rv);
2114
2115 response = trans->GetResponseInfo();
2116 ASSERT_FALSE(response == NULL);
2117
2118 EXPECT_TRUE(response->headers->IsKeepAlive());
2119 EXPECT_EQ(200, response->headers->response_code());
2120 EXPECT_EQ(100, response->headers->GetContentLength());
2121 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2122
2123 // The password prompt info should not be set.
2124 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2125}
2126
[email protected]ff007e162009-05-23 09:13:152127void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082128 const MockRead& status, int expected_status) {
2129 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002130 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:082131
[email protected]228ff742009-06-05 01:19:592132 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:082133
[email protected]1c773ea12009-04-28 19:58:422134 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082135 request.method = "GET";
2136 request.url = GURL("https://www.google.com/");
2137 request.load_flags = 0;
2138
2139 // Since we have proxy, should try to establish tunnel.
2140 MockWrite data_writes[] = {
2141 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452142 "Host: www.google.com\r\n"
2143 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082144 };
2145
2146 MockRead data_reads[] = {
2147 status,
2148 MockRead("Content-Length: 10\r\n\r\n"),
2149 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422150 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082151 };
2152
[email protected]31a2bfe2010-02-09 08:03:392153 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2154 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592155 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082156
2157 TestCompletionCallback callback;
2158
[email protected]0b0bf032010-09-21 18:08:502159 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2160
[email protected]5a1d7ca2010-04-28 20:12:272161 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422162 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082163
2164 rv = callback.WaitForResult();
2165 EXPECT_EQ(expected_status, rv);
2166}
2167
[email protected]ff007e162009-05-23 09:13:152168void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082169 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422170 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082171}
2172
2173TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2174 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2175}
2176
2177TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2178 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2179}
2180
2181TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2182 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2183}
2184
2185TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2186 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2187}
2188
2189TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2190 ConnectStatusHelper(
2191 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2192}
2193
2194TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2195 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2196}
2197
2198TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2199 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2200}
2201
2202TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2203 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2204}
2205
2206TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2207 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2208}
2209
2210TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2211 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2212}
2213
2214TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2215 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2216}
2217
2218TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2219 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2220}
2221
2222TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2223 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2224}
2225
2226TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2227 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2228}
2229
2230TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2231 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2232}
2233
2234TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2235 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2236}
2237
2238TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2239 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2240}
2241
2242TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2243 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2244}
2245
2246TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2247 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2248}
2249
2250TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2251 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2252}
2253
2254TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2255 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2256}
2257
2258TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2259 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2260}
2261
2262TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2263 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2264}
2265
2266TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2267 ConnectStatusHelperWithExpectedStatus(
2268 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542269 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082270}
2271
2272TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2273 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2274}
2275
2276TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2277 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2278}
2279
2280TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2281 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2282}
2283
2284TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2285 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2286}
2287
2288TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2289 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2290}
2291
2292TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2293 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2294}
2295
2296TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2297 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2298}
2299
2300TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2301 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2302}
2303
2304TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2305 ConnectStatusHelper(
2306 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2307}
2308
2309TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2310 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2311}
2312
2313TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2314 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2315}
2316
2317TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2318 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2319}
2320
2321TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2322 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2323}
2324
2325TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2326 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2327}
2328
2329TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2330 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2331}
2332
2333TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2334 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2335}
2336
[email protected]038e9a32008-10-08 22:40:162337// Test the flow when both the proxy server AND origin server require
2338// authentication. Again, this uses basic auth for both since that is
2339// the simplest to mock.
2340TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]81cdfcd2010-10-16 00:49:002341 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012342
[email protected]038e9a32008-10-08 22:40:162343 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422344 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432345 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162346
[email protected]1c773ea12009-04-28 19:58:422347 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162348 request.method = "GET";
2349 request.url = GURL("http://www.google.com/");
2350 request.load_flags = 0;
2351
[email protected]f9ee6b52008-11-08 06:46:232352 MockWrite data_writes1[] = {
2353 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2354 "Host: www.google.com\r\n"
2355 "Proxy-Connection: keep-alive\r\n\r\n"),
2356 };
2357
[email protected]038e9a32008-10-08 22:40:162358 MockRead data_reads1[] = {
2359 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2360 // Give a couple authenticate options (only the middle one is actually
2361 // supported).
[email protected]22927ad2009-09-21 19:56:192362 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162363 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2364 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2365 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2366 // Large content-length -- won't matter, as connection will be reset.
2367 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422368 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162369 };
2370
2371 // After calling trans->RestartWithAuth() the first time, this is the
2372 // request we should be issuing -- the final header line contains the
2373 // proxy's credentials.
2374 MockWrite data_writes2[] = {
2375 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2376 "Host: www.google.com\r\n"
2377 "Proxy-Connection: keep-alive\r\n"
2378 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2379 };
2380
2381 // Now the proxy server lets the request pass through to origin server.
2382 // The origin server responds with a 401.
2383 MockRead data_reads2[] = {
2384 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2385 // Note: We are using the same realm-name as the proxy server. This is
2386 // completely valid, as realms are unique across hosts.
2387 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2389 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422390 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162391 };
2392
2393 // After calling trans->RestartWithAuth() the second time, we should send
2394 // the credentials for both the proxy and origin server.
2395 MockWrite data_writes3[] = {
2396 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2397 "Host: www.google.com\r\n"
2398 "Proxy-Connection: keep-alive\r\n"
2399 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2400 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2401 };
2402
2403 // Lastly we get the desired content.
2404 MockRead data_reads3[] = {
2405 MockRead("HTTP/1.0 200 OK\r\n"),
2406 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2407 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422408 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162409 };
2410
[email protected]31a2bfe2010-02-09 08:03:392411 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2412 data_writes1, arraysize(data_writes1));
2413 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2414 data_writes2, arraysize(data_writes2));
2415 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2416 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592417 session_deps.socket_factory.AddSocketDataProvider(&data1);
2418 session_deps.socket_factory.AddSocketDataProvider(&data2);
2419 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162420
2421 TestCompletionCallback callback1;
2422
[email protected]5a1d7ca2010-04-28 20:12:272423 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422424 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162425
2426 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422427 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162428
[email protected]1c773ea12009-04-28 19:58:422429 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162430 EXPECT_FALSE(response == NULL);
2431
2432 // The password prompt info should have been set in response->auth_challenge.
2433 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2434
[email protected]71e4573a2009-05-21 22:03:002435 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162436 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2437 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2438
2439 TestCompletionCallback callback2;
2440
[email protected]13c8a092010-07-29 06:15:442441 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422442 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162443
2444 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422445 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162446
2447 response = trans->GetResponseInfo();
2448 EXPECT_FALSE(response == NULL);
2449 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2450
[email protected]71e4573a2009-05-21 22:03:002451 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162452 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2453 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2454
2455 TestCompletionCallback callback3;
2456
[email protected]13c8a092010-07-29 06:15:442457 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422458 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162459
2460 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422461 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162462
2463 response = trans->GetResponseInfo();
2464 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2465 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162466}
[email protected]4ddaf2502008-10-23 18:26:192467
[email protected]ea9dc9a2009-09-05 00:43:322468// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2469// can't hook into its internals to cause it to generate predictable NTLM
2470// authorization headers.
2471#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292472// The NTLM authentication unit tests were generated by capturing the HTTP
2473// requests and responses using Fiddler 2 and inspecting the generated random
2474// bytes in the debugger.
2475
2476// Enter the correct password and authenticate successfully.
2477TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422478 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112479 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592480 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502481 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242482
[email protected]1c773ea12009-04-28 19:58:422483 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242484 request.method = "GET";
2485 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2486 request.load_flags = 0;
2487
2488 MockWrite data_writes1[] = {
2489 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2490 "Host: 172.22.68.17\r\n"
2491 "Connection: keep-alive\r\n\r\n"),
2492 };
2493
2494 MockRead data_reads1[] = {
2495 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042496 // Negotiate and NTLM are often requested together. However, we only want
2497 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2498 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242499 MockRead("WWW-Authenticate: NTLM\r\n"),
2500 MockRead("Connection: close\r\n"),
2501 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362502 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242503 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422504 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242505 };
2506
2507 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222508 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242509 // request we should be issuing -- the final header line contains a Type
2510 // 1 message.
2511 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2512 "Host: 172.22.68.17\r\n"
2513 "Connection: keep-alive\r\n"
2514 "Authorization: NTLM "
2515 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2516
2517 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2518 // (the credentials for the origin server). The second request continues
2519 // on the same connection.
2520 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2521 "Host: 172.22.68.17\r\n"
2522 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292523 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2524 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2525 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2526 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2527 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242528 };
2529
2530 MockRead data_reads2[] = {
2531 // The origin server responds with a Type 2 message.
2532 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2533 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292534 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242535 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2536 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2537 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2538 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2539 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2540 "BtAAAAAAA=\r\n"),
2541 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362542 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242543 MockRead("You are not authorized to view this page\r\n"),
2544
2545 // Lastly we get the desired content.
2546 MockRead("HTTP/1.1 200 OK\r\n"),
2547 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2548 MockRead("Content-Length: 13\r\n\r\n"),
2549 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422550 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242551 };
2552
[email protected]31a2bfe2010-02-09 08:03:392553 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2554 data_writes1, arraysize(data_writes1));
2555 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2556 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592557 session_deps.socket_factory.AddSocketDataProvider(&data1);
2558 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242559
2560 TestCompletionCallback callback1;
2561
[email protected]0b0bf032010-09-21 18:08:502562 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2563
[email protected]5a1d7ca2010-04-28 20:12:272564 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422565 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242566
2567 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422568 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242569
[email protected]0757e7702009-03-27 04:00:222570 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2571 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442572 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422573 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222574 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422575 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222576 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2577
[email protected]1c773ea12009-04-28 19:58:422578 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042579 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242580
[email protected]aef04272010-06-28 18:03:042581 // The password prompt info should have been set in
2582 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242583 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2584
[email protected]71e4573a2009-05-21 22:03:002585 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242586 EXPECT_EQ(L"", response->auth_challenge->realm);
2587 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2588
[email protected]0757e7702009-03-27 04:00:222589 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242590
[email protected]13c8a092010-07-29 06:15:442591 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422592 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242593
[email protected]0757e7702009-03-27 04:00:222594 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422595 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242596
2597 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042598 ASSERT_FALSE(response == NULL);
2599
[email protected]3f918782009-02-28 01:29:242600 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2601 EXPECT_EQ(13, response->headers->GetContentLength());
2602}
2603
[email protected]385a4672009-03-11 22:21:292604// Enter a wrong password, and then the correct one.
2605TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422606 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112607 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592608 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502609 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292610
[email protected]1c773ea12009-04-28 19:58:422611 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292612 request.method = "GET";
2613 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2614 request.load_flags = 0;
2615
2616 MockWrite data_writes1[] = {
2617 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2618 "Host: 172.22.68.17\r\n"
2619 "Connection: keep-alive\r\n\r\n"),
2620 };
2621
2622 MockRead data_reads1[] = {
2623 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042624 // Negotiate and NTLM are often requested together. However, we only want
2625 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2626 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292627 MockRead("WWW-Authenticate: NTLM\r\n"),
2628 MockRead("Connection: close\r\n"),
2629 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362630 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292631 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422632 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292633 };
2634
2635 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222636 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292637 // request we should be issuing -- the final header line contains a Type
2638 // 1 message.
2639 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2640 "Host: 172.22.68.17\r\n"
2641 "Connection: keep-alive\r\n"
2642 "Authorization: NTLM "
2643 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2644
2645 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2646 // (the credentials for the origin server). The second request continues
2647 // on the same connection.
2648 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2649 "Host: 172.22.68.17\r\n"
2650 "Connection: keep-alive\r\n"
2651 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2652 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2653 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2654 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2655 "4Ww7b7E=\r\n\r\n"),
2656 };
2657
2658 MockRead data_reads2[] = {
2659 // The origin server responds with a Type 2 message.
2660 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2661 MockRead("WWW-Authenticate: NTLM "
2662 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2663 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2664 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2665 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2666 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2667 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2668 "BtAAAAAAA=\r\n"),
2669 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362670 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292671 MockRead("You are not authorized to view this page\r\n"),
2672
2673 // Wrong password.
2674 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292675 MockRead("WWW-Authenticate: NTLM\r\n"),
2676 MockRead("Connection: close\r\n"),
2677 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362678 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292679 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422680 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292681 };
2682
2683 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222684 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292685 // request we should be issuing -- the final header line contains a Type
2686 // 1 message.
2687 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2688 "Host: 172.22.68.17\r\n"
2689 "Connection: keep-alive\r\n"
2690 "Authorization: NTLM "
2691 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2692
2693 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2694 // (the credentials for the origin server). The second request continues
2695 // on the same connection.
2696 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2697 "Host: 172.22.68.17\r\n"
2698 "Connection: keep-alive\r\n"
2699 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2700 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2701 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2702 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2703 "+4MUm7c=\r\n\r\n"),
2704 };
2705
2706 MockRead data_reads3[] = {
2707 // The origin server responds with a Type 2 message.
2708 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2709 MockRead("WWW-Authenticate: NTLM "
2710 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2711 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2712 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2713 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2714 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2715 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2716 "BtAAAAAAA=\r\n"),
2717 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362718 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292719 MockRead("You are not authorized to view this page\r\n"),
2720
2721 // Lastly we get the desired content.
2722 MockRead("HTTP/1.1 200 OK\r\n"),
2723 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2724 MockRead("Content-Length: 13\r\n\r\n"),
2725 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422726 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292727 };
2728
[email protected]31a2bfe2010-02-09 08:03:392729 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2730 data_writes1, arraysize(data_writes1));
2731 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2732 data_writes2, arraysize(data_writes2));
2733 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2734 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592735 session_deps.socket_factory.AddSocketDataProvider(&data1);
2736 session_deps.socket_factory.AddSocketDataProvider(&data2);
2737 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292738
2739 TestCompletionCallback callback1;
2740
[email protected]0b0bf032010-09-21 18:08:502741 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2742
[email protected]5a1d7ca2010-04-28 20:12:272743 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292745
2746 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422747 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292748
[email protected]0757e7702009-03-27 04:00:222749 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292750 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442751 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422752 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292753 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422754 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222755 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292756
[email protected]1c773ea12009-04-28 19:58:422757 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292758 EXPECT_FALSE(response == NULL);
2759
2760 // The password prompt info should have been set in response->auth_challenge.
2761 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2762
[email protected]71e4573a2009-05-21 22:03:002763 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292764 EXPECT_EQ(L"", response->auth_challenge->realm);
2765 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2766
2767 TestCompletionCallback callback3;
2768
[email protected]0757e7702009-03-27 04:00:222769 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442770 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422771 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292772
2773 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422774 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292775
[email protected]0757e7702009-03-27 04:00:222776 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2777 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442778 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422779 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222780 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422781 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222782 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2783
2784 response = trans->GetResponseInfo();
2785 EXPECT_FALSE(response == NULL);
2786
2787 // The password prompt info should have been set in response->auth_challenge.
2788 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2789
[email protected]71e4573a2009-05-21 22:03:002790 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222791 EXPECT_EQ(L"", response->auth_challenge->realm);
2792 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2793
2794 TestCompletionCallback callback5;
2795
2796 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442797 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422798 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222799
2800 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422801 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222802
[email protected]385a4672009-03-11 22:21:292803 response = trans->GetResponseInfo();
2804 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2805 EXPECT_EQ(13, response->headers->GetContentLength());
2806}
[email protected]ea9dc9a2009-09-05 00:43:322807#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292808
[email protected]4ddaf2502008-10-23 18:26:192809// Test reading a server response which has only headers, and no body.
2810// After some maximum number of bytes is consumed, the transaction should
2811// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2812TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592813 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402814 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432815 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192816
[email protected]1c773ea12009-04-28 19:58:422817 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192818 request.method = "GET";
2819 request.url = GURL("http://www.google.com/");
2820 request.load_flags = 0;
2821
[email protected]b75b7b2f2009-10-06 00:54:532822 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432823 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532824 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192825
2826 MockRead data_reads[] = {
2827 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432828 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192829 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422830 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192831 };
[email protected]31a2bfe2010-02-09 08:03:392832 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592833 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192834
2835 TestCompletionCallback callback;
2836
[email protected]5a1d7ca2010-04-28 20:12:272837 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422838 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192839
2840 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422841 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192842
[email protected]1c773ea12009-04-28 19:58:422843 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192844 EXPECT_TRUE(response == NULL);
2845}
[email protected]f4e426b2008-11-05 00:24:492846
2847// Make sure that we don't try to reuse a TCPClientSocket when failing to
2848// establish tunnel.
2849// http://code.google.com/p/chromium/issues/detail?id=3772
2850TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2851 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002852 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012853
[email protected]228ff742009-06-05 01:19:592854 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492855
[email protected]5695b8c2009-09-30 21:36:432856 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492857
[email protected]1c773ea12009-04-28 19:58:422858 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492859 request.method = "GET";
2860 request.url = GURL("https://www.google.com/");
2861 request.load_flags = 0;
2862
2863 // Since we have proxy, should try to establish tunnel.
2864 MockWrite data_writes1[] = {
2865 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452866 "Host: www.google.com\r\n"
2867 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492868 };
2869
[email protected]77848d12008-11-14 00:00:222870 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492871 // connection. Usually a proxy would return 501 (not implemented),
2872 // or 200 (tunnel established).
2873 MockRead data_reads1[] = {
2874 MockRead("HTTP/1.1 404 Not Found\r\n"),
2875 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422876 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492877 };
2878
[email protected]31a2bfe2010-02-09 08:03:392879 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2880 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592881 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492882
2883 TestCompletionCallback callback1;
2884
[email protected]5a1d7ca2010-04-28 20:12:272885 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422886 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492887
2888 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422889 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492890
[email protected]1c773ea12009-04-28 19:58:422891 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082892 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492893
[email protected]b4404c02009-04-10 16:38:522894 // Empty the current queue. This is necessary because idle sockets are
2895 // added to the connection pool asynchronously with a PostTask.
2896 MessageLoop::current()->RunAllPending();
2897
[email protected]f4e426b2008-11-05 00:24:492898 // We now check to make sure the TCPClientSocket was not added back to
2899 // the pool.
[email protected]a937a06d2009-08-19 21:19:242900 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492901 trans.reset();
[email protected]b4404c02009-04-10 16:38:522902 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492903 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242904 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492905}
[email protected]372d34a2008-11-05 21:30:512906
[email protected]1b157c02009-04-21 01:55:402907// Make sure that we recycle a socket after reading all of the response body.
2908TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592909 SessionDependencies session_deps;
2910 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402911
[email protected]5695b8c2009-09-30 21:36:432912 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402913
[email protected]1c773ea12009-04-28 19:58:422914 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402915 request.method = "GET";
2916 request.url = GURL("http://www.google.com/");
2917 request.load_flags = 0;
2918
2919 MockRead data_reads[] = {
2920 // A part of the response body is received with the response headers.
2921 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2922 // The rest of the response body is received in two parts.
2923 MockRead("lo"),
2924 MockRead(" world"),
2925 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422926 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402927 };
2928
[email protected]31a2bfe2010-02-09 08:03:392929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592930 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402931
2932 TestCompletionCallback callback;
2933
[email protected]5a1d7ca2010-04-28 20:12:272934 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422935 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402936
2937 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422938 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402939
[email protected]1c773ea12009-04-28 19:58:422940 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402941 EXPECT_TRUE(response != NULL);
2942
2943 EXPECT_TRUE(response->headers != NULL);
2944 std::string status_line = response->headers->GetStatusLine();
2945 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2946
[email protected]a937a06d2009-08-19 21:19:242947 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402948
2949 std::string response_data;
2950 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422951 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402952 EXPECT_EQ("hello world", response_data);
2953
2954 // Empty the current queue. This is necessary because idle sockets are
2955 // added to the connection pool asynchronously with a PostTask.
2956 MessageLoop::current()->RunAllPending();
2957
2958 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242959 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402960}
2961
[email protected]76a505b2010-08-25 06:23:002962// Make sure that we recycle a SSL socket after reading all of the response
2963// body.
2964TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
2965 SessionDependencies session_deps;
2966 HttpRequestInfo request;
2967 request.method = "GET";
2968 request.url = GURL("https://www.google.com/");
2969 request.load_flags = 0;
2970
2971 MockWrite data_writes[] = {
2972 MockWrite("GET / HTTP/1.1\r\n"
2973 "Host: www.google.com\r\n"
2974 "Connection: keep-alive\r\n\r\n"),
2975 };
2976
2977 MockRead data_reads[] = {
2978 MockRead("HTTP/1.1 200 OK\r\n"),
2979 MockRead("Content-Length: 11\r\n\r\n"),
2980 MockRead("hello world"),
2981 MockRead(false, OK),
2982 };
2983
2984 SSLSocketDataProvider ssl(true, OK);
2985 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2986
2987 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2988 data_writes, arraysize(data_writes));
2989 session_deps.socket_factory.AddSocketDataProvider(&data);
2990
2991 TestCompletionCallback callback;
2992
2993 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2994 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2995
2996 int rv = trans->Start(&request, &callback, BoundNetLog());
2997
2998 EXPECT_EQ(ERR_IO_PENDING, rv);
2999 EXPECT_EQ(OK, callback.WaitForResult());
3000
3001 const HttpResponseInfo* response = trans->GetResponseInfo();
3002 ASSERT_TRUE(response != NULL);
3003 ASSERT_TRUE(response->headers != NULL);
3004 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3005
3006 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3007
3008 std::string response_data;
3009 rv = ReadTransaction(trans.get(), &response_data);
3010 EXPECT_EQ(OK, rv);
3011 EXPECT_EQ("hello world", response_data);
3012
3013 // Empty the current queue. This is necessary because idle sockets are
3014 // added to the connection pool asynchronously with a PostTask.
3015 MessageLoop::current()->RunAllPending();
3016
3017 // We now check to make sure the socket was added back to the pool.
3018 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3019}
3020
3021// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3022// from the pool and make sure that we recover okay.
3023TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3024 SessionDependencies session_deps;
3025 HttpRequestInfo request;
3026 request.method = "GET";
3027 request.url = GURL("https://www.google.com/");
3028 request.load_flags = 0;
3029
3030 MockWrite data_writes[] = {
3031 MockWrite("GET / HTTP/1.1\r\n"
3032 "Host: www.google.com\r\n"
3033 "Connection: keep-alive\r\n\r\n"),
3034 MockWrite("GET / HTTP/1.1\r\n"
3035 "Host: www.google.com\r\n"
3036 "Connection: keep-alive\r\n\r\n"),
3037 };
3038
3039 MockRead data_reads[] = {
3040 MockRead("HTTP/1.1 200 OK\r\n"),
3041 MockRead("Content-Length: 11\r\n\r\n"),
3042 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3043 MockRead("hello world"),
3044 MockRead(true, 0, 0) // EOF
3045 };
3046
3047 SSLSocketDataProvider ssl(true, OK);
3048 SSLSocketDataProvider ssl2(true, OK);
3049 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3050 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3051
3052 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3053 data_writes, arraysize(data_writes));
3054 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3055 data_writes, arraysize(data_writes));
3056 session_deps.socket_factory.AddSocketDataProvider(&data);
3057 session_deps.socket_factory.AddSocketDataProvider(&data2);
3058
3059 TestCompletionCallback callback;
3060
3061 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3062 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3063
3064 int rv = trans->Start(&request, &callback, BoundNetLog());
3065
3066 EXPECT_EQ(ERR_IO_PENDING, rv);
3067 EXPECT_EQ(OK, callback.WaitForResult());
3068
3069 const HttpResponseInfo* response = trans->GetResponseInfo();
3070 ASSERT_TRUE(response != NULL);
3071 ASSERT_TRUE(response->headers != NULL);
3072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3073
3074 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3075
3076 std::string response_data;
3077 rv = ReadTransaction(trans.get(), &response_data);
3078 EXPECT_EQ(OK, rv);
3079 EXPECT_EQ("hello world", response_data);
3080
3081 // Empty the current queue. This is necessary because idle sockets are
3082 // added to the connection pool asynchronously with a PostTask.
3083 MessageLoop::current()->RunAllPending();
3084
3085 // We now check to make sure the socket was added back to the pool.
3086 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3087
3088 // Now start the second transaction, which should reuse the previous socket.
3089
3090 trans.reset(new HttpNetworkTransaction(session));
3091
3092 rv = trans->Start(&request, &callback, BoundNetLog());
3093
3094 EXPECT_EQ(ERR_IO_PENDING, rv);
3095 EXPECT_EQ(OK, callback.WaitForResult());
3096
3097 response = trans->GetResponseInfo();
3098 ASSERT_TRUE(response != NULL);
3099 ASSERT_TRUE(response->headers != NULL);
3100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3101
3102 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3103
3104 rv = ReadTransaction(trans.get(), &response_data);
3105 EXPECT_EQ(OK, rv);
3106 EXPECT_EQ("hello world", response_data);
3107
3108 // Empty the current queue. This is necessary because idle sockets are
3109 // added to the connection pool asynchronously with a PostTask.
3110 MessageLoop::current()->RunAllPending();
3111
3112 // We now check to make sure the socket was added back to the pool.
3113 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3114}
3115
[email protected]b4404c02009-04-10 16:38:523116// Make sure that we recycle a socket after a zero-length response.
3117// http://crbug.com/9880
3118TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:593119 SessionDependencies session_deps;
3120 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:523121
[email protected]5695b8c2009-09-30 21:36:433122 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:523123
[email protected]1c773ea12009-04-28 19:58:423124 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523125 request.method = "GET";
3126 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3127 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3128 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3129 "rt=prt.2642,ol.2649,xjs.2951");
3130 request.load_flags = 0;
3131
3132 MockRead data_reads[] = {
3133 MockRead("HTTP/1.1 204 No Content\r\n"
3134 "Content-Length: 0\r\n"
3135 "Content-Type: text/html\r\n\r\n"),
3136 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423137 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523138 };
3139
[email protected]31a2bfe2010-02-09 08:03:393140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593141 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523142
3143 TestCompletionCallback callback;
3144
[email protected]5a1d7ca2010-04-28 20:12:273145 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523147
3148 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423149 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523150
[email protected]1c773ea12009-04-28 19:58:423151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523152 EXPECT_TRUE(response != NULL);
3153
3154 EXPECT_TRUE(response->headers != NULL);
3155 std::string status_line = response->headers->GetStatusLine();
3156 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3157
[email protected]a937a06d2009-08-19 21:19:243158 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523159
3160 std::string response_data;
3161 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423162 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523163 EXPECT_EQ("", response_data);
3164
3165 // Empty the current queue. This is necessary because idle sockets are
3166 // added to the connection pool asynchronously with a PostTask.
3167 MessageLoop::current()->RunAllPending();
3168
3169 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243170 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523171}
3172
[email protected]372d34a2008-11-05 21:30:513173TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423174 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513175 // Transaction 1: a GET request that succeeds. The socket is recycled
3176 // after use.
3177 request[0].method = "GET";
3178 request[0].url = GURL("http://www.google.com/");
3179 request[0].load_flags = 0;
3180 // Transaction 2: a POST request. Reuses the socket kept alive from
3181 // transaction 1. The first attempts fails when writing the POST data.
3182 // This causes the transaction to retry with a new socket. The second
3183 // attempt succeeds.
3184 request[1].method = "POST";
3185 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423186 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513187 request[1].upload_data->AppendBytes("foo", 3);
3188 request[1].load_flags = 0;
3189
[email protected]228ff742009-06-05 01:19:593190 SessionDependencies session_deps;
3191 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:513192
3193 // The first socket is used for transaction 1 and the first attempt of
3194 // transaction 2.
3195
3196 // The response of transaction 1.
3197 MockRead data_reads1[] = {
3198 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3199 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423200 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513201 };
3202 // The mock write results of transaction 1 and the first attempt of
3203 // transaction 2.
3204 MockWrite data_writes1[] = {
3205 MockWrite(false, 64), // GET
3206 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423207 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513208 };
[email protected]31a2bfe2010-02-09 08:03:393209 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3210 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513211
3212 // The second socket is used for the second attempt of transaction 2.
3213
3214 // The response of transaction 2.
3215 MockRead data_reads2[] = {
3216 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3217 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423218 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513219 };
3220 // The mock write results of the second attempt of transaction 2.
3221 MockWrite data_writes2[] = {
3222 MockWrite(false, 93), // POST
3223 MockWrite(false, 3), // POST data
3224 };
[email protected]31a2bfe2010-02-09 08:03:393225 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3226 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513227
[email protected]5ecc992a42009-11-11 01:41:593228 session_deps.socket_factory.AddSocketDataProvider(&data1);
3229 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513230
3231 const char* kExpectedResponseData[] = {
3232 "hello world", "welcome"
3233 };
3234
3235 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423236 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433237 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513238
3239 TestCompletionCallback callback;
3240
[email protected]5a1d7ca2010-04-28 20:12:273241 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423242 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513243
3244 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423245 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513246
[email protected]1c773ea12009-04-28 19:58:423247 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513248 EXPECT_TRUE(response != NULL);
3249
3250 EXPECT_TRUE(response->headers != NULL);
3251 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3252
3253 std::string response_data;
3254 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423255 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513256 EXPECT_EQ(kExpectedResponseData[i], response_data);
3257 }
3258}
[email protected]f9ee6b52008-11-08 06:46:233259
3260// Test the request-challenge-retry sequence for basic auth when there is
3261// an identity in the URL. The request should be sent as normal, but when
3262// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323263TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593264 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403265 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433266 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233267
[email protected]1c773ea12009-04-28 19:58:423268 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233269 request.method = "GET";
3270 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293271 request.url = GURL("http://foo:b@[email protected]/");
3272
3273 // The password contains an escaped character -- for this test to pass it
3274 // will need to be unescaped by HttpNetworkTransaction.
3275 EXPECT_EQ("b%40r", request.url.password());
3276
[email protected]ea9dc9a2009-09-05 00:43:323277 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233278
3279 MockWrite data_writes1[] = {
3280 MockWrite("GET / HTTP/1.1\r\n"
3281 "Host: www.google.com\r\n"
3282 "Connection: keep-alive\r\n\r\n"),
3283 };
3284
3285 MockRead data_reads1[] = {
3286 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3287 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3288 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423289 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233290 };
3291
3292 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323293 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233294 MockWrite data_writes2[] = {
3295 MockWrite("GET / HTTP/1.1\r\n"
3296 "Host: www.google.com\r\n"
3297 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293298 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233299 };
3300
3301 MockRead data_reads2[] = {
3302 MockRead("HTTP/1.0 200 OK\r\n"),
3303 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423304 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233305 };
3306
[email protected]31a2bfe2010-02-09 08:03:393307 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3308 data_writes1, arraysize(data_writes1));
3309 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3310 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593311 session_deps.socket_factory.AddSocketDataProvider(&data1);
3312 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233313
3314 TestCompletionCallback callback1;
3315
[email protected]5a1d7ca2010-04-28 20:12:273316 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423317 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233318
3319 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423320 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233321
[email protected]0757e7702009-03-27 04:00:223322 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3323 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443324 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423325 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223326 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423327 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223328 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3329
[email protected]1c773ea12009-04-28 19:58:423330 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233331 EXPECT_FALSE(response == NULL);
3332
3333 // There is no challenge info, since the identity in URL worked.
3334 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3335
3336 EXPECT_EQ(100, response->headers->GetContentLength());
3337
3338 // Empty the current queue.
3339 MessageLoop::current()->RunAllPending();
3340}
3341
[email protected]ea9dc9a2009-09-05 00:43:323342// Test the request-challenge-retry sequence for basic auth when there is
3343// an incorrect identity in the URL. The identity from the URL should be used
3344// only once.
3345TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3346 SessionDependencies session_deps;
3347 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433348 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323349
3350 HttpRequestInfo request;
3351 request.method = "GET";
3352 // Note: the URL has a username:password in it. The password "baz" is
3353 // wrong (should be "bar").
3354 request.url = GURL("http://foo:[email protected]/");
3355
3356 request.load_flags = LOAD_NORMAL;
3357
3358 MockWrite data_writes1[] = {
3359 MockWrite("GET / HTTP/1.1\r\n"
3360 "Host: www.google.com\r\n"
3361 "Connection: keep-alive\r\n\r\n"),
3362 };
3363
3364 MockRead data_reads1[] = {
3365 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3366 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3367 MockRead("Content-Length: 10\r\n\r\n"),
3368 MockRead(false, ERR_FAILED),
3369 };
3370
3371 // After the challenge above, the transaction will be restarted using the
3372 // identity from the url (foo, baz) to answer the challenge.
3373 MockWrite data_writes2[] = {
3374 MockWrite("GET / HTTP/1.1\r\n"
3375 "Host: www.google.com\r\n"
3376 "Connection: keep-alive\r\n"
3377 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3378 };
3379
3380 MockRead data_reads2[] = {
3381 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3382 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3383 MockRead("Content-Length: 10\r\n\r\n"),
3384 MockRead(false, ERR_FAILED),
3385 };
3386
3387 // After the challenge above, the transaction will be restarted using the
3388 // identity supplied by the user (foo, bar) to answer the challenge.
3389 MockWrite data_writes3[] = {
3390 MockWrite("GET / HTTP/1.1\r\n"
3391 "Host: www.google.com\r\n"
3392 "Connection: keep-alive\r\n"
3393 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3394 };
3395
3396 MockRead data_reads3[] = {
3397 MockRead("HTTP/1.0 200 OK\r\n"),
3398 MockRead("Content-Length: 100\r\n\r\n"),
3399 MockRead(false, OK),
3400 };
3401
[email protected]31a2bfe2010-02-09 08:03:393402 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3403 data_writes1, arraysize(data_writes1));
3404 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3405 data_writes2, arraysize(data_writes2));
3406 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3407 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593408 session_deps.socket_factory.AddSocketDataProvider(&data1);
3409 session_deps.socket_factory.AddSocketDataProvider(&data2);
3410 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323411
3412 TestCompletionCallback callback1;
3413
[email protected]5a1d7ca2010-04-28 20:12:273414 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323415 EXPECT_EQ(ERR_IO_PENDING, rv);
3416
3417 rv = callback1.WaitForResult();
3418 EXPECT_EQ(OK, rv);
3419
3420 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3421 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443422 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323423 EXPECT_EQ(ERR_IO_PENDING, rv);
3424 rv = callback2.WaitForResult();
3425 EXPECT_EQ(OK, rv);
3426 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3427
3428 const HttpResponseInfo* response = trans->GetResponseInfo();
3429 EXPECT_FALSE(response == NULL);
3430 // The password prompt info should have been set in response->auth_challenge.
3431 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3432
3433 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3434 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3435 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3436
3437 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443438 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323439 EXPECT_EQ(ERR_IO_PENDING, rv);
3440 rv = callback3.WaitForResult();
3441 EXPECT_EQ(OK, rv);
3442 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3443
3444 response = trans->GetResponseInfo();
3445 EXPECT_FALSE(response == NULL);
3446
3447 // There is no challenge info, since the identity worked.
3448 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3449
3450 EXPECT_EQ(100, response->headers->GetContentLength());
3451
3452 // Empty the current queue.
3453 MessageLoop::current()->RunAllPending();
3454}
3455
[email protected]f9ee6b52008-11-08 06:46:233456// Test that previously tried username/passwords for a realm get re-used.
3457TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593458 SessionDependencies session_deps;
3459 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:233460
3461 // Transaction 1: authenticate (foo, bar) on MyRealm1
3462 {
[email protected]5695b8c2009-09-30 21:36:433463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233464
[email protected]1c773ea12009-04-28 19:58:423465 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233466 request.method = "GET";
3467 request.url = GURL("http://www.google.com/x/y/z");
3468 request.load_flags = 0;
3469
3470 MockWrite data_writes1[] = {
3471 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3472 "Host: www.google.com\r\n"
3473 "Connection: keep-alive\r\n\r\n"),
3474 };
3475
3476 MockRead data_reads1[] = {
3477 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3478 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3479 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423480 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233481 };
3482
3483 // Resend with authorization (username=foo, password=bar)
3484 MockWrite data_writes2[] = {
3485 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3486 "Host: www.google.com\r\n"
3487 "Connection: keep-alive\r\n"
3488 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3489 };
3490
3491 // Sever accepts the authorization.
3492 MockRead data_reads2[] = {
3493 MockRead("HTTP/1.0 200 OK\r\n"),
3494 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423495 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233496 };
3497
[email protected]31a2bfe2010-02-09 08:03:393498 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3499 data_writes1, arraysize(data_writes1));
3500 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3501 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593502 session_deps.socket_factory.AddSocketDataProvider(&data1);
3503 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233504
3505 TestCompletionCallback callback1;
3506
[email protected]5a1d7ca2010-04-28 20:12:273507 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423508 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233509
3510 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423511 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233512
[email protected]1c773ea12009-04-28 19:58:423513 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233514 EXPECT_FALSE(response == NULL);
3515
3516 // The password prompt info should have been set in
3517 // response->auth_challenge.
3518 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3519
[email protected]71e4573a2009-05-21 22:03:003520 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233521 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3522 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3523
3524 TestCompletionCallback callback2;
3525
[email protected]13c8a092010-07-29 06:15:443526 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423527 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233528
3529 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423530 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233531
3532 response = trans->GetResponseInfo();
3533 EXPECT_FALSE(response == NULL);
3534 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3535 EXPECT_EQ(100, response->headers->GetContentLength());
3536 }
3537
3538 // ------------------------------------------------------------------------
3539
3540 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3541 {
[email protected]5695b8c2009-09-30 21:36:433542 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233543
[email protected]1c773ea12009-04-28 19:58:423544 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233545 request.method = "GET";
3546 // Note that Transaction 1 was at /x/y/z, so this is in the same
3547 // protection space as MyRealm1.
3548 request.url = GURL("http://www.google.com/x/y/a/b");
3549 request.load_flags = 0;
3550
3551 MockWrite data_writes1[] = {
3552 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3553 "Host: www.google.com\r\n"
3554 "Connection: keep-alive\r\n"
3555 // Send preemptive authorization for MyRealm1
3556 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3557 };
3558
3559 // The server didn't like the preemptive authorization, and
3560 // challenges us for a different realm (MyRealm2).
3561 MockRead data_reads1[] = {
3562 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3563 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3564 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423565 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233566 };
3567
3568 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3569 MockWrite data_writes2[] = {
3570 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3571 "Host: www.google.com\r\n"
3572 "Connection: keep-alive\r\n"
3573 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3574 };
3575
3576 // Sever accepts the authorization.
3577 MockRead data_reads2[] = {
3578 MockRead("HTTP/1.0 200 OK\r\n"),
3579 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423580 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233581 };
3582
[email protected]31a2bfe2010-02-09 08:03:393583 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3584 data_writes1, arraysize(data_writes1));
3585 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3586 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593587 session_deps.socket_factory.AddSocketDataProvider(&data1);
3588 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233589
3590 TestCompletionCallback callback1;
3591
[email protected]5a1d7ca2010-04-28 20:12:273592 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423593 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233594
3595 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423596 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233597
[email protected]1c773ea12009-04-28 19:58:423598 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233599 EXPECT_FALSE(response == NULL);
3600
3601 // The password prompt info should have been set in
3602 // response->auth_challenge.
3603 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3604
[email protected]71e4573a2009-05-21 22:03:003605 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233606 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3607 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3608
3609 TestCompletionCallback callback2;
3610
[email protected]13c8a092010-07-29 06:15:443611 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423612 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233613
3614 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423615 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233616
3617 response = trans->GetResponseInfo();
3618 EXPECT_FALSE(response == NULL);
3619 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3620 EXPECT_EQ(100, response->headers->GetContentLength());
3621 }
3622
3623 // ------------------------------------------------------------------------
3624
3625 // Transaction 3: Resend a request in MyRealm's protection space --
3626 // succeed with preemptive authorization.
3627 {
[email protected]5695b8c2009-09-30 21:36:433628 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233629
[email protected]1c773ea12009-04-28 19:58:423630 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233631 request.method = "GET";
3632 request.url = GURL("http://www.google.com/x/y/z2");
3633 request.load_flags = 0;
3634
3635 MockWrite data_writes1[] = {
3636 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3637 "Host: www.google.com\r\n"
3638 "Connection: keep-alive\r\n"
3639 // The authorization for MyRealm1 gets sent preemptively
3640 // (since the url is in the same protection space)
3641 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3642 };
3643
3644 // Sever accepts the preemptive authorization
3645 MockRead data_reads1[] = {
3646 MockRead("HTTP/1.0 200 OK\r\n"),
3647 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423648 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233649 };
3650
[email protected]31a2bfe2010-02-09 08:03:393651 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3652 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593653 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233654
3655 TestCompletionCallback callback1;
3656
[email protected]5a1d7ca2010-04-28 20:12:273657 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233659
3660 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423661 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233662
[email protected]1c773ea12009-04-28 19:58:423663 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233664 EXPECT_FALSE(response == NULL);
3665
3666 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3667 EXPECT_EQ(100, response->headers->GetContentLength());
3668 }
3669
3670 // ------------------------------------------------------------------------
3671
3672 // Transaction 4: request another URL in MyRealm (however the
3673 // url is not known to belong to the protection space, so no pre-auth).
3674 {
[email protected]5695b8c2009-09-30 21:36:433675 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233676
[email protected]1c773ea12009-04-28 19:58:423677 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233678 request.method = "GET";
3679 request.url = GURL("http://www.google.com/x/1");
3680 request.load_flags = 0;
3681
3682 MockWrite data_writes1[] = {
3683 MockWrite("GET /x/1 HTTP/1.1\r\n"
3684 "Host: www.google.com\r\n"
3685 "Connection: keep-alive\r\n\r\n"),
3686 };
3687
3688 MockRead data_reads1[] = {
3689 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3690 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3691 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423692 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233693 };
3694
3695 // Resend with authorization from MyRealm's cache.
3696 MockWrite data_writes2[] = {
3697 MockWrite("GET /x/1 HTTP/1.1\r\n"
3698 "Host: www.google.com\r\n"
3699 "Connection: keep-alive\r\n"
3700 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3701 };
3702
3703 // Sever accepts the authorization.
3704 MockRead data_reads2[] = {
3705 MockRead("HTTP/1.0 200 OK\r\n"),
3706 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423707 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233708 };
3709
[email protected]31a2bfe2010-02-09 08:03:393710 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3711 data_writes1, arraysize(data_writes1));
3712 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3713 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593714 session_deps.socket_factory.AddSocketDataProvider(&data1);
3715 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233716
3717 TestCompletionCallback callback1;
3718
[email protected]5a1d7ca2010-04-28 20:12:273719 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423720 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233721
3722 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423723 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233724
[email protected]0757e7702009-03-27 04:00:223725 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3726 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443727 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423728 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223729 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423730 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223731 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3732
[email protected]1c773ea12009-04-28 19:58:423733 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233734 EXPECT_FALSE(response == NULL);
3735 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3736 EXPECT_EQ(100, response->headers->GetContentLength());
3737 }
3738
3739 // ------------------------------------------------------------------------
3740
3741 // Transaction 5: request a URL in MyRealm, but the server rejects the
3742 // cached identity. Should invalidate and re-prompt.
3743 {
[email protected]5695b8c2009-09-30 21:36:433744 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233745
[email protected]1c773ea12009-04-28 19:58:423746 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233747 request.method = "GET";
3748 request.url = GURL("http://www.google.com/p/q/t");
3749 request.load_flags = 0;
3750
3751 MockWrite data_writes1[] = {
3752 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3753 "Host: www.google.com\r\n"
3754 "Connection: keep-alive\r\n\r\n"),
3755 };
3756
3757 MockRead data_reads1[] = {
3758 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3759 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3760 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423761 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233762 };
3763
3764 // Resend with authorization from cache for MyRealm.
3765 MockWrite data_writes2[] = {
3766 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3767 "Host: www.google.com\r\n"
3768 "Connection: keep-alive\r\n"
3769 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3770 };
3771
3772 // Sever rejects the authorization.
3773 MockRead data_reads2[] = {
3774 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3775 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3776 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423777 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233778 };
3779
3780 // At this point we should prompt for new credentials for MyRealm.
3781 // Restart with username=foo3, password=foo4.
3782 MockWrite data_writes3[] = {
3783 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3787 };
3788
3789 // Sever accepts the authorization.
3790 MockRead data_reads3[] = {
3791 MockRead("HTTP/1.0 200 OK\r\n"),
3792 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423793 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233794 };
3795
[email protected]31a2bfe2010-02-09 08:03:393796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3797 data_writes1, arraysize(data_writes1));
3798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3799 data_writes2, arraysize(data_writes2));
3800 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3801 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593802 session_deps.socket_factory.AddSocketDataProvider(&data1);
3803 session_deps.socket_factory.AddSocketDataProvider(&data2);
3804 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233805
3806 TestCompletionCallback callback1;
3807
[email protected]5a1d7ca2010-04-28 20:12:273808 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423809 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233810
3811 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423812 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233813
[email protected]0757e7702009-03-27 04:00:223814 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3815 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443816 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423817 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223818 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423819 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223820 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3821
[email protected]1c773ea12009-04-28 19:58:423822 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233823 EXPECT_FALSE(response == NULL);
3824
3825 // The password prompt info should have been set in
3826 // response->auth_challenge.
3827 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3828
[email protected]71e4573a2009-05-21 22:03:003829 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233830 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3831 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3832
[email protected]0757e7702009-03-27 04:00:223833 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233834
[email protected]13c8a092010-07-29 06:15:443835 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423836 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233837
[email protected]0757e7702009-03-27 04:00:223838 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423839 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233840
3841 response = trans->GetResponseInfo();
3842 EXPECT_FALSE(response == NULL);
3843 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3844 EXPECT_EQ(100, response->headers->GetContentLength());
3845 }
3846}
[email protected]89ceba9a2009-03-21 03:46:063847
[email protected]3c32c5f2010-05-18 15:18:123848// Tests that nonce count increments when multiple auth attempts
3849// are started with the same nonce.
3850TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3851 SessionDependencies session_deps;
3852 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3853 HttpAuthHandlerDigest::SetFixedCnonce(true);
3854
3855 // Transaction 1: authenticate (foo, bar) on MyRealm1
3856 {
3857 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3858
3859 HttpRequestInfo request;
3860 request.method = "GET";
3861 request.url = GURL("http://www.google.com/x/y/z");
3862 request.load_flags = 0;
3863
3864 MockWrite data_writes1[] = {
3865 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3866 "Host: www.google.com\r\n"
3867 "Connection: keep-alive\r\n\r\n"),
3868 };
3869
3870 MockRead data_reads1[] = {
3871 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3872 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3873 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3874 MockRead(false, OK),
3875 };
3876
3877 // Resend with authorization (username=foo, password=bar)
3878 MockWrite data_writes2[] = {
3879 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3880 "Host: www.google.com\r\n"
3881 "Connection: keep-alive\r\n"
3882 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3883 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3884 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3885 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3886 };
3887
3888 // Sever accepts the authorization.
3889 MockRead data_reads2[] = {
3890 MockRead("HTTP/1.0 200 OK\r\n"),
3891 MockRead(false, OK),
3892 };
3893
3894 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3895 data_writes1, arraysize(data_writes1));
3896 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3897 data_writes2, arraysize(data_writes2));
3898 session_deps.socket_factory.AddSocketDataProvider(&data1);
3899 session_deps.socket_factory.AddSocketDataProvider(&data2);
3900
3901 TestCompletionCallback callback1;
3902
3903 int rv = trans->Start(&request, &callback1, BoundNetLog());
3904 EXPECT_EQ(ERR_IO_PENDING, rv);
3905
3906 rv = callback1.WaitForResult();
3907 EXPECT_EQ(OK, rv);
3908
3909 const HttpResponseInfo* response = trans->GetResponseInfo();
3910 ASSERT_FALSE(response == NULL);
3911
3912 // The password prompt info should have been set in
3913 // response->auth_challenge.
3914 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3915
3916 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3917 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3918 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3919
3920 TestCompletionCallback callback2;
3921
[email protected]13c8a092010-07-29 06:15:443922 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123923 EXPECT_EQ(ERR_IO_PENDING, rv);
3924
3925 rv = callback2.WaitForResult();
3926 EXPECT_EQ(OK, rv);
3927
3928 response = trans->GetResponseInfo();
3929 ASSERT_FALSE(response == NULL);
3930 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3931 }
3932
3933 // ------------------------------------------------------------------------
3934
3935 // Transaction 2: Request another resource in digestive's protection space.
3936 // This will preemptively add an Authorization header which should have an
3937 // "nc" value of 2 (as compared to 1 in the first use.
3938 {
3939 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3940
3941 HttpRequestInfo request;
3942 request.method = "GET";
3943 // Note that Transaction 1 was at /x/y/z, so this is in the same
3944 // protection space as digest.
3945 request.url = GURL("http://www.google.com/x/y/a/b");
3946 request.load_flags = 0;
3947
3948 MockWrite data_writes1[] = {
3949 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3950 "Host: www.google.com\r\n"
3951 "Connection: keep-alive\r\n"
3952 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3953 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3954 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3955 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3956 };
3957
3958 // Sever accepts the authorization.
3959 MockRead data_reads1[] = {
3960 MockRead("HTTP/1.0 200 OK\r\n"),
3961 MockRead("Content-Length: 100\r\n\r\n"),
3962 MockRead(false, OK),
3963 };
3964
3965 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3966 data_writes1, arraysize(data_writes1));
3967 session_deps.socket_factory.AddSocketDataProvider(&data1);
3968
3969 TestCompletionCallback callback1;
3970
3971 int rv = trans->Start(&request, &callback1, BoundNetLog());
3972 EXPECT_EQ(ERR_IO_PENDING, rv);
3973
3974 rv = callback1.WaitForResult();
3975 EXPECT_EQ(OK, rv);
3976
3977 const HttpResponseInfo* response = trans->GetResponseInfo();
3978 ASSERT_FALSE(response == NULL);
3979 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3980 }
3981}
3982
[email protected]89ceba9a2009-03-21 03:46:063983// Test the ResetStateForRestart() private method.
3984TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3985 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593986 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403987 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433988 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063989
3990 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063991 trans->read_buf_ = new IOBuffer(15);
3992 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573993 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063994
3995 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143996 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573997 response->auth_challenge = new AuthChallengeInfo();
3998 response->ssl_info.cert_status = -15;
3999 response->response_time = base::Time::Now();
4000 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064001
4002 { // Setup state for response_.vary_data
4003 HttpRequestInfo request;
4004 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4005 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:574006 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:434007 request.extra_headers.SetHeader("Foo", "1");
4008 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574009 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064010 }
4011
4012 // Cause the above state to be reset.
4013 trans->ResetStateForRestart();
4014
4015 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074016 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064017 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:574018 EXPECT_EQ(0U, trans->request_headers_.size());
4019 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4020 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044021 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574022 EXPECT_EQ(0, response->ssl_info.cert_status);
4023 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064024}
4025
[email protected]bacff652009-03-31 17:50:334026// Test HTTPS connections to a site with a bad certificate
4027TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:594028 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404029 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434030 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334031
4032 HttpRequestInfo request;
4033 request.method = "GET";
4034 request.url = GURL("https://www.google.com/");
4035 request.load_flags = 0;
4036
4037 MockWrite data_writes[] = {
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 data_reads[] = {
4044 MockRead("HTTP/1.0 200 OK\r\n"),
4045 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4046 MockRead("Content-Length: 100\r\n\r\n"),
4047 MockRead(false, OK),
4048 };
4049
[email protected]5ecc992a42009-11-11 01:41:594050 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394051 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4052 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594053 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4054 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334055
[email protected]5ecc992a42009-11-11 01:41:594056 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4057 session_deps.socket_factory.AddSocketDataProvider(&data);
4058 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4059 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334060
4061 TestCompletionCallback callback;
4062
[email protected]5a1d7ca2010-04-28 20:12:274063 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334064 EXPECT_EQ(ERR_IO_PENDING, rv);
4065
4066 rv = callback.WaitForResult();
4067 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4068
4069 rv = trans->RestartIgnoringLastError(&callback);
4070 EXPECT_EQ(ERR_IO_PENDING, rv);
4071
4072 rv = callback.WaitForResult();
4073 EXPECT_EQ(OK, rv);
4074
4075 const HttpResponseInfo* response = trans->GetResponseInfo();
4076
4077 EXPECT_FALSE(response == NULL);
4078 EXPECT_EQ(100, response->headers->GetContentLength());
4079}
4080
4081// Test HTTPS connections to a site with a bad certificate, going through a
4082// proxy
4083TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004084 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334085
4086 HttpRequestInfo request;
4087 request.method = "GET";
4088 request.url = GURL("https://www.google.com/");
4089 request.load_flags = 0;
4090
4091 MockWrite proxy_writes[] = {
4092 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454093 "Host: www.google.com\r\n"
4094 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334095 };
4096
4097 MockRead proxy_reads[] = {
4098 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424099 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334100 };
4101
4102 MockWrite data_writes[] = {
4103 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454104 "Host: www.google.com\r\n"
4105 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334106 MockWrite("GET / HTTP/1.1\r\n"
4107 "Host: www.google.com\r\n"
4108 "Connection: keep-alive\r\n\r\n"),
4109 };
4110
4111 MockRead data_reads[] = {
4112 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4113 MockRead("HTTP/1.0 200 OK\r\n"),
4114 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4115 MockRead("Content-Length: 100\r\n\r\n"),
4116 MockRead(false, OK),
4117 };
4118
[email protected]31a2bfe2010-02-09 08:03:394119 StaticSocketDataProvider ssl_bad_certificate(
4120 proxy_reads, arraysize(proxy_reads),
4121 proxy_writes, arraysize(proxy_writes));
4122 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4123 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594124 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4125 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334126
[email protected]5ecc992a42009-11-11 01:41:594127 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4128 session_deps.socket_factory.AddSocketDataProvider(&data);
4129 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4130 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334131
4132 TestCompletionCallback callback;
4133
4134 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594135 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334136
[email protected]d207a5f2009-06-04 05:28:404137 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434138 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334139
[email protected]5a1d7ca2010-04-28 20:12:274140 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334141 EXPECT_EQ(ERR_IO_PENDING, rv);
4142
4143 rv = callback.WaitForResult();
4144 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4145
4146 rv = trans->RestartIgnoringLastError(&callback);
4147 EXPECT_EQ(ERR_IO_PENDING, rv);
4148
4149 rv = callback.WaitForResult();
4150 EXPECT_EQ(OK, rv);
4151
4152 const HttpResponseInfo* response = trans->GetResponseInfo();
4153
4154 EXPECT_FALSE(response == NULL);
4155 EXPECT_EQ(100, response->headers->GetContentLength());
4156 }
4157}
4158
[email protected]2df19bb2010-08-25 20:13:464159
4160// Test HTTPS connections to a site, going through an HTTPS proxy
4161TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004162 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464163
4164 HttpRequestInfo request;
4165 request.method = "GET";
4166 request.url = GURL("https://www.google.com/");
4167 request.load_flags = 0;
4168
4169 MockWrite data_writes[] = {
4170 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4171 "Host: www.google.com\r\n"
4172 "Proxy-Connection: keep-alive\r\n\r\n"),
4173 MockWrite("GET / HTTP/1.1\r\n"
4174 "Host: www.google.com\r\n"
4175 "Connection: keep-alive\r\n\r\n"),
4176 };
4177
4178 MockRead data_reads[] = {
4179 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4180 MockRead("HTTP/1.1 200 OK\r\n"),
4181 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4182 MockRead("Content-Length: 100\r\n\r\n"),
4183 MockRead(false, OK),
4184 };
4185
4186 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4187 data_writes, arraysize(data_writes));
4188 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4189 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4190
4191 session_deps.socket_factory.AddSocketDataProvider(&data);
4192 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4193 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4194
4195 TestCompletionCallback callback;
4196
4197 scoped_ptr<HttpTransaction> trans(
4198 new HttpNetworkTransaction(CreateSession(&session_deps)));
4199
4200 int rv = trans->Start(&request, &callback, BoundNetLog());
4201 EXPECT_EQ(ERR_IO_PENDING, rv);
4202
4203 rv = callback.WaitForResult();
4204 EXPECT_EQ(OK, rv);
4205 const HttpResponseInfo* response = trans->GetResponseInfo();
4206
4207 ASSERT_FALSE(response == NULL);
4208
4209 EXPECT_TRUE(response->headers->IsKeepAlive());
4210 EXPECT_EQ(200, response->headers->response_code());
4211 EXPECT_EQ(100, response->headers->GetContentLength());
4212 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4213}
4214
4215// Test HTTPS connections to a site with a bad certificate, going through an
4216// HTTPS proxy
4217TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004218 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464219
4220 HttpRequestInfo request;
4221 request.method = "GET";
4222 request.url = GURL("https://www.google.com/");
4223 request.load_flags = 0;
4224
4225 // Attempt to fetch the URL from a server with a bad cert
4226 MockWrite bad_cert_writes[] = {
4227 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4228 "Host: www.google.com\r\n"
4229 "Proxy-Connection: keep-alive\r\n\r\n"),
4230 };
4231
4232 MockRead bad_cert_reads[] = {
4233 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4234 MockRead(false, OK)
4235 };
4236
4237 // Attempt to fetch the URL with a good cert
4238 MockWrite good_data_writes[] = {
4239 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4240 "Host: www.google.com\r\n"
4241 "Proxy-Connection: keep-alive\r\n\r\n"),
4242 MockWrite("GET / HTTP/1.1\r\n"
4243 "Host: www.google.com\r\n"
4244 "Connection: keep-alive\r\n\r\n"),
4245 };
4246
4247 MockRead good_cert_reads[] = {
4248 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4249 MockRead("HTTP/1.0 200 OK\r\n"),
4250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4251 MockRead("Content-Length: 100\r\n\r\n"),
4252 MockRead(false, OK),
4253 };
4254
4255 StaticSocketDataProvider ssl_bad_certificate(
4256 bad_cert_reads, arraysize(bad_cert_reads),
4257 bad_cert_writes, arraysize(bad_cert_writes));
4258 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4259 good_data_writes, arraysize(good_data_writes));
4260 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4261 SSLSocketDataProvider ssl(true, OK);
4262
4263 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4264 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4265 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4266 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4267
4268 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4269 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4270 session_deps.socket_factory.AddSocketDataProvider(&data);
4271 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4272
4273 TestCompletionCallback callback;
4274
4275 scoped_ptr<HttpTransaction> trans(
4276 new HttpNetworkTransaction(CreateSession(&session_deps)));
4277
4278 int rv = trans->Start(&request, &callback, BoundNetLog());
4279 EXPECT_EQ(ERR_IO_PENDING, rv);
4280
4281 rv = callback.WaitForResult();
4282 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4283
4284 rv = trans->RestartIgnoringLastError(&callback);
4285 EXPECT_EQ(ERR_IO_PENDING, rv);
4286
4287 rv = callback.WaitForResult();
4288 EXPECT_EQ(OK, rv);
4289
4290 const HttpResponseInfo* response = trans->GetResponseInfo();
4291
4292 EXPECT_FALSE(response == NULL);
4293 EXPECT_EQ(100, response->headers->GetContentLength());
4294}
4295
[email protected]1c773ea12009-04-28 19:58:424296TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594297 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404298 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434299 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424300
4301 HttpRequestInfo request;
4302 request.method = "GET";
4303 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434304 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4305 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424306
4307 MockWrite data_writes[] = {
4308 MockWrite("GET / HTTP/1.1\r\n"
4309 "Host: www.google.com\r\n"
4310 "Connection: keep-alive\r\n"
4311 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4312 };
4313
4314 // Lastly, the server responds with the actual content.
4315 MockRead data_reads[] = {
4316 MockRead("HTTP/1.0 200 OK\r\n"),
4317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4318 MockRead("Content-Length: 100\r\n\r\n"),
4319 MockRead(false, OK),
4320 };
4321
[email protected]31a2bfe2010-02-09 08:03:394322 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4323 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594324 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424325
4326 TestCompletionCallback callback;
4327
[email protected]5a1d7ca2010-04-28 20:12:274328 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424329 EXPECT_EQ(ERR_IO_PENDING, rv);
4330
4331 rv = callback.WaitForResult();
4332 EXPECT_EQ(OK, rv);
4333}
4334
[email protected]da81f132010-08-18 23:39:294335TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]81cdfcd2010-10-16 00:49:004336 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]da81f132010-08-18 23:39:294337 scoped_ptr<HttpTransaction> trans(
4338 new HttpNetworkTransaction(CreateSession(&session_deps)));
4339
4340 HttpRequestInfo request;
4341 request.method = "GET";
4342 request.url = GURL("https://www.google.com/");
4343 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4344 "Chromium Ultra Awesome X Edition");
4345
4346 MockWrite data_writes[] = {
4347 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4348 "Host: www.google.com\r\n"
4349 "Proxy-Connection: keep-alive\r\n"
4350 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4351 };
4352 MockRead data_reads[] = {
4353 // Return an error, so the transaction stops here (this test isn't
4354 // interested in the rest).
4355 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4356 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4357 MockRead("Proxy-Connection: close\r\n\r\n"),
4358 };
4359
4360 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4361 data_writes, arraysize(data_writes));
4362 session_deps.socket_factory.AddSocketDataProvider(&data);
4363
4364 TestCompletionCallback callback;
4365
4366 int rv = trans->Start(&request, &callback, BoundNetLog());
4367 EXPECT_EQ(ERR_IO_PENDING, rv);
4368
4369 rv = callback.WaitForResult();
4370 EXPECT_EQ(OK, rv);
4371}
4372
[email protected]1c773ea12009-04-28 19:58:424373TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594374 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404375 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434376 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424377
4378 HttpRequestInfo request;
4379 request.method = "GET";
4380 request.url = GURL("http://www.google.com/");
4381 request.load_flags = 0;
4382 request.referrer = GURL("http://the.previous.site.com/");
4383
4384 MockWrite data_writes[] = {
4385 MockWrite("GET / HTTP/1.1\r\n"
4386 "Host: www.google.com\r\n"
4387 "Connection: keep-alive\r\n"
4388 "Referer: http://the.previous.site.com/\r\n\r\n"),
4389 };
4390
4391 // Lastly, the server responds with the actual content.
4392 MockRead data_reads[] = {
4393 MockRead("HTTP/1.0 200 OK\r\n"),
4394 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4395 MockRead("Content-Length: 100\r\n\r\n"),
4396 MockRead(false, OK),
4397 };
4398
[email protected]31a2bfe2010-02-09 08:03:394399 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4400 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594401 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424402
4403 TestCompletionCallback callback;
4404
[email protected]5a1d7ca2010-04-28 20:12:274405 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424406 EXPECT_EQ(ERR_IO_PENDING, rv);
4407
4408 rv = callback.WaitForResult();
4409 EXPECT_EQ(OK, rv);
4410}
4411
4412TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594413 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404414 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434415 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424416
4417 HttpRequestInfo request;
4418 request.method = "POST";
4419 request.url = GURL("http://www.google.com/");
4420
4421 MockWrite data_writes[] = {
4422 MockWrite("POST / HTTP/1.1\r\n"
4423 "Host: www.google.com\r\n"
4424 "Connection: keep-alive\r\n"
4425 "Content-Length: 0\r\n\r\n"),
4426 };
4427
4428 // Lastly, the server responds with the actual content.
4429 MockRead data_reads[] = {
4430 MockRead("HTTP/1.0 200 OK\r\n"),
4431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4432 MockRead("Content-Length: 100\r\n\r\n"),
4433 MockRead(false, OK),
4434 };
4435
[email protected]31a2bfe2010-02-09 08:03:394436 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4437 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594438 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424439
4440 TestCompletionCallback callback;
4441
[email protected]5a1d7ca2010-04-28 20:12:274442 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424443 EXPECT_EQ(ERR_IO_PENDING, rv);
4444
4445 rv = callback.WaitForResult();
4446 EXPECT_EQ(OK, rv);
4447}
4448
4449TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594450 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404451 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434452 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424453
4454 HttpRequestInfo request;
4455 request.method = "PUT";
4456 request.url = GURL("http://www.google.com/");
4457
4458 MockWrite data_writes[] = {
4459 MockWrite("PUT / HTTP/1.1\r\n"
4460 "Host: www.google.com\r\n"
4461 "Connection: keep-alive\r\n"
4462 "Content-Length: 0\r\n\r\n"),
4463 };
4464
4465 // Lastly, the server responds with the actual content.
4466 MockRead data_reads[] = {
4467 MockRead("HTTP/1.0 200 OK\r\n"),
4468 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4469 MockRead("Content-Length: 100\r\n\r\n"),
4470 MockRead(false, OK),
4471 };
4472
[email protected]31a2bfe2010-02-09 08:03:394473 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4474 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594475 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424476
4477 TestCompletionCallback callback;
4478
[email protected]5a1d7ca2010-04-28 20:12:274479 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424480 EXPECT_EQ(ERR_IO_PENDING, rv);
4481
4482 rv = callback.WaitForResult();
4483 EXPECT_EQ(OK, rv);
4484}
4485
4486TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594487 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404488 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434489 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424490
4491 HttpRequestInfo request;
4492 request.method = "HEAD";
4493 request.url = GURL("http://www.google.com/");
4494
4495 MockWrite data_writes[] = {
4496 MockWrite("HEAD / HTTP/1.1\r\n"
4497 "Host: www.google.com\r\n"
4498 "Connection: keep-alive\r\n"
4499 "Content-Length: 0\r\n\r\n"),
4500 };
4501
4502 // Lastly, the server responds with the actual content.
4503 MockRead data_reads[] = {
4504 MockRead("HTTP/1.0 200 OK\r\n"),
4505 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4506 MockRead("Content-Length: 100\r\n\r\n"),
4507 MockRead(false, OK),
4508 };
4509
[email protected]31a2bfe2010-02-09 08:03:394510 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4511 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594512 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424513
4514 TestCompletionCallback callback;
4515
[email protected]5a1d7ca2010-04-28 20:12:274516 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424517 EXPECT_EQ(ERR_IO_PENDING, rv);
4518
4519 rv = callback.WaitForResult();
4520 EXPECT_EQ(OK, rv);
4521}
4522
4523TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594524 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404525 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434526 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424527
4528 HttpRequestInfo request;
4529 request.method = "GET";
4530 request.url = GURL("http://www.google.com/");
4531 request.load_flags = LOAD_BYPASS_CACHE;
4532
4533 MockWrite data_writes[] = {
4534 MockWrite("GET / HTTP/1.1\r\n"
4535 "Host: www.google.com\r\n"
4536 "Connection: keep-alive\r\n"
4537 "Pragma: no-cache\r\n"
4538 "Cache-Control: no-cache\r\n\r\n"),
4539 };
4540
4541 // Lastly, the server responds with the actual content.
4542 MockRead data_reads[] = {
4543 MockRead("HTTP/1.0 200 OK\r\n"),
4544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4545 MockRead("Content-Length: 100\r\n\r\n"),
4546 MockRead(false, OK),
4547 };
4548
[email protected]31a2bfe2010-02-09 08:03:394549 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4550 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594551 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424552
4553 TestCompletionCallback callback;
4554
[email protected]5a1d7ca2010-04-28 20:12:274555 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424556 EXPECT_EQ(ERR_IO_PENDING, rv);
4557
4558 rv = callback.WaitForResult();
4559 EXPECT_EQ(OK, rv);
4560}
4561
4562TEST_F(HttpNetworkTransactionTest,
4563 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594564 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404565 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434566 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424567
4568 HttpRequestInfo request;
4569 request.method = "GET";
4570 request.url = GURL("http://www.google.com/");
4571 request.load_flags = LOAD_VALIDATE_CACHE;
4572
4573 MockWrite data_writes[] = {
4574 MockWrite("GET / HTTP/1.1\r\n"
4575 "Host: www.google.com\r\n"
4576 "Connection: keep-alive\r\n"
4577 "Cache-Control: max-age=0\r\n\r\n"),
4578 };
4579
4580 // Lastly, the server responds with the actual content.
4581 MockRead data_reads[] = {
4582 MockRead("HTTP/1.0 200 OK\r\n"),
4583 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4584 MockRead("Content-Length: 100\r\n\r\n"),
4585 MockRead(false, OK),
4586 };
4587
[email protected]31a2bfe2010-02-09 08:03:394588 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4589 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594590 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424591
4592 TestCompletionCallback callback;
4593
[email protected]5a1d7ca2010-04-28 20:12:274594 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424595 EXPECT_EQ(ERR_IO_PENDING, rv);
4596
4597 rv = callback.WaitForResult();
4598 EXPECT_EQ(OK, rv);
4599}
4600
4601TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594602 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404603 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434604 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424605
4606 HttpRequestInfo request;
4607 request.method = "GET";
4608 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434609 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424610
4611 MockWrite data_writes[] = {
4612 MockWrite("GET / HTTP/1.1\r\n"
4613 "Host: www.google.com\r\n"
4614 "Connection: keep-alive\r\n"
4615 "FooHeader: Bar\r\n\r\n"),
4616 };
4617
4618 // Lastly, the server responds with the actual content.
4619 MockRead data_reads[] = {
4620 MockRead("HTTP/1.0 200 OK\r\n"),
4621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4622 MockRead("Content-Length: 100\r\n\r\n"),
4623 MockRead(false, OK),
4624 };
4625
[email protected]31a2bfe2010-02-09 08:03:394626 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4627 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594628 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424629
4630 TestCompletionCallback callback;
4631
[email protected]5a1d7ca2010-04-28 20:12:274632 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424633 EXPECT_EQ(ERR_IO_PENDING, rv);
4634
4635 rv = callback.WaitForResult();
4636 EXPECT_EQ(OK, rv);
4637}
4638
[email protected]270c6412010-03-29 22:02:474639TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4640 SessionDependencies session_deps;
4641 scoped_ptr<HttpTransaction> trans(
4642 new HttpNetworkTransaction(CreateSession(&session_deps)));
4643
4644 HttpRequestInfo request;
4645 request.method = "GET";
4646 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434647 request.extra_headers.SetHeader("referer", "www.foo.com");
4648 request.extra_headers.SetHeader("hEllo", "Kitty");
4649 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474650
4651 MockWrite data_writes[] = {
4652 MockWrite("GET / HTTP/1.1\r\n"
4653 "Host: www.google.com\r\n"
4654 "Connection: keep-alive\r\n"
4655 "hEllo: Kitty\r\n"
4656 "FoO: bar\r\n\r\n"),
4657 };
4658
4659 // Lastly, the server responds with the actual content.
4660 MockRead data_reads[] = {
4661 MockRead("HTTP/1.0 200 OK\r\n"),
4662 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4663 MockRead("Content-Length: 100\r\n\r\n"),
4664 MockRead(false, OK),
4665 };
4666
4667 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4668 data_writes, arraysize(data_writes));
4669 session_deps.socket_factory.AddSocketDataProvider(&data);
4670
4671 TestCompletionCallback callback;
4672
[email protected]5a1d7ca2010-04-28 20:12:274673 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474674 EXPECT_EQ(ERR_IO_PENDING, rv);
4675
4676 rv = callback.WaitForResult();
4677 EXPECT_EQ(OK, rv);
4678}
4679
[email protected]3cd17242009-06-23 02:59:024680TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094681 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004682 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024683
4684 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434685 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024686
4687 HttpRequestInfo request;
4688 request.method = "GET";
4689 request.url = GURL("http://www.google.com/");
4690 request.load_flags = 0;
4691
4692 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4693 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4694
4695 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354696 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024697 MockWrite("GET / HTTP/1.1\r\n"
4698 "Host: www.google.com\r\n"
4699 "Connection: keep-alive\r\n\r\n")
4700 };
4701
4702 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594703 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024704 MockRead("HTTP/1.0 200 OK\r\n"),
4705 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4706 MockRead("Payload"),
4707 MockRead(false, OK)
4708 };
4709
[email protected]31a2bfe2010-02-09 08:03:394710 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4711 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594712 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024713
4714 TestCompletionCallback callback;
4715
[email protected]5a1d7ca2010-04-28 20:12:274716 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024717 EXPECT_EQ(ERR_IO_PENDING, rv);
4718
4719 rv = callback.WaitForResult();
4720 EXPECT_EQ(OK, rv);
4721
4722 const HttpResponseInfo* response = trans->GetResponseInfo();
4723 EXPECT_FALSE(response == NULL);
4724
4725 std::string response_text;
4726 rv = ReadTransaction(trans.get(), &response_text);
4727 EXPECT_EQ(OK, rv);
4728 EXPECT_EQ("Payload", response_text);
4729}
4730
4731TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094732 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004733 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024734
4735 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434736 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024737
4738 HttpRequestInfo request;
4739 request.method = "GET";
4740 request.url = GURL("https://www.google.com/");
4741 request.load_flags = 0;
4742
4743 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4744 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4745
4746 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354747 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4748 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024749 MockWrite("GET / HTTP/1.1\r\n"
4750 "Host: www.google.com\r\n"
4751 "Connection: keep-alive\r\n\r\n")
4752 };
4753
4754 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354755 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4756 arraysize(read_buffer)),
4757 MockRead("HTTP/1.0 200 OK\r\n"),
4758 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4759 MockRead("Payload"),
4760 MockRead(false, OK)
4761 };
4762
[email protected]31a2bfe2010-02-09 08:03:394763 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4764 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594765 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354766
[email protected]5ecc992a42009-11-11 01:41:594767 SSLSocketDataProvider ssl(true, OK);
4768 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354769
4770 TestCompletionCallback callback;
4771
[email protected]5a1d7ca2010-04-28 20:12:274772 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354773 EXPECT_EQ(ERR_IO_PENDING, rv);
4774
4775 rv = callback.WaitForResult();
4776 EXPECT_EQ(OK, rv);
4777
4778 const HttpResponseInfo* response = trans->GetResponseInfo();
4779 EXPECT_FALSE(response == NULL);
4780
4781 std::string response_text;
4782 rv = ReadTransaction(trans.get(), &response_text);
4783 EXPECT_EQ(OK, rv);
4784 EXPECT_EQ("Payload", response_text);
4785}
4786
4787TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094788 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004789 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354790
4791 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434792 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354793
4794 HttpRequestInfo request;
4795 request.method = "GET";
4796 request.url = GURL("http://www.google.com/");
4797 request.load_flags = 0;
4798
4799 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4800 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374801 const char kSOCKS5OkRequest[] = {
4802 0x05, // Version
4803 0x01, // Command (CONNECT)
4804 0x00, // Reserved.
4805 0x03, // Address type (DOMAINNAME).
4806 0x0E, // Length of domain (14)
4807 // Domain string:
4808 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4809 0x00, 0x50, // 16-bit port (80)
4810 };
[email protected]e0c27be2009-07-15 13:09:354811 const char kSOCKS5OkResponse[] =
4812 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4813
4814 MockWrite data_writes[] = {
4815 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4816 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4817 MockWrite("GET / HTTP/1.1\r\n"
4818 "Host: www.google.com\r\n"
4819 "Connection: keep-alive\r\n\r\n")
4820 };
4821
4822 MockRead data_reads[] = {
4823 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4824 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4825 MockRead("HTTP/1.0 200 OK\r\n"),
4826 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4827 MockRead("Payload"),
4828 MockRead(false, OK)
4829 };
4830
[email protected]31a2bfe2010-02-09 08:03:394831 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4832 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594833 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354834
4835 TestCompletionCallback callback;
4836
[email protected]5a1d7ca2010-04-28 20:12:274837 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354838 EXPECT_EQ(ERR_IO_PENDING, rv);
4839
4840 rv = callback.WaitForResult();
4841 EXPECT_EQ(OK, rv);
4842
4843 const HttpResponseInfo* response = trans->GetResponseInfo();
4844 EXPECT_FALSE(response == NULL);
4845
4846 std::string response_text;
4847 rv = ReadTransaction(trans.get(), &response_text);
4848 EXPECT_EQ(OK, rv);
4849 EXPECT_EQ("Payload", response_text);
4850}
4851
4852TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094853 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004854 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354855
4856 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434857 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354858
4859 HttpRequestInfo request;
4860 request.method = "GET";
4861 request.url = GURL("https://www.google.com/");
4862 request.load_flags = 0;
4863
4864 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4865 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374866 const unsigned char kSOCKS5OkRequest[] = {
4867 0x05, // Version
4868 0x01, // Command (CONNECT)
4869 0x00, // Reserved.
4870 0x03, // Address type (DOMAINNAME).
4871 0x0E, // Length of domain (14)
4872 // Domain string:
4873 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4874 0x01, 0xBB, // 16-bit port (443)
4875 };
4876
[email protected]e0c27be2009-07-15 13:09:354877 const char kSOCKS5OkResponse[] =
4878 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4879
4880 MockWrite data_writes[] = {
4881 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4882 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4883 arraysize(kSOCKS5OkRequest)),
4884 MockWrite("GET / HTTP/1.1\r\n"
4885 "Host: www.google.com\r\n"
4886 "Connection: keep-alive\r\n\r\n")
4887 };
4888
4889 MockRead data_reads[] = {
4890 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4891 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024892 MockRead("HTTP/1.0 200 OK\r\n"),
4893 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4894 MockRead("Payload"),
4895 MockRead(false, OK)
4896 };
4897
[email protected]31a2bfe2010-02-09 08:03:394898 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4899 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594900 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024901
[email protected]5ecc992a42009-11-11 01:41:594902 SSLSocketDataProvider ssl(true, OK);
4903 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024904
4905 TestCompletionCallback callback;
4906
[email protected]5a1d7ca2010-04-28 20:12:274907 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024908 EXPECT_EQ(ERR_IO_PENDING, rv);
4909
4910 rv = callback.WaitForResult();
4911 EXPECT_EQ(OK, rv);
4912
4913 const HttpResponseInfo* response = trans->GetResponseInfo();
4914 EXPECT_FALSE(response == NULL);
4915
4916 std::string response_text;
4917 rv = ReadTransaction(trans.get(), &response_text);
4918 EXPECT_EQ(OK, rv);
4919 EXPECT_EQ("Payload", response_text);
4920}
4921
[email protected]04e5be32009-06-26 20:00:314922// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064923
4924struct GroupNameTest {
4925 std::string proxy_server;
4926 std::string url;
4927 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184928 bool ssl;
[email protected]2d731a32010-04-29 01:04:064929};
4930
4931scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4932 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:004933 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:064934 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4935
4936 HttpAlternateProtocols* alternate_protocols =
4937 session->mutable_alternate_protocols();
4938 alternate_protocols->SetAlternateProtocolFor(
4939 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354940 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064941
4942 return session;
4943}
4944
4945int GroupNameTransactionHelper(
4946 const std::string& url,
4947 const scoped_refptr<HttpNetworkSession>& session) {
4948 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4949
4950 HttpRequestInfo request;
4951 request.method = "GET";
4952 request.url = GURL(url);
4953 request.load_flags = 0;
4954
4955 TestCompletionCallback callback;
4956
4957 // We do not complete this request, the dtor will clean the transaction up.
4958 return trans->Start(&request, &callback, BoundNetLog());
4959}
4960
4961TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4962 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314963 {
[email protected]2d731a32010-04-29 01:04:064964 "", // unused
[email protected]04e5be32009-06-26 20:00:314965 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544966 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184967 false,
[email protected]2ff8b312010-04-26 22:20:544968 },
4969 {
[email protected]2d731a32010-04-29 01:04:064970 "", // unused
[email protected]2ff8b312010-04-26 22:20:544971 "http://[2001:1418:13:1::25]/direct",
4972 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184973 false,
[email protected]04e5be32009-06-26 20:00:314974 },
[email protected]04e5be32009-06-26 20:00:314975
4976 // SSL Tests
4977 {
[email protected]2d731a32010-04-29 01:04:064978 "", // unused
[email protected]04e5be32009-06-26 20:00:314979 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024980 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184981 true,
[email protected]04e5be32009-06-26 20:00:314982 },
4983 {
[email protected]2d731a32010-04-29 01:04:064984 "", // unused
4985 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024986 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184987 true,
[email protected]04e5be32009-06-26 20:00:314988 },
4989 {
[email protected]2d731a32010-04-29 01:04:064990 "", // unused
[email protected]2ff8b312010-04-26 22:20:544991 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024992 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184993 true,
[email protected]2ff8b312010-04-26 22:20:544994 },
[email protected]2d731a32010-04-29 01:04:064995 };
[email protected]2ff8b312010-04-26 22:20:544996
[email protected]8e6441ca2010-08-19 05:56:384997 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064998
4999 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5000 scoped_refptr<HttpNetworkSession> session(
5001 SetupSessionForGroupNameTests(tests[i].proxy_server));
5002
5003 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135004 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5005 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065006 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135007 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5008 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185009 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065010
5011 EXPECT_EQ(ERR_IO_PENDING,
5012 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185013 if (tests[i].ssl)
5014 EXPECT_EQ(tests[i].expected_group_name,
5015 ssl_conn_pool->last_group_name_received());
5016 else
5017 EXPECT_EQ(tests[i].expected_group_name,
5018 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065019 }
5020
[email protected]8e6441ca2010-08-19 05:56:385021 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065022}
5023
5024TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5025 const GroupNameTest tests[] = {
5026 {
5027 "http_proxy",
5028 "http://www.google.com/http_proxy_normal",
5029 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185030 false,
[email protected]2d731a32010-04-29 01:04:065031 },
5032
5033 // SSL Tests
5034 {
5035 "http_proxy",
5036 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025037 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185038 true,
[email protected]2d731a32010-04-29 01:04:065039 },
[email protected]9faeded92010-04-29 20:03:055040 {
5041 "http_proxy",
5042 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025043 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185044 true,
[email protected]9faeded92010-04-29 20:03:055045 },
[email protected]2d731a32010-04-29 01:04:065046 };
5047
[email protected]8e6441ca2010-08-19 05:56:385048 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065049
5050 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5051 scoped_refptr<HttpNetworkSession> session(
5052 SetupSessionForGroupNameTests(tests[i].proxy_server));
5053
5054 HttpNetworkSessionPeer peer(session);
5055
[email protected]e60e47a2010-07-14 03:37:185056 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135057 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5058 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185059 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135060 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5061 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185062 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065063
5064 EXPECT_EQ(ERR_IO_PENDING,
5065 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185066 if (tests[i].ssl)
5067 EXPECT_EQ(tests[i].expected_group_name,
5068 ssl_conn_pool->last_group_name_received());
5069 else
5070 EXPECT_EQ(tests[i].expected_group_name,
5071 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065072 }
5073
[email protected]8e6441ca2010-08-19 05:56:385074 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065075}
5076
5077TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5078 const GroupNameTest tests[] = {
5079 {
5080 "socks4://socks_proxy:1080",
5081 "http://www.google.com/socks4_direct",
5082 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185083 false,
[email protected]2d731a32010-04-29 01:04:065084 },
5085 {
5086 "socks5://socks_proxy:1080",
5087 "http://www.google.com/socks5_direct",
5088 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185089 false,
[email protected]2d731a32010-04-29 01:04:065090 },
5091
5092 // SSL Tests
5093 {
5094 "socks4://socks_proxy:1080",
5095 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025096 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185097 true,
[email protected]2d731a32010-04-29 01:04:065098 },
5099 {
5100 "socks5://socks_proxy:1080",
5101 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025102 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185103 true,
[email protected]2d731a32010-04-29 01:04:065104 },
[email protected]9faeded92010-04-29 20:03:055105 {
5106 "socks4://socks_proxy:1080",
5107 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025108 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185109 true,
[email protected]9faeded92010-04-29 20:03:055110 },
[email protected]04e5be32009-06-26 20:00:315111 };
5112
[email protected]8e6441ca2010-08-19 05:56:385113 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545114
[email protected]04e5be32009-06-26 20:00:315115 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065116 scoped_refptr<HttpNetworkSession> session(
5117 SetupSessionForGroupNameTests(tests[i].proxy_server));
5118 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315119
[email protected]e60e47a2010-07-14 03:37:185120 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135121 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5122 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185123 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135124 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5125 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185126 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315127
[email protected]5695b8c2009-09-30 21:36:435128 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315129
[email protected]2d731a32010-04-29 01:04:065130 EXPECT_EQ(ERR_IO_PENDING,
5131 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185132 if (tests[i].ssl)
5133 EXPECT_EQ(tests[i].expected_group_name,
5134 ssl_conn_pool->last_group_name_received());
5135 else
5136 EXPECT_EQ(tests[i].expected_group_name,
5137 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315138 }
[email protected]2ff8b312010-04-26 22:20:545139
[email protected]8e6441ca2010-08-19 05:56:385140 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315141}
5142
[email protected]9172a982009-06-06 00:30:255143TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545144 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005145 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325146
[email protected]69719062010-01-05 20:09:215147 // This simulates failure resolving all hostnames; that means we will fail
5148 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325149 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5150
[email protected]9172a982009-06-06 00:30:255151 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435152 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255153
5154 HttpRequestInfo request;
5155 request.method = "GET";
5156 request.url = GURL("http://www.google.com/");
5157
5158 TestCompletionCallback callback;
5159
[email protected]5a1d7ca2010-04-28 20:12:275160 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255161 EXPECT_EQ(ERR_IO_PENDING, rv);
5162
[email protected]9172a982009-06-06 00:30:255163 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015164 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255165}
5166
[email protected]f3e6c1e2009-06-15 20:52:125167// Host resolution observer used by
5168// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5169// resovle requests are issued with a referrer of |expected_referrer|.
5170class ResolutionReferrerObserver : public HostResolver::Observer {
5171 public:
5172 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5173 : expected_referrer_(expected_referrer),
5174 called_start_with_referrer_(false),
5175 called_finish_with_referrer_(false) {
5176 }
5177
5178 virtual void OnStartResolution(int id,
5179 const HostResolver::RequestInfo& info) {
5180 if (info.referrer() == expected_referrer_)
5181 called_start_with_referrer_ = true;
5182 }
5183
5184 virtual void OnFinishResolutionWithStatus(
5185 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5186 if (info.referrer() == expected_referrer_)
5187 called_finish_with_referrer_ = true;
5188 }
5189
[email protected]eb255d32009-06-17 02:11:035190 virtual void OnCancelResolution(int id,
5191 const HostResolver::RequestInfo& info ) {
5192 FAIL() << "Should not be cancelling any requests!";
5193 }
5194
[email protected]f3e6c1e2009-06-15 20:52:125195 bool did_complete_with_expected_referrer() const {
5196 return called_start_with_referrer_ && called_finish_with_referrer_;
5197 }
5198
5199 private:
5200 GURL expected_referrer_;
5201 bool called_start_with_referrer_;
5202 bool called_finish_with_referrer_;
5203
5204 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5205};
5206
5207// Make sure that when HostResolver::Resolve() is invoked, it passes through
5208// the "referrer". This is depended on by the DNS prefetch observer.
5209TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5210 GURL referrer = GURL("http://expected-referrer/");
5211 EXPECT_TRUE(referrer.is_valid());
5212 ResolutionReferrerObserver resolution_observer(referrer);
5213
5214 SessionDependencies session_deps;
5215 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435216 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125217
5218 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145219 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125220
5221 // Connect up a mock socket which will fail when reading.
5222 MockRead data_reads[] = {
5223 MockRead(false, ERR_FAILED),
5224 };
[email protected]31a2bfe2010-02-09 08:03:395225 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595226 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125227
5228 // Issue a request, containing an HTTP referrer.
5229 HttpRequestInfo request;
5230 request.method = "GET";
5231 request.referrer = referrer;
5232 request.url = GURL("http://www.google.com/");
5233
5234 // Run the request until it fails reading from the socket.
5235 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275236 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125237 EXPECT_EQ(ERR_IO_PENDING, rv);
5238 rv = callback.WaitForResult();
5239 EXPECT_EQ(ERR_FAILED, rv);
5240
5241 // Check that the host resolution observer saw |referrer|.
5242 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5243}
5244
[email protected]685af592010-05-11 19:31:245245// Base test to make sure that when the load flags for a request specify to
5246// bypass the cache, the DNS cache is not used.
5247void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285248 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325249
[email protected]a2c2fb92009-07-18 07:31:045250 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545251 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325252
[email protected]3b9cca42009-06-16 01:08:285253 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435254 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285255
5256 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5257 // a synchronous lookup.)
5258 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145259 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105260 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275261 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285262 EXPECT_EQ(OK, rv);
5263
5264 // Verify that it was added to host cache, by doing a subsequent async lookup
5265 // and confirming it completes synchronously.
5266 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465267 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105268 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275269 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325270 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285271
5272 // Inject a failure the next time that "www.google.com" is resolved. This way
5273 // we can tell if the next lookup hit the cache, or the "network".
5274 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325275 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285276
5277 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5278 // first read -- this won't be reached as the host resolution will fail first.
5279 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395280 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595281 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285282
5283 // Issue a request, asking to bypass the cache(s).
5284 HttpRequestInfo request;
5285 request.method = "GET";
[email protected]685af592010-05-11 19:31:245286 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285287 request.url = GURL("http://www.google.com/");
5288
5289 // Run the request.
5290 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275291 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285292 ASSERT_EQ(ERR_IO_PENDING, rv);
5293 rv = callback.WaitForResult();
5294
5295 // If we bypassed the cache, we would have gotten a failure while resolving
5296 // "www.google.com".
5297 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5298}
5299
[email protected]685af592010-05-11 19:31:245300// There are multiple load flags that should trigger the host cache bypass.
5301// Test each in isolation:
5302TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5303 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5304}
5305
5306TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5307 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5308}
5309
5310TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5311 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5312}
5313
[email protected]0877e3d2009-10-17 22:29:575314// Make sure we can handle an error when writing the request.
5315TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5316 SessionDependencies session_deps;
5317 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5318
5319 HttpRequestInfo request;
5320 request.method = "GET";
5321 request.url = GURL("http://www.foo.com/");
5322 request.load_flags = 0;
5323
5324 MockWrite write_failure[] = {
5325 MockWrite(true, ERR_CONNECTION_RESET),
5326 };
[email protected]31a2bfe2010-02-09 08:03:395327 StaticSocketDataProvider data(NULL, 0,
5328 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595329 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575330
5331 TestCompletionCallback callback;
5332
5333 scoped_ptr<HttpTransaction> trans(
5334 new HttpNetworkTransaction(CreateSession(&session_deps)));
5335
[email protected]5a1d7ca2010-04-28 20:12:275336 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575337 EXPECT_EQ(ERR_IO_PENDING, rv);
5338
5339 rv = callback.WaitForResult();
5340 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5341}
5342
5343// Check that a connection closed after the start of the headers finishes ok.
5344TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5345 SessionDependencies session_deps;
5346 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5347
5348 HttpRequestInfo request;
5349 request.method = "GET";
5350 request.url = GURL("http://www.foo.com/");
5351 request.load_flags = 0;
5352
5353 MockRead data_reads[] = {
5354 MockRead("HTTP/1."),
5355 MockRead(false, OK),
5356 };
5357
[email protected]31a2bfe2010-02-09 08:03:395358 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595359 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575360
5361 TestCompletionCallback callback;
5362
5363 scoped_ptr<HttpTransaction> trans(
5364 new HttpNetworkTransaction(CreateSession(&session_deps)));
5365
[email protected]5a1d7ca2010-04-28 20:12:275366 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575367 EXPECT_EQ(ERR_IO_PENDING, rv);
5368
5369 rv = callback.WaitForResult();
5370 EXPECT_EQ(OK, rv);
5371
5372 const HttpResponseInfo* response = trans->GetResponseInfo();
5373 EXPECT_TRUE(response != NULL);
5374
5375 EXPECT_TRUE(response->headers != NULL);
5376 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5377
5378 std::string response_data;
5379 rv = ReadTransaction(trans.get(), &response_data);
5380 EXPECT_EQ(OK, rv);
5381 EXPECT_EQ("", response_data);
5382}
5383
5384// Make sure that a dropped connection while draining the body for auth
5385// restart does the right thing.
5386TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5387 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:505388 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]0877e3d2009-10-17 22:29:575389
5390 HttpRequestInfo request;
5391 request.method = "GET";
5392 request.url = GURL("http://www.google.com/");
5393 request.load_flags = 0;
5394
5395 MockWrite data_writes1[] = {
5396 MockWrite("GET / HTTP/1.1\r\n"
5397 "Host: www.google.com\r\n"
5398 "Connection: keep-alive\r\n\r\n"),
5399 };
5400
5401 MockRead data_reads1[] = {
5402 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5403 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5405 MockRead("Content-Length: 14\r\n\r\n"),
5406 MockRead("Unauth"),
5407 MockRead(true, ERR_CONNECTION_RESET),
5408 };
5409
[email protected]31a2bfe2010-02-09 08:03:395410 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5411 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595412 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575413
5414 // After calling trans->RestartWithAuth(), this is the request we should
5415 // be issuing -- the final header line contains the credentials.
5416 MockWrite data_writes2[] = {
5417 MockWrite("GET / HTTP/1.1\r\n"
5418 "Host: www.google.com\r\n"
5419 "Connection: keep-alive\r\n"
5420 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5421 };
5422
5423 // Lastly, the server responds with the actual content.
5424 MockRead data_reads2[] = {
5425 MockRead("HTTP/1.1 200 OK\r\n"),
5426 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5427 MockRead("Content-Length: 100\r\n\r\n"),
5428 MockRead(false, OK),
5429 };
5430
[email protected]31a2bfe2010-02-09 08:03:395431 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5432 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595433 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575434
5435 TestCompletionCallback callback1;
5436
[email protected]0b0bf032010-09-21 18:08:505437 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5438
[email protected]5a1d7ca2010-04-28 20:12:275439 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575440 EXPECT_EQ(ERR_IO_PENDING, rv);
5441
5442 rv = callback1.WaitForResult();
5443 EXPECT_EQ(OK, rv);
5444
5445 const HttpResponseInfo* response = trans->GetResponseInfo();
5446 EXPECT_FALSE(response == NULL);
5447
5448 // The password prompt info should have been set in response->auth_challenge.
5449 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5450
5451 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5452 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5453 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5454
5455 TestCompletionCallback callback2;
5456
[email protected]13c8a092010-07-29 06:15:445457 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575458 EXPECT_EQ(ERR_IO_PENDING, rv);
5459
5460 rv = callback2.WaitForResult();
5461 EXPECT_EQ(OK, rv);
5462
5463 response = trans->GetResponseInfo();
5464 EXPECT_FALSE(response == NULL);
5465 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5466 EXPECT_EQ(100, response->headers->GetContentLength());
5467}
5468
5469// Test HTTPS connections going through a proxy that sends extra data.
5470TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005471 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575472
5473 HttpRequestInfo request;
5474 request.method = "GET";
5475 request.url = GURL("https://www.google.com/");
5476 request.load_flags = 0;
5477
5478 MockRead proxy_reads[] = {
5479 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5480 MockRead(false, OK)
5481 };
5482
[email protected]31a2bfe2010-02-09 08:03:395483 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595484 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575485
[email protected]5ecc992a42009-11-11 01:41:595486 session_deps.socket_factory.AddSocketDataProvider(&data);
5487 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575488
5489 TestCompletionCallback callback;
5490
5491 session_deps.socket_factory.ResetNextMockIndexes();
5492
5493 scoped_ptr<HttpTransaction> trans(
5494 new HttpNetworkTransaction(CreateSession(&session_deps)));
5495
[email protected]5a1d7ca2010-04-28 20:12:275496 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575497 EXPECT_EQ(ERR_IO_PENDING, rv);
5498
5499 rv = callback.WaitForResult();
5500 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5501}
5502
[email protected]e22e1362009-11-23 21:31:125503TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465504 SessionDependencies session_deps;
5505 scoped_ptr<HttpTransaction> trans(
5506 new HttpNetworkTransaction(CreateSession(&session_deps)));
5507
5508 HttpRequestInfo request;
5509 request.method = "GET";
5510 request.url = GURL("http://www.google.com/");
5511 request.load_flags = 0;
5512
[email protected]e22e1362009-11-23 21:31:125513 MockRead data_reads[] = {
5514 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5515 MockRead(false, OK),
5516 };
[email protected]9492e4a2010-02-24 00:58:465517
5518 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5519 session_deps.socket_factory.AddSocketDataProvider(&data);
5520
5521 TestCompletionCallback callback;
5522
[email protected]5a1d7ca2010-04-28 20:12:275523 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465524 EXPECT_EQ(ERR_IO_PENDING, rv);
5525
5526 EXPECT_EQ(OK, callback.WaitForResult());
5527
5528 const HttpResponseInfo* response = trans->GetResponseInfo();
5529 EXPECT_TRUE(response != NULL);
5530
5531 EXPECT_TRUE(response->headers != NULL);
5532 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5533
5534 std::string response_data;
5535 rv = ReadTransaction(trans.get(), &response_data);
5536 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125537}
5538
[email protected]95d88ffe2010-02-04 21:25:335539TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5540 SessionDependencies session_deps;
5541 scoped_ptr<HttpTransaction> trans(
5542 new HttpNetworkTransaction(CreateSession(&session_deps)));
5543
5544 HttpRequestInfo request;
5545 request.method = "POST";
5546 request.url = GURL("http://www.google.com/upload");
5547 request.upload_data = new UploadData;
5548 request.load_flags = 0;
5549
5550 FilePath temp_file_path;
5551 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5552 const uint64 kFakeSize = 100000; // file is actually blank
5553
5554 std::vector<UploadData::Element> elements;
5555 UploadData::Element element;
5556 element.SetToFilePath(temp_file_path);
5557 element.SetContentLength(kFakeSize);
5558 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535559 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335560 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5561
5562 MockRead data_reads[] = {
5563 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5564 MockRead("hello world"),
5565 MockRead(false, OK),
5566 };
[email protected]31a2bfe2010-02-09 08:03:395567 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335568 session_deps.socket_factory.AddSocketDataProvider(&data);
5569
5570 TestCompletionCallback callback;
5571
[email protected]5a1d7ca2010-04-28 20:12:275572 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335573 EXPECT_EQ(ERR_IO_PENDING, rv);
5574
5575 rv = callback.WaitForResult();
5576 EXPECT_EQ(OK, rv);
5577
5578 const HttpResponseInfo* response = trans->GetResponseInfo();
5579 EXPECT_TRUE(response != NULL);
5580
5581 EXPECT_TRUE(response->headers != NULL);
5582 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5583
5584 std::string response_data;
5585 rv = ReadTransaction(trans.get(), &response_data);
5586 EXPECT_EQ(OK, rv);
5587 EXPECT_EQ("hello world", response_data);
5588
5589 file_util::Delete(temp_file_path, false);
5590}
5591
[email protected]6624b4622010-03-29 19:58:365592TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5593 // If we try to upload an unreadable file, the network stack should report
5594 // the file size as zero and upload zero bytes for that file.
5595 SessionDependencies session_deps;
5596 scoped_ptr<HttpTransaction> trans(
5597 new HttpNetworkTransaction(CreateSession(&session_deps)));
5598
5599 FilePath temp_file;
5600 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5601 std::string temp_file_content("Unreadable file.");
5602 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5603 temp_file_content.length()));
5604 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5605
5606 HttpRequestInfo request;
5607 request.method = "POST";
5608 request.url = GURL("http://www.google.com/upload");
5609 request.upload_data = new UploadData;
5610 request.load_flags = 0;
5611
5612 std::vector<UploadData::Element> elements;
5613 UploadData::Element element;
5614 element.SetToFilePath(temp_file);
5615 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535616 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365617
5618 MockRead data_reads[] = {
5619 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5620 MockRead(false, OK),
5621 };
5622 MockWrite data_writes[] = {
5623 MockWrite("POST /upload HTTP/1.1\r\n"
5624 "Host: www.google.com\r\n"
5625 "Connection: keep-alive\r\n"
5626 "Content-Length: 0\r\n\r\n"),
5627 MockWrite(false, OK),
5628 };
5629 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5630 arraysize(data_writes));
5631 session_deps.socket_factory.AddSocketDataProvider(&data);
5632
5633 TestCompletionCallback callback;
5634
[email protected]5a1d7ca2010-04-28 20:12:275635 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365636 EXPECT_EQ(ERR_IO_PENDING, rv);
5637
5638 rv = callback.WaitForResult();
5639 EXPECT_EQ(OK, rv);
5640
5641 const HttpResponseInfo* response = trans->GetResponseInfo();
5642 EXPECT_TRUE(response != NULL);
5643 EXPECT_TRUE(response->headers != NULL);
5644 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5645
5646 file_util::Delete(temp_file, false);
5647}
5648
5649TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5650 SessionDependencies session_deps;
5651 scoped_ptr<HttpTransaction> trans(
5652 new HttpNetworkTransaction(CreateSession(&session_deps)));
5653
5654 FilePath temp_file;
5655 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5656 std::string temp_file_contents("Unreadable file.");
5657 std::string unreadable_contents(temp_file_contents.length(), '\0');
5658 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5659 temp_file_contents.length()));
5660
5661 HttpRequestInfo request;
5662 request.method = "POST";
5663 request.url = GURL("http://www.google.com/upload");
5664 request.upload_data = new UploadData;
5665 request.load_flags = 0;
5666
5667 std::vector<UploadData::Element> elements;
5668 UploadData::Element element;
5669 element.SetToFilePath(temp_file);
5670 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535671 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365672
5673 MockRead data_reads[] = {
5674 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5675 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5676 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5677
5678 MockRead("HTTP/1.1 200 OK\r\n"),
5679 MockRead("Content-Length: 0\r\n\r\n"),
5680 MockRead(false, OK),
5681 };
5682 MockWrite data_writes[] = {
5683 MockWrite("POST /upload HTTP/1.1\r\n"
5684 "Host: www.google.com\r\n"
5685 "Connection: keep-alive\r\n"
5686 "Content-Length: 16\r\n\r\n"),
5687 MockWrite(false, temp_file_contents.c_str()),
5688
5689 MockWrite("POST /upload HTTP/1.1\r\n"
5690 "Host: www.google.com\r\n"
5691 "Connection: keep-alive\r\n"
5692 "Content-Length: 16\r\n"
5693 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5694 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5695 MockWrite(false, OK),
5696 };
5697 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5698 arraysize(data_writes));
5699 session_deps.socket_factory.AddSocketDataProvider(&data);
5700
5701 TestCompletionCallback callback1;
5702
[email protected]5a1d7ca2010-04-28 20:12:275703 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365704 EXPECT_EQ(ERR_IO_PENDING, rv);
5705
5706 rv = callback1.WaitForResult();
5707 EXPECT_EQ(OK, rv);
5708
5709 const HttpResponseInfo* response = trans->GetResponseInfo();
5710 EXPECT_TRUE(response != NULL);
5711 EXPECT_TRUE(response->headers != NULL);
5712 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5713
5714 // The password prompt info should have been set in response->auth_challenge.
5715 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5716 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5717 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5718 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5719
5720 // Now make the file unreadable and try again.
5721 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5722
5723 TestCompletionCallback callback2;
5724
[email protected]13c8a092010-07-29 06:15:445725 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365726 EXPECT_EQ(ERR_IO_PENDING, rv);
5727
5728 rv = callback2.WaitForResult();
5729 EXPECT_EQ(OK, rv);
5730
5731 response = trans->GetResponseInfo();
5732 EXPECT_TRUE(response != NULL);
5733 EXPECT_TRUE(response->headers != NULL);
5734 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5735 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5736
5737 file_util::Delete(temp_file, false);
5738}
5739
[email protected]aeefc9e82010-02-19 16:18:275740// Tests that changes to Auth realms are treated like auth rejections.
5741TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5742 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275743
5744 HttpRequestInfo request;
5745 request.method = "GET";
5746 request.url = GURL("http://www.google.com/");
5747 request.load_flags = 0;
5748
5749 // First transaction will request a resource and receive a Basic challenge
5750 // with realm="first_realm".
5751 MockWrite data_writes1[] = {
5752 MockWrite("GET / HTTP/1.1\r\n"
5753 "Host: www.google.com\r\n"
5754 "Connection: keep-alive\r\n"
5755 "\r\n"),
5756 };
5757 MockRead data_reads1[] = {
5758 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5759 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5760 "\r\n"),
5761 };
5762
5763 // After calling trans->RestartWithAuth(), provide an Authentication header
5764 // for first_realm. The server will reject and provide a challenge with
5765 // second_realm.
5766 MockWrite data_writes2[] = {
5767 MockWrite("GET / HTTP/1.1\r\n"
5768 "Host: www.google.com\r\n"
5769 "Connection: keep-alive\r\n"
5770 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5771 "\r\n"),
5772 };
5773 MockRead data_reads2[] = {
5774 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5775 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5776 "\r\n"),
5777 };
5778
5779 // This again fails, and goes back to first_realm. Make sure that the
5780 // entry is removed from cache.
5781 MockWrite data_writes3[] = {
5782 MockWrite("GET / HTTP/1.1\r\n"
5783 "Host: www.google.com\r\n"
5784 "Connection: keep-alive\r\n"
5785 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5786 "\r\n"),
5787 };
5788 MockRead data_reads3[] = {
5789 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5790 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5791 "\r\n"),
5792 };
5793
5794 // Try one last time (with the correct password) and get the resource.
5795 MockWrite data_writes4[] = {
5796 MockWrite("GET / HTTP/1.1\r\n"
5797 "Host: www.google.com\r\n"
5798 "Connection: keep-alive\r\n"
5799 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5800 "\r\n"),
5801 };
5802 MockRead data_reads4[] = {
5803 MockRead("HTTP/1.1 200 OK\r\n"
5804 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:505805 "Content-Length: 5\r\n"
5806 "\r\n"
5807 "hello"),
[email protected]aeefc9e82010-02-19 16:18:275808 };
5809
5810 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5811 data_writes1, arraysize(data_writes1));
5812 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5813 data_writes2, arraysize(data_writes2));
5814 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5815 data_writes3, arraysize(data_writes3));
5816 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5817 data_writes4, arraysize(data_writes4));
5818 session_deps.socket_factory.AddSocketDataProvider(&data1);
5819 session_deps.socket_factory.AddSocketDataProvider(&data2);
5820 session_deps.socket_factory.AddSocketDataProvider(&data3);
5821 session_deps.socket_factory.AddSocketDataProvider(&data4);
5822
5823 TestCompletionCallback callback1;
5824
[email protected]0b0bf032010-09-21 18:08:505825 scoped_ptr<HttpTransaction> trans(
5826 new HttpNetworkTransaction(CreateSession(&session_deps)));
5827
[email protected]aeefc9e82010-02-19 16:18:275828 // Issue the first request with Authorize headers. There should be a
5829 // password prompt for first_realm waiting to be filled in after the
5830 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275831 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275832 EXPECT_EQ(ERR_IO_PENDING, rv);
5833 rv = callback1.WaitForResult();
5834 EXPECT_EQ(OK, rv);
5835 const HttpResponseInfo* response = trans->GetResponseInfo();
5836 ASSERT_FALSE(response == NULL);
5837 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5838 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5839 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5840 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5841
5842 // Issue the second request with an incorrect password. There should be a
5843 // password prompt for second_realm waiting to be filled in after the
5844 // transaction completes.
5845 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445846 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275847 EXPECT_EQ(ERR_IO_PENDING, rv);
5848 rv = callback2.WaitForResult();
5849 EXPECT_EQ(OK, rv);
5850 response = trans->GetResponseInfo();
5851 ASSERT_FALSE(response == NULL);
5852 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5853 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5854 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5855 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5856
5857 // Issue the third request with another incorrect password. There should be
5858 // a password prompt for first_realm waiting to be filled in. If the password
5859 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5860 // first_realm was not correctly removed.
5861 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445862 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275863 EXPECT_EQ(ERR_IO_PENDING, rv);
5864 rv = callback3.WaitForResult();
5865 EXPECT_EQ(OK, rv);
5866 response = trans->GetResponseInfo();
5867 ASSERT_FALSE(response == NULL);
5868 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5869 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5870 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5871 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5872
5873 // Issue the fourth request with the correct password and username.
5874 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445875 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275876 EXPECT_EQ(ERR_IO_PENDING, rv);
5877 rv = callback4.WaitForResult();
5878 EXPECT_EQ(OK, rv);
5879 response = trans->GetResponseInfo();
5880 ASSERT_FALSE(response == NULL);
5881 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5882}
5883
[email protected]564b4912010-03-09 16:30:425884TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385885 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5886 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425887
[email protected]564b4912010-03-09 16:30:425888 SessionDependencies session_deps;
5889
5890 MockRead data_reads[] = {
5891 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355892 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425893 MockRead("hello world"),
5894 MockRead(false, OK),
5895 };
5896
5897 HttpRequestInfo request;
5898 request.method = "GET";
5899 request.url = GURL("http://www.google.com/");
5900 request.load_flags = 0;
5901
5902 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5903
5904 session_deps.socket_factory.AddSocketDataProvider(&data);
5905
5906 TestCompletionCallback callback;
5907
5908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5909 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5910
[email protected]5a1d7ca2010-04-28 20:12:275911 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425912 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535913
[email protected]2fbaecf22010-07-22 22:20:355914 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425915 const HttpAlternateProtocols& alternate_protocols =
5916 session->alternate_protocols();
5917 EXPECT_FALSE(
5918 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5919
5920 EXPECT_EQ(OK, callback.WaitForResult());
5921
5922 const HttpResponseInfo* response = trans->GetResponseInfo();
5923 ASSERT_TRUE(response != NULL);
5924 ASSERT_TRUE(response->headers != NULL);
5925 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535926 EXPECT_FALSE(response->was_fetched_via_spdy);
5927 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575928 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425929
5930 std::string response_data;
5931 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5932 EXPECT_EQ("hello world", response_data);
5933
5934 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5935 const HttpAlternateProtocols::PortProtocolPair alternate =
5936 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5937 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5938 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355939 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425940 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425941
[email protected]8e6441ca2010-08-19 05:56:385942 HttpStreamFactory::set_use_alternate_protocols(false);
5943 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:425944}
5945
5946TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:385947 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:425948 SessionDependencies session_deps;
5949
5950 HttpRequestInfo request;
5951 request.method = "GET";
5952 request.url = GURL("http://www.google.com/");
5953 request.load_flags = 0;
5954
5955 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5956 StaticSocketDataProvider first_data;
5957 first_data.set_connect_data(mock_connect);
5958 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5959
5960 MockRead data_reads[] = {
5961 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5962 MockRead("hello world"),
5963 MockRead(true, OK),
5964 };
5965 StaticSocketDataProvider second_data(
5966 data_reads, arraysize(data_reads), NULL, 0);
5967 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5968
5969 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5970 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5971 // http://crbug.com/37454.
5972 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5973
5974 TestCompletionCallback callback;
5975
5976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5977
[email protected]2fbaecf22010-07-22 22:20:355978 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425979 HttpAlternateProtocols* alternate_protocols =
5980 session->mutable_alternate_protocols();
5981 alternate_protocols->SetAlternateProtocolFor(
5982 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355983 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425984
5985 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5986
[email protected]5a1d7ca2010-04-28 20:12:275987 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425988 EXPECT_EQ(ERR_IO_PENDING, rv);
5989 EXPECT_EQ(OK, callback.WaitForResult());
5990
5991 const HttpResponseInfo* response = trans->GetResponseInfo();
5992 ASSERT_TRUE(response != NULL);
5993 ASSERT_TRUE(response->headers != NULL);
5994 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5995
5996 std::string response_data;
5997 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5998 EXPECT_EQ("hello world", response_data);
5999
6000 ASSERT_TRUE(
6001 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6002 const HttpAlternateProtocols::PortProtocolPair alternate =
6003 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6004 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386005 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426006}
6007
6008// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6009// says that it does SPDY, but it just does the TLS handshake, but the NPN
6010// response does not indicate SPDY, so we just do standard HTTPS over the port.
6011// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6012// on the original port.
[email protected]a2cb8122010-03-10 17:22:426013// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6014// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536015//
[email protected]a2cb8122010-03-10 17:22:426016// HttpRequestInfo request;
6017// request.method = "GET";
6018// request.url = GURL("http://www.google.com/");
6019// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536020//
[email protected]a2cb8122010-03-10 17:22:426021// MockRead data_reads[] = {
6022// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6023// MockRead("hello world"),
6024// MockRead(true, OK),
6025// };
6026// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6027// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536028//
[email protected]a2cb8122010-03-10 17:22:426029// SSLSocketDataProvider ssl(true, OK);
6030// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536031//
[email protected]a2cb8122010-03-10 17:22:426032// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536033//
[email protected]a2cb8122010-03-10 17:22:426034// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536035//
[email protected]a2cb8122010-03-10 17:22:426036// HostPortPair http_host_port_pair;
6037// http_host_port_pair.host = "www.google.com";
6038// http_host_port_pair.port = 80;
6039// HttpAlternateProtocols* alternate_protocols =
6040// session->mutable_alternate_protocols();
6041// alternate_protocols->SetAlternateProtocolFor(
6042// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066043// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536044//
[email protected]a2cb8122010-03-10 17:22:426045// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536046//
[email protected]5a1d7ca2010-04-28 20:12:276047// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426048// EXPECT_EQ(ERR_IO_PENDING, rv);
6049// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536050//
[email protected]a2cb8122010-03-10 17:22:426051// const HttpResponseInfo* response = trans->GetResponseInfo();
6052// ASSERT_TRUE(response != NULL);
6053// ASSERT_TRUE(response->headers != NULL);
6054// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536055//
[email protected]a2cb8122010-03-10 17:22:426056// std::string response_data;
6057// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6058// EXPECT_EQ("hello world", response_data);
6059// }
6060
6061TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386062 HttpStreamFactory::set_use_alternate_protocols(true);
6063 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426064 SessionDependencies session_deps;
6065
6066 HttpRequestInfo request;
6067 request.method = "GET";
6068 request.url = GURL("http://www.google.com/");
6069 request.load_flags = 0;
6070
[email protected]a2cb8122010-03-10 17:22:426071 StaticSocketDataProvider first_tcp_connect;
6072 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6073
6074 SSLSocketDataProvider ssl(true, OK);
6075 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6076
[email protected]564b4912010-03-09 16:30:426077 MockRead data_reads[] = {
6078 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6079 MockRead("hello world"),
6080 MockRead(true, OK),
6081 };
[email protected]a2cb8122010-03-10 17:22:426082 StaticSocketDataProvider fallback_data(
6083 data_reads, arraysize(data_reads), NULL, 0);
6084 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426085
6086 TestCompletionCallback callback;
6087
6088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6089
[email protected]2fbaecf22010-07-22 22:20:356090 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426091 HttpAlternateProtocols* alternate_protocols =
6092 session->mutable_alternate_protocols();
6093 alternate_protocols->SetAlternateProtocolFor(
6094 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356095 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426096
6097 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6098
[email protected]5a1d7ca2010-04-28 20:12:276099 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426100 EXPECT_EQ(ERR_IO_PENDING, rv);
6101 EXPECT_EQ(OK, callback.WaitForResult());
6102
6103 const HttpResponseInfo* response = trans->GetResponseInfo();
6104 ASSERT_TRUE(response != NULL);
6105 ASSERT_TRUE(response->headers != NULL);
6106 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6107
6108 std::string response_data;
6109 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6110 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386111 HttpStreamFactory::set_next_protos("");
6112 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546113}
6114
6115TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386116 HttpStreamFactory::set_use_alternate_protocols(true);
6117 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546118 SessionDependencies session_deps;
6119
6120 HttpRequestInfo request;
6121 request.method = "GET";
6122 request.url = GURL("http://www.google.com/");
6123 request.load_flags = 0;
6124
6125 MockRead data_reads[] = {
6126 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356127 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546128 MockRead("hello world"),
6129 MockRead(true, OK),
6130 };
6131
6132 StaticSocketDataProvider first_transaction(
6133 data_reads, arraysize(data_reads), NULL, 0);
6134 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6135
6136 SSLSocketDataProvider ssl(true, OK);
6137 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356138 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536139 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546140 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6141
[email protected]2bd93022010-07-17 00:58:446142 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136143 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546144
[email protected]2bd93022010-07-17 00:58:446145 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6146 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546147 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136148 CreateMockRead(*resp),
6149 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546150 MockRead(true, 0, 0),
6151 };
6152
6153 scoped_refptr<DelayedSocketData> spdy_data(
6154 new DelayedSocketData(
6155 1, // wait for one write to finish before reading.
6156 spdy_reads, arraysize(spdy_reads),
6157 spdy_writes, arraysize(spdy_writes)));
6158 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6159
6160 TestCompletionCallback callback;
6161
6162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6163 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6164
[email protected]5a1d7ca2010-04-28 20:12:276165 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546166 EXPECT_EQ(ERR_IO_PENDING, rv);
6167 EXPECT_EQ(OK, callback.WaitForResult());
6168
6169 const HttpResponseInfo* response = trans->GetResponseInfo();
6170 ASSERT_TRUE(response != NULL);
6171 ASSERT_TRUE(response->headers != NULL);
6172 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6173
6174 std::string response_data;
6175 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6176 EXPECT_EQ("hello world", response_data);
6177
6178 trans.reset(new HttpNetworkTransaction(session));
6179
[email protected]5a1d7ca2010-04-28 20:12:276180 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546181 EXPECT_EQ(ERR_IO_PENDING, rv);
6182 EXPECT_EQ(OK, callback.WaitForResult());
6183
6184 response = trans->GetResponseInfo();
6185 ASSERT_TRUE(response != NULL);
6186 ASSERT_TRUE(response->headers != NULL);
6187 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536188 EXPECT_TRUE(response->was_fetched_via_spdy);
6189 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576190 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546191
6192 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6193 EXPECT_EQ("hello!", response_data);
6194
[email protected]8e6441ca2010-08-19 05:56:386195 HttpStreamFactory::set_next_protos("");
6196 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546197}
6198
[email protected]631f1322010-04-30 17:59:116199class CapturingProxyResolver : public ProxyResolver {
6200 public:
6201 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6202 virtual ~CapturingProxyResolver() {}
6203
6204 virtual int GetProxyForURL(const GURL& url,
6205 ProxyInfo* results,
6206 CompletionCallback* callback,
6207 RequestHandle* request,
6208 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406209 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6210 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426211 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116212 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426213 return OK;
[email protected]631f1322010-04-30 17:59:116214 }
6215
6216 virtual void CancelRequest(RequestHandle request) {
6217 NOTREACHED();
6218 }
6219
[email protected]24476402010-07-20 20:55:176220 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116221 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426222 return OK;
[email protected]631f1322010-04-30 17:59:116223 }
6224
[email protected]24476402010-07-20 20:55:176225 const std::vector<GURL>& resolved() const { return resolved_; }
6226
6227 private:
[email protected]631f1322010-04-30 17:59:116228 std::vector<GURL> resolved_;
6229
6230 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6231};
6232
[email protected]631f1322010-04-30 17:59:116233TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386234 HttpStreamFactory::set_use_alternate_protocols(true);
6235 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116236
6237 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426238 proxy_config.set_auto_detect(true);
6239 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116240
[email protected]631f1322010-04-30 17:59:116241 CapturingProxyResolver* capturing_proxy_resolver =
6242 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386243 SessionDependencies session_deps(new ProxyService(
6244 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6245 NULL));
[email protected]631f1322010-04-30 17:59:116246
6247 HttpRequestInfo request;
6248 request.method = "GET";
6249 request.url = GURL("http://www.google.com/");
6250 request.load_flags = 0;
6251
6252 MockRead data_reads[] = {
6253 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356254 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116255 MockRead("hello world"),
6256 MockRead(true, OK),
6257 };
6258
6259 StaticSocketDataProvider first_transaction(
6260 data_reads, arraysize(data_reads), NULL, 0);
6261 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6262
6263 SSLSocketDataProvider ssl(true, OK);
6264 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356265 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536266 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116267 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6268
[email protected]2bd93022010-07-17 00:58:446269 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116270 MockWrite spdy_writes[] = {
6271 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6272 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426273 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136274 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116275 };
6276
[email protected]d911f1b2010-05-05 22:39:426277 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6278
[email protected]2bd93022010-07-17 00:58:446279 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6280 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116281 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426282 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136283 CreateMockRead(*resp.get(), 4), // 2, 4
6284 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426285 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116286 };
6287
[email protected]d911f1b2010-05-05 22:39:426288 scoped_refptr<OrderedSocketData> spdy_data(
6289 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116290 spdy_reads, arraysize(spdy_reads),
6291 spdy_writes, arraysize(spdy_writes)));
6292 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6293
6294 TestCompletionCallback callback;
6295
6296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6297 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6298
6299 int rv = trans->Start(&request, &callback, BoundNetLog());
6300 EXPECT_EQ(ERR_IO_PENDING, rv);
6301 EXPECT_EQ(OK, callback.WaitForResult());
6302
6303 const HttpResponseInfo* response = trans->GetResponseInfo();
6304 ASSERT_TRUE(response != NULL);
6305 ASSERT_TRUE(response->headers != NULL);
6306 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536307 EXPECT_FALSE(response->was_fetched_via_spdy);
6308 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116309
6310 std::string response_data;
6311 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6312 EXPECT_EQ("hello world", response_data);
6313
6314 trans.reset(new HttpNetworkTransaction(session));
6315
6316 rv = trans->Start(&request, &callback, BoundNetLog());
6317 EXPECT_EQ(ERR_IO_PENDING, rv);
6318 EXPECT_EQ(OK, callback.WaitForResult());
6319
6320 response = trans->GetResponseInfo();
6321 ASSERT_TRUE(response != NULL);
6322 ASSERT_TRUE(response->headers != NULL);
6323 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536324 EXPECT_TRUE(response->was_fetched_via_spdy);
6325 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116326
6327 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6328 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426329 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6330 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116331 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426332 EXPECT_EQ("https://www.google.com/",
6333 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116334
[email protected]8e6441ca2010-08-19 05:56:386335 HttpStreamFactory::set_next_protos("");
6336 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116337}
[email protected]631f1322010-04-30 17:59:116338
[email protected]2ff8b312010-04-26 22:20:546339TEST_F(HttpNetworkTransactionTest,
6340 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386341 HttpStreamFactory::set_use_alternate_protocols(true);
6342 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546343 SessionDependencies session_deps;
6344
6345 HttpRequestInfo request;
6346 request.method = "GET";
6347 request.url = GURL("http://www.google.com/");
6348 request.load_flags = 0;
6349
6350 MockRead data_reads[] = {
6351 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356352 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546353 MockRead("hello world"),
6354 MockRead(true, OK),
6355 };
6356
6357 StaticSocketDataProvider first_transaction(
6358 data_reads, arraysize(data_reads), NULL, 0);
6359 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6360
6361 SSLSocketDataProvider ssl(true, OK);
6362 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356363 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536364 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546365 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536366 // Make sure we use ssl for spdy here.
6367 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546368
[email protected]2bd93022010-07-17 00:58:446369 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136370 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546371
[email protected]2bd93022010-07-17 00:58:446372 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6373 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546374 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136375 CreateMockRead(*resp),
6376 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546377 MockRead(true, 0, 0),
6378 };
6379
6380 scoped_refptr<DelayedSocketData> spdy_data(
6381 new DelayedSocketData(
6382 1, // wait for one write to finish before reading.
6383 spdy_reads, arraysize(spdy_reads),
6384 spdy_writes, arraysize(spdy_writes)));
6385 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6386
6387 TestCompletionCallback callback;
6388
6389 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6390
6391 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6392
[email protected]5a1d7ca2010-04-28 20:12:276393 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546394 EXPECT_EQ(ERR_IO_PENDING, rv);
6395 EXPECT_EQ(OK, callback.WaitForResult());
6396
6397 const HttpResponseInfo* response = trans->GetResponseInfo();
6398 ASSERT_TRUE(response != NULL);
6399 ASSERT_TRUE(response->headers != NULL);
6400 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6401
6402 std::string response_data;
6403 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6404 EXPECT_EQ("hello world", response_data);
6405
6406 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386407 HostPortPair host_port_pair("www.google.com", 443);
6408 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546409 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276410 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6411 BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:216412 scoped_refptr<TCPSocketParams> tcp_params =
6413 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:386414
6415 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6416 EXPECT_EQ(ERR_IO_PENDING,
6417 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6418 &callback, session->tcp_socket_pool(),
6419 BoundNetLog()));
6420 EXPECT_EQ(OK, callback.WaitForResult());
6421
6422 SSLConfig ssl_config;
6423 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6424 ClientSocket* socket = connection->release_socket();
[email protected]563ee902010-09-27 16:16:176425 socket = session->socket_factory()->CreateSSLClientSocket(socket, "" ,
6426 ssl_config);
[email protected]02b0c342010-09-25 21:09:386427 connection->set_socket(socket);
6428 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6429 EXPECT_EQ(OK, callback.WaitForResult());
6430
6431 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6432 true, OK));
6433
[email protected]2ff8b312010-04-26 22:20:546434 trans.reset(new HttpNetworkTransaction(session));
6435
[email protected]5a1d7ca2010-04-28 20:12:276436 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546437 EXPECT_EQ(ERR_IO_PENDING, rv);
6438 EXPECT_EQ(OK, callback.WaitForResult());
6439
6440 response = trans->GetResponseInfo();
6441 ASSERT_TRUE(response != NULL);
6442 ASSERT_TRUE(response->headers != NULL);
6443 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536444 EXPECT_TRUE(response->was_fetched_via_spdy);
6445 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576446 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546447
6448 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6449 EXPECT_EQ("hello!", response_data);
6450
[email protected]8e6441ca2010-08-19 05:56:386451 HttpStreamFactory::set_next_protos("");
6452 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426453}
6454
[email protected]044de0642010-06-17 10:42:156455// GenerateAuthToken is a mighty big test.
6456// It tests all permutation of GenerateAuthToken behavior:
6457// - Synchronous and Asynchronous completion.
6458// - OK or error on completion.
6459// - Direct connection, non-authenticating proxy, and authenticating proxy.
6460// - HTTP or HTTPS backend (to include proxy tunneling).
6461// - Non-authenticating and authenticating backend.
6462//
6463// In all, there are 44 reasonable permuations (for example, if there are
6464// problems generating an auth token for an authenticating proxy, we don't
6465// need to test all permutations of the backend server).
6466//
6467// The test proceeds by going over each of the configuration cases, and
6468// potentially running up to three rounds in each of the tests. The TestConfig
6469// specifies both the configuration for the test as well as the expectations
6470// for the results.
6471TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506472 static const char kServer[] = "http://www.example.com";
6473 static const char kSecureServer[] = "https://www.example.com";
6474 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156475 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6476
6477 enum AuthTiming {
6478 AUTH_NONE,
6479 AUTH_SYNC,
6480 AUTH_ASYNC,
6481 };
6482
6483 const MockWrite kGet(
6484 "GET / HTTP/1.1\r\n"
6485 "Host: www.example.com\r\n"
6486 "Connection: keep-alive\r\n\r\n");
6487 const MockWrite kGetProxy(
6488 "GET http://www.example.com/ HTTP/1.1\r\n"
6489 "Host: www.example.com\r\n"
6490 "Proxy-Connection: keep-alive\r\n\r\n");
6491 const MockWrite kGetAuth(
6492 "GET / HTTP/1.1\r\n"
6493 "Host: www.example.com\r\n"
6494 "Connection: keep-alive\r\n"
6495 "Authorization: auth_token\r\n\r\n");
6496 const MockWrite kGetProxyAuth(
6497 "GET http://www.example.com/ HTTP/1.1\r\n"
6498 "Host: www.example.com\r\n"
6499 "Proxy-Connection: keep-alive\r\n"
6500 "Proxy-Authorization: auth_token\r\n\r\n");
6501 const MockWrite kGetAuthThroughProxy(
6502 "GET http://www.example.com/ HTTP/1.1\r\n"
6503 "Host: www.example.com\r\n"
6504 "Proxy-Connection: keep-alive\r\n"
6505 "Authorization: auth_token\r\n\r\n");
6506 const MockWrite kGetAuthWithProxyAuth(
6507 "GET http://www.example.com/ HTTP/1.1\r\n"
6508 "Host: www.example.com\r\n"
6509 "Proxy-Connection: keep-alive\r\n"
6510 "Proxy-Authorization: auth_token\r\n"
6511 "Authorization: auth_token\r\n\r\n");
6512 const MockWrite kConnect(
6513 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6514 "Host: www.example.com\r\n"
6515 "Proxy-Connection: keep-alive\r\n\r\n");
6516 const MockWrite kConnectProxyAuth(
6517 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6518 "Host: www.example.com\r\n"
6519 "Proxy-Connection: keep-alive\r\n"
6520 "Proxy-Authorization: auth_token\r\n\r\n");
6521
6522 const MockRead kSuccess(
6523 "HTTP/1.1 200 OK\r\n"
6524 "Content-Type: text/html; charset=iso-8859-1\r\n"
6525 "Content-Length: 3\r\n\r\n"
6526 "Yes");
6527 const MockRead kFailure(
6528 "Should not be called.");
6529 const MockRead kServerChallenge(
6530 "HTTP/1.1 401 Unauthorized\r\n"
6531 "WWW-Authenticate: Mock realm=server\r\n"
6532 "Content-Type: text/html; charset=iso-8859-1\r\n"
6533 "Content-Length: 14\r\n\r\n"
6534 "Unauthorized\r\n");
6535 const MockRead kProxyChallenge(
6536 "HTTP/1.1 407 Unauthorized\r\n"
6537 "Proxy-Authenticate: Mock realm=proxy\r\n"
6538 "Proxy-Connection: close\r\n"
6539 "Content-Type: text/html; charset=iso-8859-1\r\n"
6540 "Content-Length: 14\r\n\r\n"
6541 "Unauthorized\r\n");
6542 const MockRead kProxyConnected(
6543 "HTTP/1.1 200 Connection Established\r\n\r\n");
6544
6545 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6546 // no constructors, but the C++ compiler on Windows warns about
6547 // unspecified data in compound literals. So, moved to using constructors,
6548 // and TestRound's created with the default constructor should not be used.
6549 struct TestRound {
6550 TestRound()
6551 : expected_rv(ERR_UNEXPECTED),
6552 extra_write(NULL),
6553 extra_read(NULL) {
6554 }
6555 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6556 int expected_rv_arg)
6557 : write(write_arg),
6558 read(read_arg),
6559 expected_rv(expected_rv_arg),
6560 extra_write(NULL),
6561 extra_read(NULL) {
6562 }
6563 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6564 int expected_rv_arg, const MockWrite* extra_write_arg,
6565 const MockWrite* extra_read_arg)
6566 : write(write_arg),
6567 read(read_arg),
6568 expected_rv(expected_rv_arg),
6569 extra_write(extra_write_arg),
6570 extra_read(extra_read_arg) {
6571 }
6572 MockWrite write;
6573 MockRead read;
6574 int expected_rv;
6575 const MockWrite* extra_write;
6576 const MockRead* extra_read;
6577 };
6578
6579 static const int kNoSSL = 500;
6580
6581 struct TestConfig {
6582 const char* proxy_url;
6583 AuthTiming proxy_auth_timing;
6584 int proxy_auth_rv;
6585 const char* server_url;
6586 AuthTiming server_auth_timing;
6587 int server_auth_rv;
6588 int num_auth_rounds;
6589 int first_ssl_round;
6590 TestRound rounds[3];
6591 } test_configs[] = {
6592 // Non-authenticating HTTP server with a direct connection.
6593 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6594 { TestRound(kGet, kSuccess, OK)}},
6595 // Authenticating HTTP server with a direct connection.
6596 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6597 { TestRound(kGet, kServerChallenge, OK),
6598 TestRound(kGetAuth, kSuccess, OK)}},
6599 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6600 { TestRound(kGet, kServerChallenge, OK),
6601 TestRound(kGetAuth, kFailure, kAuthErr)}},
6602 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6603 { TestRound(kGet, kServerChallenge, OK),
6604 TestRound(kGetAuth, kSuccess, OK)}},
6605 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6606 { TestRound(kGet, kServerChallenge, OK),
6607 TestRound(kGetAuth, kFailure, kAuthErr)}},
6608 // Non-authenticating HTTP server through a non-authenticating proxy.
6609 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6610 { TestRound(kGetProxy, kSuccess, OK)}},
6611 // Authenticating HTTP server through a non-authenticating proxy.
6612 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6613 { TestRound(kGetProxy, kServerChallenge, OK),
6614 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6615 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6616 { TestRound(kGetProxy, kServerChallenge, OK),
6617 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6618 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6619 { TestRound(kGetProxy, kServerChallenge, OK),
6620 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6621 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6622 { TestRound(kGetProxy, kServerChallenge, OK),
6623 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6624 // Non-authenticating HTTP server through an authenticating proxy.
6625 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6626 { TestRound(kGetProxy, kProxyChallenge, OK),
6627 TestRound(kGetProxyAuth, kSuccess, OK)}},
6628 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6629 { TestRound(kGetProxy, kProxyChallenge, OK),
6630 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6631 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6632 { TestRound(kGetProxy, kProxyChallenge, OK),
6633 TestRound(kGetProxyAuth, kSuccess, OK)}},
6634 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6635 { TestRound(kGetProxy, kProxyChallenge, OK),
6636 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6637 // Authenticating HTTP server through an authenticating proxy.
6638 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6639 { TestRound(kGetProxy, kProxyChallenge, OK),
6640 TestRound(kGetProxyAuth, kServerChallenge, OK),
6641 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6642 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6643 { TestRound(kGetProxy, kProxyChallenge, OK),
6644 TestRound(kGetProxyAuth, kServerChallenge, OK),
6645 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6646 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6647 { TestRound(kGetProxy, kProxyChallenge, OK),
6648 TestRound(kGetProxyAuth, kServerChallenge, OK),
6649 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6650 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6651 { TestRound(kGetProxy, kProxyChallenge, OK),
6652 TestRound(kGetProxyAuth, kServerChallenge, OK),
6653 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6654 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6655 { TestRound(kGetProxy, kProxyChallenge, OK),
6656 TestRound(kGetProxyAuth, kServerChallenge, OK),
6657 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6658 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6659 { TestRound(kGetProxy, kProxyChallenge, OK),
6660 TestRound(kGetProxyAuth, kServerChallenge, OK),
6661 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6662 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6663 { TestRound(kGetProxy, kProxyChallenge, OK),
6664 TestRound(kGetProxyAuth, kServerChallenge, OK),
6665 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6666 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6667 { TestRound(kGetProxy, kProxyChallenge, OK),
6668 TestRound(kGetProxyAuth, kServerChallenge, OK),
6669 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6670 // Non-authenticating HTTPS server with a direct connection.
6671 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6672 { TestRound(kGet, kSuccess, OK)}},
6673 // Authenticating HTTPS server with a direct connection.
6674 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6675 { TestRound(kGet, kServerChallenge, OK),
6676 TestRound(kGetAuth, kSuccess, OK)}},
6677 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6678 { TestRound(kGet, kServerChallenge, OK),
6679 TestRound(kGetAuth, kFailure, kAuthErr)}},
6680 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6681 { TestRound(kGet, kServerChallenge, OK),
6682 TestRound(kGetAuth, kSuccess, OK)}},
6683 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6684 { TestRound(kGet, kServerChallenge, OK),
6685 TestRound(kGetAuth, kFailure, kAuthErr)}},
6686 // Non-authenticating HTTPS server with a non-authenticating proxy.
6687 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6688 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6689 // Authenticating HTTPS server through a non-authenticating proxy.
6690 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6691 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6692 TestRound(kGetAuth, kSuccess, OK)}},
6693 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6694 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6695 TestRound(kGetAuth, kFailure, kAuthErr)}},
6696 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6697 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6698 TestRound(kGetAuth, kSuccess, OK)}},
6699 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6700 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6701 TestRound(kGetAuth, kFailure, kAuthErr)}},
6702 // Non-Authenticating HTTPS server through an authenticating proxy.
6703 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6704 { TestRound(kConnect, kProxyChallenge, OK),
6705 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6706 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6707 { TestRound(kConnect, kProxyChallenge, OK),
6708 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6709 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6710 { TestRound(kConnect, kProxyChallenge, OK),
6711 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6712 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6713 { TestRound(kConnect, kProxyChallenge, OK),
6714 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6715 // Authenticating HTTPS server through an authenticating proxy.
6716 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6717 { TestRound(kConnect, kProxyChallenge, OK),
6718 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6719 &kGet, &kServerChallenge),
6720 TestRound(kGetAuth, kSuccess, OK)}},
6721 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6722 { TestRound(kConnect, kProxyChallenge, OK),
6723 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6724 &kGet, &kServerChallenge),
6725 TestRound(kGetAuth, kFailure, kAuthErr)}},
6726 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6727 { TestRound(kConnect, kProxyChallenge, OK),
6728 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6729 &kGet, &kServerChallenge),
6730 TestRound(kGetAuth, kSuccess, OK)}},
6731 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6732 { TestRound(kConnect, kProxyChallenge, OK),
6733 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6734 &kGet, &kServerChallenge),
6735 TestRound(kGetAuth, kFailure, kAuthErr)}},
6736 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6737 { TestRound(kConnect, kProxyChallenge, OK),
6738 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6739 &kGet, &kServerChallenge),
6740 TestRound(kGetAuth, kSuccess, OK)}},
6741 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6742 { TestRound(kConnect, kProxyChallenge, OK),
6743 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6744 &kGet, &kServerChallenge),
6745 TestRound(kGetAuth, kFailure, kAuthErr)}},
6746 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6747 { TestRound(kConnect, kProxyChallenge, OK),
6748 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6749 &kGet, &kServerChallenge),
6750 TestRound(kGetAuth, kSuccess, OK)}},
6751 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6752 { TestRound(kConnect, kProxyChallenge, OK),
6753 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6754 &kGet, &kServerChallenge),
6755 TestRound(kGetAuth, kFailure, kAuthErr)}},
6756 };
6757
6758 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:006759 HttpAuthHandlerMock::Factory* auth_factory(
6760 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156761 session_deps.http_auth_handler_factory.reset(auth_factory);
6762
6763 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6764 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266765
6766 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156767 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006768 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156769 std::string auth_challenge = "Mock realm=proxy";
6770 GURL origin(test_config.proxy_url);
6771 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6772 auth_challenge.end());
6773 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6774 origin, BoundNetLog());
6775 auth_handler->SetGenerateExpectation(
6776 test_config.proxy_auth_timing == AUTH_ASYNC,
6777 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156778 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6779 }
6780 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006781 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156782 std::string auth_challenge = "Mock realm=server";
6783 GURL origin(test_config.server_url);
6784 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6785 auth_challenge.end());
6786 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6787 origin, BoundNetLog());
6788 auth_handler->SetGenerateExpectation(
6789 test_config.server_auth_timing == AUTH_ASYNC,
6790 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156791 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6792 }
6793 if (test_config.proxy_url) {
6794 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:006795 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:156796 } else {
[email protected]ebeefff32010-09-15 05:10:026797 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:156798 }
6799
6800 HttpRequestInfo request;
6801 request.method = "GET";
6802 request.url = GURL(test_config.server_url);
6803 request.load_flags = 0;
6804
[email protected]0b0bf032010-09-21 18:08:506805 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6806 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:156807
6808 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6809 const TestRound& read_write_round = test_config.rounds[round];
6810
6811 // Set up expected reads and writes.
6812 MockRead reads[2];
6813 reads[0] = read_write_round.read;
6814 size_t length_reads = 1;
6815 if (read_write_round.extra_read) {
6816 reads[1] = *read_write_round.extra_read;
6817 length_reads = 2;
6818 }
6819
6820 MockWrite writes[2];
6821 writes[0] = read_write_round.write;
6822 size_t length_writes = 1;
6823 if (read_write_round.extra_write) {
6824 writes[1] = *read_write_round.extra_write;
6825 length_writes = 2;
6826 }
6827 StaticSocketDataProvider data_provider(
6828 reads, length_reads, writes, length_writes);
6829 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6830
6831 // Add an SSL sequence if necessary.
6832 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6833 if (round >= test_config.first_ssl_round)
6834 session_deps.socket_factory.AddSSLSocketDataProvider(
6835 &ssl_socket_data_provider);
6836
6837 // Start or restart the transaction.
6838 TestCompletionCallback callback;
6839 int rv;
6840 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:506841 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:156842 } else {
[email protected]0b0bf032010-09-21 18:08:506843 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156844 }
6845 if (rv == ERR_IO_PENDING)
6846 rv = callback.WaitForResult();
6847
6848 // Compare results with expected data.
6849 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:506850 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:156851 if (read_write_round.expected_rv == OK) {
6852 EXPECT_FALSE(response == NULL);
6853 } else {
6854 EXPECT_TRUE(response == NULL);
6855 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6856 continue;
6857 }
6858 if (round + 1 < test_config.num_auth_rounds) {
6859 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6860 } else {
6861 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6862 }
6863 }
[email protected]e5ae96a2010-04-14 20:12:456864 }
6865}
6866
[email protected]c871bce92010-07-15 21:51:146867TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6868 // Do multi-round authentication and make sure it works correctly.
6869 SessionDependencies session_deps;
6870 HttpAuthHandlerMock::Factory* auth_factory(
6871 new HttpAuthHandlerMock::Factory());
6872 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:026873 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:146874 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6875 session_deps.host_resolver->set_synchronous_mode(true);
6876
6877 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6878 auth_handler->set_connection_based(true);
6879 std::string auth_challenge = "Mock realm=server";
6880 GURL origin("http://www.example.com");
6881 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6882 auth_challenge.end());
6883 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6884 origin, BoundNetLog());
6885 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6886
6887 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6888 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6889
6890 int rv = OK;
6891 const HttpResponseInfo* response = NULL;
6892 HttpRequestInfo request;
6893 request.method = "GET";
6894 request.url = origin;
6895 request.load_flags = 0;
6896 TestCompletionCallback callback;
6897
6898 const MockWrite kGet(
6899 "GET / HTTP/1.1\r\n"
6900 "Host: www.example.com\r\n"
6901 "Connection: keep-alive\r\n\r\n");
6902 const MockWrite kGetAuth(
6903 "GET / HTTP/1.1\r\n"
6904 "Host: www.example.com\r\n"
6905 "Connection: keep-alive\r\n"
6906 "Authorization: auth_token\r\n\r\n");
6907
6908 const MockRead kServerChallenge(
6909 "HTTP/1.1 401 Unauthorized\r\n"
6910 "WWW-Authenticate: Mock realm=server\r\n"
6911 "Content-Type: text/html; charset=iso-8859-1\r\n"
6912 "Content-Length: 14\r\n\r\n"
6913 "Unauthorized\r\n");
6914 const MockRead kSuccess(
6915 "HTTP/1.1 200 OK\r\n"
6916 "Content-Type: text/html; charset=iso-8859-1\r\n"
6917 "Content-Length: 3\r\n\r\n"
6918 "Yes");
6919
6920 MockWrite writes[] = {
6921 // First round
6922 kGet,
6923 // Second round
6924 kGetAuth,
6925 // Third round
6926 kGetAuth,
[email protected]eca50e122010-09-11 14:03:306927 // Fourth round
6928 kGetAuth
[email protected]c871bce92010-07-15 21:51:146929 };
6930 MockRead reads[] = {
6931 // First round
6932 kServerChallenge,
6933 // Second round
6934 kServerChallenge,
6935 // Third round
[email protected]eca50e122010-09-11 14:03:306936 kServerChallenge,
6937 // Fourth round
[email protected]c871bce92010-07-15 21:51:146938 kSuccess,
6939 };
6940 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6941 writes, arraysize(writes));
6942 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6943
6944 // First round
6945 auth_handler->SetGenerateExpectation(false, OK);
6946 rv = trans->Start(&request, &callback, BoundNetLog());
6947 if (rv == ERR_IO_PENDING)
6948 rv = callback.WaitForResult();
6949 EXPECT_EQ(OK, rv);
6950 response = trans->GetResponseInfo();
6951 ASSERT_FALSE(response == NULL);
6952 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6953
6954 // Second round
6955 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446956 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146957 if (rv == ERR_IO_PENDING)
6958 rv = callback.WaitForResult();
6959 EXPECT_EQ(OK, rv);
6960 response = trans->GetResponseInfo();
6961 ASSERT_FALSE(response == NULL);
6962 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6963
6964 // Third round
6965 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446966 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146967 if (rv == ERR_IO_PENDING)
6968 rv = callback.WaitForResult();
6969 EXPECT_EQ(OK, rv);
6970 response = trans->GetResponseInfo();
6971 ASSERT_FALSE(response == NULL);
6972 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:306973
6974 // Fourth round
6975 auth_handler->SetGenerateExpectation(false, OK);
6976 rv = trans->RestartWithAuth(string16(), string16(), &callback);
6977 if (rv == ERR_IO_PENDING)
6978 rv = callback.WaitForResult();
6979 EXPECT_EQ(OK, rv);
6980 response = trans->GetResponseInfo();
6981 ASSERT_FALSE(response == NULL);
6982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:146983}
6984
[email protected]aeaca1f2010-04-20 22:05:216985class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6986 public:
[email protected]06650c52010-06-03 00:49:176987 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216988 : fail_all_(fail_all) {
6989 }
6990
6991 virtual MockRead GetNextRead() {
6992 if (fail_all_)
6993 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6994
6995 return MockRead(false /* async */,
6996 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6997 }
6998
6999 virtual MockWriteResult OnWrite(const std::string& data) {
7000 return MockWriteResult(false /* async */, data.size());
7001 }
7002
7003 void Reset() {
7004 }
7005
7006 private:
7007 const bool fail_all_;
7008};
7009
7010// Test that we restart a connection when we see a decompression failure from
7011// the peer during the handshake. (In the real world we'll restart with SSLv3
7012// and we won't offer DEFLATE in that case.)
7013TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7014 HttpRequestInfo request;
7015 request.method = "GET";
7016 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7017 request.load_flags = 0;
7018
7019 SessionDependencies session_deps;
7020 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7021 false /* fail all reads */);
7022 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7023 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117024 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217025 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7026 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7027 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7028 session_deps.socket_factory.AddSSLSocketDataProvider(
7029 &ssl_socket_data_provider1);
7030 session_deps.socket_factory.AddSSLSocketDataProvider(
7031 &ssl_socket_data_provider2);
7032
[email protected]e60e47a2010-07-14 03:37:187033 // Work around http://crbug.com/37454
7034 StaticSocketDataProvider bug37454_connection;
7035 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7036 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7037
[email protected]aeaca1f2010-04-20 22:05:217038 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7039 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7040 TestCompletionCallback callback;
7041
[email protected]5a1d7ca2010-04-28 20:12:277042 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217043 EXPECT_EQ(ERR_IO_PENDING, rv);
7044 EXPECT_EQ(OK, callback.WaitForResult());
7045
7046 const HttpResponseInfo* response = trans->GetResponseInfo();
7047 ASSERT_TRUE(response != NULL);
7048 ASSERT_TRUE(response->headers != NULL);
7049 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7050
7051 std::string response_data;
7052 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7053 EXPECT_EQ("ok.", response_data);
7054}
7055
7056// Test that we restart a connection if we get a decompression failure from the
7057// peer while reading the first bytes from the connection. This occurs when the
7058// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7059// in the handshake.
7060TEST_F(HttpNetworkTransactionTest,
7061 RestartAfterTLSDecompressionFailureWithFalseStart) {
7062 HttpRequestInfo request;
7063 request.method = "GET";
7064 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7065 request.load_flags = 0;
7066
7067 SessionDependencies session_deps;
7068 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7069 true /* fail all reads */);
7070 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7071 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7072 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7073 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7074 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7075 session_deps.socket_factory.AddSSLSocketDataProvider(
7076 &ssl_socket_data_provider1);
7077 session_deps.socket_factory.AddSSLSocketDataProvider(
7078 &ssl_socket_data_provider2);
7079
7080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7081 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7082 TestCompletionCallback callback;
7083
[email protected]5a1d7ca2010-04-28 20:12:277084 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217085 EXPECT_EQ(ERR_IO_PENDING, rv);
7086 EXPECT_EQ(OK, callback.WaitForResult());
7087
7088 const HttpResponseInfo* response = trans->GetResponseInfo();
7089 ASSERT_TRUE(response != NULL);
7090 ASSERT_TRUE(response->headers != NULL);
7091 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7092
7093 std::string response_data;
7094 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7095 EXPECT_EQ("ok.", response_data);
7096}
7097
[email protected]65041fa2010-05-21 06:56:537098// This tests the case that a request is issued via http instead of spdy after
7099// npn is negotiated.
7100TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387101 HttpStreamFactory::set_use_alternate_protocols(true);
7102 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537103 SessionDependencies session_deps;
7104 HttpRequestInfo request;
7105 request.method = "GET";
7106 request.url = GURL("https://www.google.com/");
7107 request.load_flags = 0;
7108
7109 MockWrite data_writes[] = {
7110 MockWrite("GET / HTTP/1.1\r\n"
7111 "Host: www.google.com\r\n"
7112 "Connection: keep-alive\r\n\r\n"),
7113 };
7114
7115 MockRead data_reads[] = {
7116 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357117 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537118 MockRead("hello world"),
7119 MockRead(false, OK),
7120 };
7121
7122 SSLSocketDataProvider ssl(true, OK);
7123 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7124 ssl.next_proto = "http/1.1";
7125
7126 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7127
7128 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7129 data_writes, arraysize(data_writes));
7130 session_deps.socket_factory.AddSocketDataProvider(&data);
7131
7132 TestCompletionCallback callback;
7133
7134 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7135 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7136
7137 int rv = trans->Start(&request, &callback, BoundNetLog());
7138
7139 EXPECT_EQ(ERR_IO_PENDING, rv);
7140 EXPECT_EQ(OK, callback.WaitForResult());
7141
7142 const HttpResponseInfo* response = trans->GetResponseInfo();
7143 ASSERT_TRUE(response != NULL);
7144 ASSERT_TRUE(response->headers != NULL);
7145 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7146
7147 std::string response_data;
7148 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7149 EXPECT_EQ("hello world", response_data);
7150
7151 EXPECT_FALSE(response->was_fetched_via_spdy);
7152 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577153 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537154
[email protected]8e6441ca2010-08-19 05:56:387155 HttpStreamFactory::set_next_protos("");
7156 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537157}
[email protected]26ef6582010-06-24 02:30:477158
7159TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7160 // Simulate the SSL handshake completing with an NPN negotiation
7161 // followed by an immediate server closing of the socket.
7162 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387163 HttpStreamFactory::set_use_alternate_protocols(true);
7164 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477165 SessionDependencies session_deps;
7166
7167 HttpRequestInfo request;
7168 request.method = "GET";
7169 request.url = GURL("https://www.google.com/");
7170 request.load_flags = 0;
7171
7172 SSLSocketDataProvider ssl(true, OK);
7173 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357174 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477175 ssl.was_npn_negotiated = true;
7176 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7177
[email protected]2bd93022010-07-17 00:58:447178 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137179 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477180
7181 MockRead spdy_reads[] = {
7182 MockRead(false, 0, 0) // Not async - return 0 immediately.
7183 };
7184
7185 scoped_refptr<DelayedSocketData> spdy_data(
7186 new DelayedSocketData(
7187 0, // don't wait in this case, immediate hangup.
7188 spdy_reads, arraysize(spdy_reads),
7189 spdy_writes, arraysize(spdy_writes)));
7190 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7191
7192 TestCompletionCallback callback;
7193
7194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7195 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7196
7197 int rv = trans->Start(&request, &callback, BoundNetLog());
7198 EXPECT_EQ(ERR_IO_PENDING, rv);
7199 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7200
[email protected]8e6441ca2010-08-19 05:56:387201 HttpStreamFactory::set_next_protos("");
7202 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477203}
[email protected]65d34382010-07-01 18:12:267204
[email protected]f45c1ee2010-08-03 00:54:307205TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7206 // This test ensures that the URL passed into the proxy is upgraded
7207 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387208 HttpStreamFactory::set_use_alternate_protocols(true);
7209 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307210 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7211
[email protected]81cdfcd2010-10-16 00:49:007212 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307213 HttpAuthHandlerMock::Factory* auth_factory =
7214 new HttpAuthHandlerMock::Factory();
7215 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7216 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7217 auth_factory->set_do_init_from_challenge(true);
7218 session_deps.http_auth_handler_factory.reset(auth_factory);
7219
7220 HttpRequestInfo request;
7221 request.method = "GET";
7222 request.url = GURL("http://www.google.com");
7223 request.load_flags = 0;
7224
7225 // First round goes unauthenticated through the proxy.
7226 MockWrite data_writes_1[] = {
7227 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7228 "Host: www.google.com\r\n"
7229 "Proxy-Connection: keep-alive\r\n"
7230 "\r\n"),
7231 };
7232 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597233 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307234 MockRead("HTTP/1.1 200 OK\r\n"
7235 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7236 "Proxy-Connection: close\r\n"
7237 "\r\n"),
7238 };
7239 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7240 data_writes_1, arraysize(data_writes_1));
7241
7242 // Second round tries to tunnel to www.google.com due to the
7243 // Alternate-Protocol announcement in the first round. It fails due
7244 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597245 // After the failure, a tunnel is established to www.google.com using
7246 // Proxy-Authorization headers. There is then a SPDY request round.
7247 //
7248 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7249 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7250 // does a Disconnect and Connect on the same socket, rather than trying
7251 // to obtain a new one.
7252 //
7253 // NOTE: Originally, the proxy response to the second CONNECT request
7254 // simply returned another 407 so the unit test could skip the SSL connection
7255 // establishment and SPDY framing issues. Alas, the
7256 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307257 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597258
[email protected]f45c1ee2010-08-03 00:54:307259 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7260 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7261 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7262
[email protected]394816e92010-08-03 07:38:597263 MockWrite data_writes_2[] = {
7264 // First connection attempt without Proxy-Authorization.
7265 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7266 "Host: www.google.com\r\n"
7267 "Proxy-Connection: keep-alive\r\n"
7268 "\r\n"),
7269
7270 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307271 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7272 "Host: www.google.com\r\n"
7273 "Proxy-Connection: keep-alive\r\n"
7274 "Proxy-Authorization: auth_token\r\n"
7275 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307276
[email protected]394816e92010-08-03 07:38:597277 // SPDY request
7278 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307279 };
[email protected]394816e92010-08-03 07:38:597280 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7281 "Proxy-Authenticate: Mock\r\n"
7282 "Proxy-Connection: close\r\n"
7283 "\r\n");
7284 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7285 MockRead data_reads_2[] = {
7286 // First connection attempt fails
7287 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7288 MockRead(true, kRejectConnectResponse,
7289 arraysize(kRejectConnectResponse) - 1, 1),
7290
7291 // Second connection attempt passes
7292 MockRead(true, kAcceptConnectResponse,
7293 arraysize(kAcceptConnectResponse) -1, 4),
7294
7295 // SPDY response
7296 CreateMockRead(*resp.get(), 6),
7297 CreateMockRead(*data.get(), 6),
7298 MockRead(true, 0, 0, 6),
7299 };
7300 scoped_refptr<OrderedSocketData> data_2(
7301 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7302 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307303
7304 SSLSocketDataProvider ssl(true, OK);
7305 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7306 ssl.next_proto = "spdy/2";
7307 ssl.was_npn_negotiated = true;
7308
7309 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597310 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307311 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7313
7314 // First round should work and provide the Alternate-Protocol state.
7315 TestCompletionCallback callback_1;
7316 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7317 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7318 EXPECT_EQ(ERR_IO_PENDING, rv);
7319 EXPECT_EQ(OK, callback_1.WaitForResult());
7320
7321 // Second round should attempt a tunnel connect and get an auth challenge.
7322 TestCompletionCallback callback_2;
7323 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7324 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7325 EXPECT_EQ(ERR_IO_PENDING, rv);
7326 EXPECT_EQ(OK, callback_2.WaitForResult());
7327 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7328 ASSERT_FALSE(response == NULL);
7329 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7330
7331 // Restart with auth. Tunnel should work and response received.
7332 TestCompletionCallback callback_3;
7333 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7334 EXPECT_EQ(ERR_IO_PENDING, rv);
7335 EXPECT_EQ(OK, callback_3.WaitForResult());
7336
7337 // After all that work, these two lines (or actually, just the scheme) are
7338 // what this test is all about. Make sure it happens correctly.
7339 const GURL& request_url = auth_handler->request_url();
7340 EXPECT_EQ("https", request_url.scheme());
7341 EXPECT_EQ("www.google.com", request_url.host());
7342
[email protected]8e6441ca2010-08-19 05:56:387343 HttpStreamFactory::set_next_protos("");
7344 HttpStreamFactory::set_use_alternate_protocols(false);
7345}
7346
7347// Test that if we cancel the transaction as the connection is completing, that
7348// everything tears down correctly.
7349TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7350 // Setup everything about the connection to complete synchronously, so that
7351 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7352 // for is the callback from the HttpStreamRequest.
7353 // Then cancel the transaction.
7354 // Verify that we don't crash.
7355 MockConnect mock_connect(false, OK);
7356 MockRead data_reads[] = {
7357 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7358 MockRead(false, "hello world"),
7359 MockRead(false, OK),
7360 };
7361
7362 SessionDependencies session_deps;
7363 session_deps.host_resolver->set_synchronous_mode(true);
7364 scoped_ptr<HttpTransaction> trans(
7365 new HttpNetworkTransaction(CreateSession(&session_deps)));
7366
7367 HttpRequestInfo request;
7368 request.method = "GET";
7369 request.url = GURL("http://www.google.com/");
7370 request.load_flags = 0;
7371
7372 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7373 data.set_connect_data(mock_connect);
7374 session_deps.socket_factory.AddSocketDataProvider(&data);
7375
7376 TestCompletionCallback callback;
7377
7378 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7379 int rv = trans->Start(&request, &callback, log.bound());
7380 EXPECT_EQ(ERR_IO_PENDING, rv);
7381 trans.reset(); // Cancel the transaction here.
7382
7383 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307384}
7385
[email protected]76a505b2010-08-25 06:23:007386// Test a basic GET request through a proxy.
7387TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007388 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007389 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7390 session_deps.net_log = log.bound().net_log();
7391 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7392
[email protected]76a505b2010-08-25 06:23:007393 HttpRequestInfo request;
7394 request.method = "GET";
7395 request.url = GURL("http://www.google.com/");
7396
7397 MockWrite data_writes1[] = {
7398 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7399 "Host: www.google.com\r\n"
7400 "Proxy-Connection: keep-alive\r\n\r\n"),
7401 };
7402
7403 MockRead data_reads1[] = {
7404 MockRead("HTTP/1.1 200 OK\r\n"),
7405 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7406 MockRead("Content-Length: 100\r\n\r\n"),
7407 MockRead(false, OK),
7408 };
7409
7410 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7411 data_writes1, arraysize(data_writes1));
7412 session_deps.socket_factory.AddSocketDataProvider(&data1);
7413
7414 TestCompletionCallback callback1;
7415
[email protected]0b0bf032010-09-21 18:08:507416 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7417
[email protected]76a505b2010-08-25 06:23:007418 int rv = trans->Start(&request, &callback1, log.bound());
7419 EXPECT_EQ(ERR_IO_PENDING, rv);
7420
7421 rv = callback1.WaitForResult();
7422 EXPECT_EQ(OK, rv);
7423
7424 const HttpResponseInfo* response = trans->GetResponseInfo();
7425 ASSERT_FALSE(response == NULL);
7426
7427 EXPECT_TRUE(response->headers->IsKeepAlive());
7428 EXPECT_EQ(200, response->headers->response_code());
7429 EXPECT_EQ(100, response->headers->GetContentLength());
7430 EXPECT_TRUE(response->was_fetched_via_proxy);
7431 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7432}
7433
7434// Test a basic HTTPS GET request through a proxy.
7435TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007436 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007437 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7438 session_deps.net_log = log.bound().net_log();
7439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7440
[email protected]76a505b2010-08-25 06:23:007441 HttpRequestInfo request;
7442 request.method = "GET";
7443 request.url = GURL("https://www.google.com/");
7444
7445 // Since we have proxy, should try to establish tunnel.
7446 MockWrite data_writes1[] = {
7447 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7448 "Host: www.google.com\r\n"
7449 "Proxy-Connection: keep-alive\r\n\r\n"),
7450
7451 MockWrite("GET / HTTP/1.1\r\n"
7452 "Host: www.google.com\r\n"
7453 "Connection: keep-alive\r\n\r\n"),
7454 };
7455
7456 MockRead data_reads1[] = {
7457 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7458
7459 MockRead("HTTP/1.1 200 OK\r\n"),
7460 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7461 MockRead("Content-Length: 100\r\n\r\n"),
7462 MockRead(false, OK),
7463 };
7464
7465 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7466 data_writes1, arraysize(data_writes1));
7467 session_deps.socket_factory.AddSocketDataProvider(&data1);
7468 SSLSocketDataProvider ssl(true, OK);
7469 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7470
7471 TestCompletionCallback callback1;
7472
[email protected]0b0bf032010-09-21 18:08:507473 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7474
[email protected]76a505b2010-08-25 06:23:007475 int rv = trans->Start(&request, &callback1, log.bound());
7476 EXPECT_EQ(ERR_IO_PENDING, rv);
7477
7478 rv = callback1.WaitForResult();
7479 EXPECT_EQ(OK, rv);
7480 size_t pos = ExpectLogContainsSomewhere(
7481 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7482 NetLog::PHASE_NONE);
7483 ExpectLogContainsSomewhere(
7484 log.entries(), pos,
7485 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7486 NetLog::PHASE_NONE);
7487
7488 const HttpResponseInfo* response = trans->GetResponseInfo();
7489 ASSERT_FALSE(response == NULL);
7490
7491 EXPECT_TRUE(response->headers->IsKeepAlive());
7492 EXPECT_EQ(200, response->headers->response_code());
7493 EXPECT_EQ(100, response->headers->GetContentLength());
7494 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7495 EXPECT_TRUE(response->was_fetched_via_proxy);
7496}
7497
7498// Test a basic HTTPS GET request through a proxy, but the server hangs up
7499// while establishing the tunnel.
7500TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:007501 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007502 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7503 session_deps.net_log = log.bound().net_log();
7504 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7505
[email protected]76a505b2010-08-25 06:23:007506 HttpRequestInfo request;
7507 request.method = "GET";
7508 request.url = GURL("https://www.google.com/");
7509
7510 // Since we have proxy, should try to establish tunnel.
7511 MockWrite data_writes1[] = {
7512 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7513 "Host: www.google.com\r\n"
7514 "Proxy-Connection: keep-alive\r\n\r\n"),
7515
7516 MockWrite("GET / HTTP/1.1\r\n"
7517 "Host: www.google.com\r\n"
7518 "Connection: keep-alive\r\n\r\n"),
7519 };
7520
7521 MockRead data_reads1[] = {
7522 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7523 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7524 MockRead(true, 0, 0), // EOF
7525 };
7526
7527 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7528 data_writes1, arraysize(data_writes1));
7529 session_deps.socket_factory.AddSocketDataProvider(&data1);
7530 SSLSocketDataProvider ssl(true, OK);
7531 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7532
7533 TestCompletionCallback callback1;
7534
[email protected]0b0bf032010-09-21 18:08:507535 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7536
[email protected]76a505b2010-08-25 06:23:007537 int rv = trans->Start(&request, &callback1, log.bound());
7538 EXPECT_EQ(ERR_IO_PENDING, rv);
7539
7540 rv = callback1.WaitForResult();
7541 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7542 size_t pos = ExpectLogContainsSomewhere(
7543 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7544 NetLog::PHASE_NONE);
7545 ExpectLogContainsSomewhere(
7546 log.entries(), pos,
7547 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7548 NetLog::PHASE_NONE);
7549}
7550
[email protected]749eefa82010-09-13 22:14:037551// Test for crbug.com/55424.
7552TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7553 SessionDependencies session_deps;
7554
7555 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7556 "https://www.google.com", false, 1, LOWEST));
7557 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7558
7559 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7560 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7561 MockRead spdy_reads[] = {
7562 CreateMockRead(*resp),
7563 CreateMockRead(*data),
7564 MockRead(true, 0, 0),
7565 };
7566
7567 scoped_refptr<DelayedSocketData> spdy_data(
7568 new DelayedSocketData(
7569 1, // wait for one write to finish before reading.
7570 spdy_reads, arraysize(spdy_reads),
7571 spdy_writes, arraysize(spdy_writes)));
7572 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7573
7574 SSLSocketDataProvider ssl(true, OK);
7575 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7576 ssl.next_proto = "spdy/2";
7577 ssl.was_npn_negotiated = true;
7578 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7579
7580 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7581
7582 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387583 HostPortPair host_port_pair("www.google.com", 443);
7584 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037585 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277586 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7587 BoundNetLog());
[email protected]749eefa82010-09-13 22:14:037588 scoped_refptr<TCPSocketParams> tcp_params =
7589 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:387590 TestCompletionCallback callback;
7591
7592 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7593 EXPECT_EQ(ERR_IO_PENDING,
7594 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7595 &callback, session->tcp_socket_pool(),
7596 BoundNetLog()));
7597 EXPECT_EQ(OK, callback.WaitForResult());
7598 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037599
7600 HttpRequestInfo request;
7601 request.method = "GET";
7602 request.url = GURL("https://www.google.com/");
7603 request.load_flags = 0;
7604
7605 // This is the important line that marks this as a preconnect.
7606 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7607
7608 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7609
[email protected]749eefa82010-09-13 22:14:037610 int rv = trans->Start(&request, &callback, BoundNetLog());
7611 EXPECT_EQ(ERR_IO_PENDING, rv);
7612 EXPECT_EQ(OK, callback.WaitForResult());
7613}
7614
[email protected]7ec5b392010-10-08 00:38:197615
7616TEST_F(HttpNetworkTransactionTest, DoNotCreateSpdySessionForHttp) {
7617 HttpStreamFactory::set_create_new_spdy_session_for_http(false);
7618 HttpStreamFactory::set_use_alternate_protocols(true);
7619 HttpStreamFactory::set_next_protos(kExpectedNPNString);
7620
7621 SessionDependencies session_deps;
7622 HttpRequestInfo request;
7623 request.method = "GET";
7624 request.url = GURL("http://www.google.com/");
7625 request.load_flags = 0;
7626
7627 MockRead data_reads[] = {
7628 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
7629 MockRead("hello world"),
7630 MockRead(true, OK),
7631 };
7632 StaticSocketDataProvider data(
7633 data_reads, arraysize(data_reads), NULL, 0);
7634 session_deps.socket_factory.AddSocketDataProvider(&data);
7635
7636 TestCompletionCallback callback;
7637
7638 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7639
7640 HostPortPair http_host_port_pair("www.google.com", 80);
7641 HttpAlternateProtocols* alternate_protocols =
7642 session->mutable_alternate_protocols();
7643 alternate_protocols->SetAlternateProtocolFor(
7644 http_host_port_pair, 443 /* port is ignored */,
7645 HttpAlternateProtocols::NPN_SPDY_2);
7646
7647 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7648
7649 int rv = trans->Start(&request, &callback, BoundNetLog());
7650 EXPECT_EQ(ERR_IO_PENDING, rv);
7651 EXPECT_EQ(OK, callback.WaitForResult());
7652
7653 const HttpResponseInfo* response = trans->GetResponseInfo();
7654 ASSERT_TRUE(response != NULL);
7655 ASSERT_TRUE(response->headers != NULL);
7656 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7657
7658 std::string response_data;
7659 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7660 EXPECT_EQ("hello world", response_data);
7661
7662 HttpStreamFactory::set_next_protos("");
7663 HttpStreamFactory::set_use_alternate_protocols(false);
7664 HttpStreamFactory::set_create_new_spdy_session_for_http(true);
7665}
7666
[email protected]89ceba9a2009-03-21 03:46:067667} // namespace net