blob: a128b3dc0aed0459d0fead1d81fb4960d3effa6a [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]af3490e2010-10-16 21:02:295040
[email protected]9faeded92010-04-29 20:03:055041 {
5042 "http_proxy",
5043 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025044 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185045 true,
[email protected]9faeded92010-04-29 20:03:055046 },
[email protected]2d731a32010-04-29 01:04:065047 };
5048
[email protected]8e6441ca2010-08-19 05:56:385049 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065050
5051 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5052 scoped_refptr<HttpNetworkSession> session(
5053 SetupSessionForGroupNameTests(tests[i].proxy_server));
5054
5055 HttpNetworkSessionPeer peer(session);
5056
[email protected]e60e47a2010-07-14 03:37:185057 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135058 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5059 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185060 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135061 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5062 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185063 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065064
5065 EXPECT_EQ(ERR_IO_PENDING,
5066 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185067 if (tests[i].ssl)
5068 EXPECT_EQ(tests[i].expected_group_name,
5069 ssl_conn_pool->last_group_name_received());
5070 else
5071 EXPECT_EQ(tests[i].expected_group_name,
5072 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065073 }
5074
[email protected]8e6441ca2010-08-19 05:56:385075 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065076}
5077
5078TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5079 const GroupNameTest tests[] = {
5080 {
5081 "socks4://socks_proxy:1080",
5082 "http://www.google.com/socks4_direct",
5083 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185084 false,
[email protected]2d731a32010-04-29 01:04:065085 },
5086 {
5087 "socks5://socks_proxy:1080",
5088 "http://www.google.com/socks5_direct",
5089 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185090 false,
[email protected]2d731a32010-04-29 01:04:065091 },
5092
5093 // SSL Tests
5094 {
5095 "socks4://socks_proxy:1080",
5096 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025097 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185098 true,
[email protected]2d731a32010-04-29 01:04:065099 },
5100 {
5101 "socks5://socks_proxy:1080",
5102 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025103 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185104 true,
[email protected]2d731a32010-04-29 01:04:065105 },
[email protected]af3490e2010-10-16 21:02:295106
[email protected]9faeded92010-04-29 20:03:055107 {
5108 "socks4://socks_proxy:1080",
5109 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025110 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185111 true,
[email protected]9faeded92010-04-29 20:03:055112 },
[email protected]04e5be32009-06-26 20:00:315113 };
5114
[email protected]8e6441ca2010-08-19 05:56:385115 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545116
[email protected]04e5be32009-06-26 20:00:315117 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065118 scoped_refptr<HttpNetworkSession> session(
5119 SetupSessionForGroupNameTests(tests[i].proxy_server));
5120 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315121
[email protected]e60e47a2010-07-14 03:37:185122 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135123 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5124 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185125 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135126 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5127 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185128 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315129
[email protected]5695b8c2009-09-30 21:36:435130 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315131
[email protected]2d731a32010-04-29 01:04:065132 EXPECT_EQ(ERR_IO_PENDING,
5133 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185134 if (tests[i].ssl)
5135 EXPECT_EQ(tests[i].expected_group_name,
5136 ssl_conn_pool->last_group_name_received());
5137 else
5138 EXPECT_EQ(tests[i].expected_group_name,
5139 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315140 }
[email protected]2ff8b312010-04-26 22:20:545141
[email protected]8e6441ca2010-08-19 05:56:385142 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315143}
5144
[email protected]9172a982009-06-06 00:30:255145TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545146 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005147 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325148
[email protected]69719062010-01-05 20:09:215149 // This simulates failure resolving all hostnames; that means we will fail
5150 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325151 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5152
[email protected]9172a982009-06-06 00:30:255153 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435154 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255155
5156 HttpRequestInfo request;
5157 request.method = "GET";
5158 request.url = GURL("http://www.google.com/");
5159
5160 TestCompletionCallback callback;
5161
[email protected]5a1d7ca2010-04-28 20:12:275162 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255163 EXPECT_EQ(ERR_IO_PENDING, rv);
5164
[email protected]9172a982009-06-06 00:30:255165 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015166 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255167}
5168
[email protected]f3e6c1e2009-06-15 20:52:125169// Host resolution observer used by
5170// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5171// resovle requests are issued with a referrer of |expected_referrer|.
5172class ResolutionReferrerObserver : public HostResolver::Observer {
5173 public:
5174 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5175 : expected_referrer_(expected_referrer),
5176 called_start_with_referrer_(false),
5177 called_finish_with_referrer_(false) {
5178 }
5179
5180 virtual void OnStartResolution(int id,
5181 const HostResolver::RequestInfo& info) {
5182 if (info.referrer() == expected_referrer_)
5183 called_start_with_referrer_ = true;
5184 }
5185
5186 virtual void OnFinishResolutionWithStatus(
5187 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5188 if (info.referrer() == expected_referrer_)
5189 called_finish_with_referrer_ = true;
5190 }
5191
[email protected]eb255d32009-06-17 02:11:035192 virtual void OnCancelResolution(int id,
5193 const HostResolver::RequestInfo& info ) {
5194 FAIL() << "Should not be cancelling any requests!";
5195 }
5196
[email protected]f3e6c1e2009-06-15 20:52:125197 bool did_complete_with_expected_referrer() const {
5198 return called_start_with_referrer_ && called_finish_with_referrer_;
5199 }
5200
5201 private:
5202 GURL expected_referrer_;
5203 bool called_start_with_referrer_;
5204 bool called_finish_with_referrer_;
5205
5206 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5207};
5208
5209// Make sure that when HostResolver::Resolve() is invoked, it passes through
5210// the "referrer". This is depended on by the DNS prefetch observer.
5211TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5212 GURL referrer = GURL("http://expected-referrer/");
5213 EXPECT_TRUE(referrer.is_valid());
5214 ResolutionReferrerObserver resolution_observer(referrer);
5215
5216 SessionDependencies session_deps;
5217 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435218 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125219
5220 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145221 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125222
5223 // Connect up a mock socket which will fail when reading.
5224 MockRead data_reads[] = {
5225 MockRead(false, ERR_FAILED),
5226 };
[email protected]31a2bfe2010-02-09 08:03:395227 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595228 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125229
5230 // Issue a request, containing an HTTP referrer.
5231 HttpRequestInfo request;
5232 request.method = "GET";
5233 request.referrer = referrer;
5234 request.url = GURL("http://www.google.com/");
5235
5236 // Run the request until it fails reading from the socket.
5237 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275238 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125239 EXPECT_EQ(ERR_IO_PENDING, rv);
5240 rv = callback.WaitForResult();
5241 EXPECT_EQ(ERR_FAILED, rv);
5242
5243 // Check that the host resolution observer saw |referrer|.
5244 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5245}
5246
[email protected]685af592010-05-11 19:31:245247// Base test to make sure that when the load flags for a request specify to
5248// bypass the cache, the DNS cache is not used.
5249void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285250 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325251
[email protected]a2c2fb92009-07-18 07:31:045252 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545253 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325254
[email protected]3b9cca42009-06-16 01:08:285255 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435256 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285257
5258 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5259 // a synchronous lookup.)
5260 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145261 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105262 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275263 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285264 EXPECT_EQ(OK, rv);
5265
5266 // Verify that it was added to host cache, by doing a subsequent async lookup
5267 // and confirming it completes synchronously.
5268 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465269 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105270 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275271 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325272 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285273
5274 // Inject a failure the next time that "www.google.com" is resolved. This way
5275 // we can tell if the next lookup hit the cache, or the "network".
5276 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325277 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285278
5279 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5280 // first read -- this won't be reached as the host resolution will fail first.
5281 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395282 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595283 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285284
5285 // Issue a request, asking to bypass the cache(s).
5286 HttpRequestInfo request;
5287 request.method = "GET";
[email protected]685af592010-05-11 19:31:245288 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285289 request.url = GURL("http://www.google.com/");
5290
5291 // Run the request.
5292 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275293 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285294 ASSERT_EQ(ERR_IO_PENDING, rv);
5295 rv = callback.WaitForResult();
5296
5297 // If we bypassed the cache, we would have gotten a failure while resolving
5298 // "www.google.com".
5299 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5300}
5301
[email protected]685af592010-05-11 19:31:245302// There are multiple load flags that should trigger the host cache bypass.
5303// Test each in isolation:
5304TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5305 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5306}
5307
5308TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5309 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5310}
5311
5312TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5313 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5314}
5315
[email protected]0877e3d2009-10-17 22:29:575316// Make sure we can handle an error when writing the request.
5317TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5318 SessionDependencies session_deps;
5319 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5320
5321 HttpRequestInfo request;
5322 request.method = "GET";
5323 request.url = GURL("http://www.foo.com/");
5324 request.load_flags = 0;
5325
5326 MockWrite write_failure[] = {
5327 MockWrite(true, ERR_CONNECTION_RESET),
5328 };
[email protected]31a2bfe2010-02-09 08:03:395329 StaticSocketDataProvider data(NULL, 0,
5330 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595331 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575332
5333 TestCompletionCallback callback;
5334
5335 scoped_ptr<HttpTransaction> trans(
5336 new HttpNetworkTransaction(CreateSession(&session_deps)));
5337
[email protected]5a1d7ca2010-04-28 20:12:275338 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575339 EXPECT_EQ(ERR_IO_PENDING, rv);
5340
5341 rv = callback.WaitForResult();
5342 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5343}
5344
5345// Check that a connection closed after the start of the headers finishes ok.
5346TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5347 SessionDependencies session_deps;
5348 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5349
5350 HttpRequestInfo request;
5351 request.method = "GET";
5352 request.url = GURL("http://www.foo.com/");
5353 request.load_flags = 0;
5354
5355 MockRead data_reads[] = {
5356 MockRead("HTTP/1."),
5357 MockRead(false, OK),
5358 };
5359
[email protected]31a2bfe2010-02-09 08:03:395360 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595361 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575362
5363 TestCompletionCallback callback;
5364
5365 scoped_ptr<HttpTransaction> trans(
5366 new HttpNetworkTransaction(CreateSession(&session_deps)));
5367
[email protected]5a1d7ca2010-04-28 20:12:275368 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575369 EXPECT_EQ(ERR_IO_PENDING, rv);
5370
5371 rv = callback.WaitForResult();
5372 EXPECT_EQ(OK, rv);
5373
5374 const HttpResponseInfo* response = trans->GetResponseInfo();
5375 EXPECT_TRUE(response != NULL);
5376
5377 EXPECT_TRUE(response->headers != NULL);
5378 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5379
5380 std::string response_data;
5381 rv = ReadTransaction(trans.get(), &response_data);
5382 EXPECT_EQ(OK, rv);
5383 EXPECT_EQ("", response_data);
5384}
5385
5386// Make sure that a dropped connection while draining the body for auth
5387// restart does the right thing.
5388TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5389 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:505390 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]0877e3d2009-10-17 22:29:575391
5392 HttpRequestInfo request;
5393 request.method = "GET";
5394 request.url = GURL("http://www.google.com/");
5395 request.load_flags = 0;
5396
5397 MockWrite data_writes1[] = {
5398 MockWrite("GET / HTTP/1.1\r\n"
5399 "Host: www.google.com\r\n"
5400 "Connection: keep-alive\r\n\r\n"),
5401 };
5402
5403 MockRead data_reads1[] = {
5404 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5405 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5406 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5407 MockRead("Content-Length: 14\r\n\r\n"),
5408 MockRead("Unauth"),
5409 MockRead(true, ERR_CONNECTION_RESET),
5410 };
5411
[email protected]31a2bfe2010-02-09 08:03:395412 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5413 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595414 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575415
5416 // After calling trans->RestartWithAuth(), this is the request we should
5417 // be issuing -- the final header line contains the credentials.
5418 MockWrite data_writes2[] = {
5419 MockWrite("GET / HTTP/1.1\r\n"
5420 "Host: www.google.com\r\n"
5421 "Connection: keep-alive\r\n"
5422 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5423 };
5424
5425 // Lastly, the server responds with the actual content.
5426 MockRead data_reads2[] = {
5427 MockRead("HTTP/1.1 200 OK\r\n"),
5428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5429 MockRead("Content-Length: 100\r\n\r\n"),
5430 MockRead(false, OK),
5431 };
5432
[email protected]31a2bfe2010-02-09 08:03:395433 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5434 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595435 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575436
5437 TestCompletionCallback callback1;
5438
[email protected]0b0bf032010-09-21 18:08:505439 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5440
[email protected]5a1d7ca2010-04-28 20:12:275441 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575442 EXPECT_EQ(ERR_IO_PENDING, rv);
5443
5444 rv = callback1.WaitForResult();
5445 EXPECT_EQ(OK, rv);
5446
5447 const HttpResponseInfo* response = trans->GetResponseInfo();
5448 EXPECT_FALSE(response == NULL);
5449
5450 // The password prompt info should have been set in response->auth_challenge.
5451 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5452
5453 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5454 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5455 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5456
5457 TestCompletionCallback callback2;
5458
[email protected]13c8a092010-07-29 06:15:445459 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575460 EXPECT_EQ(ERR_IO_PENDING, rv);
5461
5462 rv = callback2.WaitForResult();
5463 EXPECT_EQ(OK, rv);
5464
5465 response = trans->GetResponseInfo();
5466 EXPECT_FALSE(response == NULL);
5467 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5468 EXPECT_EQ(100, response->headers->GetContentLength());
5469}
5470
5471// Test HTTPS connections going through a proxy that sends extra data.
5472TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005473 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575474
5475 HttpRequestInfo request;
5476 request.method = "GET";
5477 request.url = GURL("https://www.google.com/");
5478 request.load_flags = 0;
5479
5480 MockRead proxy_reads[] = {
5481 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5482 MockRead(false, OK)
5483 };
5484
[email protected]31a2bfe2010-02-09 08:03:395485 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595486 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575487
[email protected]5ecc992a42009-11-11 01:41:595488 session_deps.socket_factory.AddSocketDataProvider(&data);
5489 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575490
5491 TestCompletionCallback callback;
5492
5493 session_deps.socket_factory.ResetNextMockIndexes();
5494
5495 scoped_ptr<HttpTransaction> trans(
5496 new HttpNetworkTransaction(CreateSession(&session_deps)));
5497
[email protected]5a1d7ca2010-04-28 20:12:275498 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575499 EXPECT_EQ(ERR_IO_PENDING, rv);
5500
5501 rv = callback.WaitForResult();
5502 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5503}
5504
[email protected]e22e1362009-11-23 21:31:125505TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465506 SessionDependencies session_deps;
5507 scoped_ptr<HttpTransaction> trans(
5508 new HttpNetworkTransaction(CreateSession(&session_deps)));
5509
5510 HttpRequestInfo request;
5511 request.method = "GET";
5512 request.url = GURL("http://www.google.com/");
5513 request.load_flags = 0;
5514
[email protected]e22e1362009-11-23 21:31:125515 MockRead data_reads[] = {
5516 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5517 MockRead(false, OK),
5518 };
[email protected]9492e4a2010-02-24 00:58:465519
5520 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5521 session_deps.socket_factory.AddSocketDataProvider(&data);
5522
5523 TestCompletionCallback callback;
5524
[email protected]5a1d7ca2010-04-28 20:12:275525 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465526 EXPECT_EQ(ERR_IO_PENDING, rv);
5527
5528 EXPECT_EQ(OK, callback.WaitForResult());
5529
5530 const HttpResponseInfo* response = trans->GetResponseInfo();
5531 EXPECT_TRUE(response != NULL);
5532
5533 EXPECT_TRUE(response->headers != NULL);
5534 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5535
5536 std::string response_data;
5537 rv = ReadTransaction(trans.get(), &response_data);
5538 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125539}
5540
[email protected]95d88ffe2010-02-04 21:25:335541TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5542 SessionDependencies session_deps;
5543 scoped_ptr<HttpTransaction> trans(
5544 new HttpNetworkTransaction(CreateSession(&session_deps)));
5545
5546 HttpRequestInfo request;
5547 request.method = "POST";
5548 request.url = GURL("http://www.google.com/upload");
5549 request.upload_data = new UploadData;
5550 request.load_flags = 0;
5551
5552 FilePath temp_file_path;
5553 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5554 const uint64 kFakeSize = 100000; // file is actually blank
5555
5556 std::vector<UploadData::Element> elements;
5557 UploadData::Element element;
5558 element.SetToFilePath(temp_file_path);
5559 element.SetContentLength(kFakeSize);
5560 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535561 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335562 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5563
5564 MockRead data_reads[] = {
5565 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5566 MockRead("hello world"),
5567 MockRead(false, OK),
5568 };
[email protected]31a2bfe2010-02-09 08:03:395569 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335570 session_deps.socket_factory.AddSocketDataProvider(&data);
5571
5572 TestCompletionCallback callback;
5573
[email protected]5a1d7ca2010-04-28 20:12:275574 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335575 EXPECT_EQ(ERR_IO_PENDING, rv);
5576
5577 rv = callback.WaitForResult();
5578 EXPECT_EQ(OK, rv);
5579
5580 const HttpResponseInfo* response = trans->GetResponseInfo();
5581 EXPECT_TRUE(response != NULL);
5582
5583 EXPECT_TRUE(response->headers != NULL);
5584 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5585
5586 std::string response_data;
5587 rv = ReadTransaction(trans.get(), &response_data);
5588 EXPECT_EQ(OK, rv);
5589 EXPECT_EQ("hello world", response_data);
5590
5591 file_util::Delete(temp_file_path, false);
5592}
5593
[email protected]6624b4622010-03-29 19:58:365594TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5595 // If we try to upload an unreadable file, the network stack should report
5596 // the file size as zero and upload zero bytes for that file.
5597 SessionDependencies session_deps;
5598 scoped_ptr<HttpTransaction> trans(
5599 new HttpNetworkTransaction(CreateSession(&session_deps)));
5600
5601 FilePath temp_file;
5602 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5603 std::string temp_file_content("Unreadable file.");
5604 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5605 temp_file_content.length()));
5606 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5607
5608 HttpRequestInfo request;
5609 request.method = "POST";
5610 request.url = GURL("http://www.google.com/upload");
5611 request.upload_data = new UploadData;
5612 request.load_flags = 0;
5613
5614 std::vector<UploadData::Element> elements;
5615 UploadData::Element element;
5616 element.SetToFilePath(temp_file);
5617 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535618 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365619
5620 MockRead data_reads[] = {
5621 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5622 MockRead(false, OK),
5623 };
5624 MockWrite data_writes[] = {
5625 MockWrite("POST /upload HTTP/1.1\r\n"
5626 "Host: www.google.com\r\n"
5627 "Connection: keep-alive\r\n"
5628 "Content-Length: 0\r\n\r\n"),
5629 MockWrite(false, OK),
5630 };
5631 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5632 arraysize(data_writes));
5633 session_deps.socket_factory.AddSocketDataProvider(&data);
5634
5635 TestCompletionCallback callback;
5636
[email protected]5a1d7ca2010-04-28 20:12:275637 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365638 EXPECT_EQ(ERR_IO_PENDING, rv);
5639
5640 rv = callback.WaitForResult();
5641 EXPECT_EQ(OK, rv);
5642
5643 const HttpResponseInfo* response = trans->GetResponseInfo();
5644 EXPECT_TRUE(response != NULL);
5645 EXPECT_TRUE(response->headers != NULL);
5646 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5647
5648 file_util::Delete(temp_file, false);
5649}
5650
5651TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5652 SessionDependencies session_deps;
5653 scoped_ptr<HttpTransaction> trans(
5654 new HttpNetworkTransaction(CreateSession(&session_deps)));
5655
5656 FilePath temp_file;
5657 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5658 std::string temp_file_contents("Unreadable file.");
5659 std::string unreadable_contents(temp_file_contents.length(), '\0');
5660 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5661 temp_file_contents.length()));
5662
5663 HttpRequestInfo request;
5664 request.method = "POST";
5665 request.url = GURL("http://www.google.com/upload");
5666 request.upload_data = new UploadData;
5667 request.load_flags = 0;
5668
5669 std::vector<UploadData::Element> elements;
5670 UploadData::Element element;
5671 element.SetToFilePath(temp_file);
5672 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535673 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365674
5675 MockRead data_reads[] = {
5676 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5677 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5678 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5679
5680 MockRead("HTTP/1.1 200 OK\r\n"),
5681 MockRead("Content-Length: 0\r\n\r\n"),
5682 MockRead(false, OK),
5683 };
5684 MockWrite data_writes[] = {
5685 MockWrite("POST /upload HTTP/1.1\r\n"
5686 "Host: www.google.com\r\n"
5687 "Connection: keep-alive\r\n"
5688 "Content-Length: 16\r\n\r\n"),
5689 MockWrite(false, temp_file_contents.c_str()),
5690
5691 MockWrite("POST /upload HTTP/1.1\r\n"
5692 "Host: www.google.com\r\n"
5693 "Connection: keep-alive\r\n"
5694 "Content-Length: 16\r\n"
5695 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5696 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5697 MockWrite(false, OK),
5698 };
5699 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5700 arraysize(data_writes));
5701 session_deps.socket_factory.AddSocketDataProvider(&data);
5702
5703 TestCompletionCallback callback1;
5704
[email protected]5a1d7ca2010-04-28 20:12:275705 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365706 EXPECT_EQ(ERR_IO_PENDING, rv);
5707
5708 rv = callback1.WaitForResult();
5709 EXPECT_EQ(OK, rv);
5710
5711 const HttpResponseInfo* response = trans->GetResponseInfo();
5712 EXPECT_TRUE(response != NULL);
5713 EXPECT_TRUE(response->headers != NULL);
5714 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5715
5716 // The password prompt info should have been set in response->auth_challenge.
5717 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5718 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5719 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5720 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5721
5722 // Now make the file unreadable and try again.
5723 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5724
5725 TestCompletionCallback callback2;
5726
[email protected]13c8a092010-07-29 06:15:445727 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365728 EXPECT_EQ(ERR_IO_PENDING, rv);
5729
5730 rv = callback2.WaitForResult();
5731 EXPECT_EQ(OK, rv);
5732
5733 response = trans->GetResponseInfo();
5734 EXPECT_TRUE(response != NULL);
5735 EXPECT_TRUE(response->headers != NULL);
5736 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5737 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5738
5739 file_util::Delete(temp_file, false);
5740}
5741
[email protected]aeefc9e82010-02-19 16:18:275742// Tests that changes to Auth realms are treated like auth rejections.
5743TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5744 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275745
5746 HttpRequestInfo request;
5747 request.method = "GET";
5748 request.url = GURL("http://www.google.com/");
5749 request.load_flags = 0;
5750
5751 // First transaction will request a resource and receive a Basic challenge
5752 // with realm="first_realm".
5753 MockWrite data_writes1[] = {
5754 MockWrite("GET / HTTP/1.1\r\n"
5755 "Host: www.google.com\r\n"
5756 "Connection: keep-alive\r\n"
5757 "\r\n"),
5758 };
5759 MockRead data_reads1[] = {
5760 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5761 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5762 "\r\n"),
5763 };
5764
5765 // After calling trans->RestartWithAuth(), provide an Authentication header
5766 // for first_realm. The server will reject and provide a challenge with
5767 // second_realm.
5768 MockWrite data_writes2[] = {
5769 MockWrite("GET / HTTP/1.1\r\n"
5770 "Host: www.google.com\r\n"
5771 "Connection: keep-alive\r\n"
5772 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5773 "\r\n"),
5774 };
5775 MockRead data_reads2[] = {
5776 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5777 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5778 "\r\n"),
5779 };
5780
5781 // This again fails, and goes back to first_realm. Make sure that the
5782 // entry is removed from cache.
5783 MockWrite data_writes3[] = {
5784 MockWrite("GET / HTTP/1.1\r\n"
5785 "Host: www.google.com\r\n"
5786 "Connection: keep-alive\r\n"
5787 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5788 "\r\n"),
5789 };
5790 MockRead data_reads3[] = {
5791 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5792 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5793 "\r\n"),
5794 };
5795
5796 // Try one last time (with the correct password) and get the resource.
5797 MockWrite data_writes4[] = {
5798 MockWrite("GET / HTTP/1.1\r\n"
5799 "Host: www.google.com\r\n"
5800 "Connection: keep-alive\r\n"
5801 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5802 "\r\n"),
5803 };
5804 MockRead data_reads4[] = {
5805 MockRead("HTTP/1.1 200 OK\r\n"
5806 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:505807 "Content-Length: 5\r\n"
5808 "\r\n"
5809 "hello"),
[email protected]aeefc9e82010-02-19 16:18:275810 };
5811
5812 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5813 data_writes1, arraysize(data_writes1));
5814 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5815 data_writes2, arraysize(data_writes2));
5816 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5817 data_writes3, arraysize(data_writes3));
5818 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5819 data_writes4, arraysize(data_writes4));
5820 session_deps.socket_factory.AddSocketDataProvider(&data1);
5821 session_deps.socket_factory.AddSocketDataProvider(&data2);
5822 session_deps.socket_factory.AddSocketDataProvider(&data3);
5823 session_deps.socket_factory.AddSocketDataProvider(&data4);
5824
5825 TestCompletionCallback callback1;
5826
[email protected]0b0bf032010-09-21 18:08:505827 scoped_ptr<HttpTransaction> trans(
5828 new HttpNetworkTransaction(CreateSession(&session_deps)));
5829
[email protected]aeefc9e82010-02-19 16:18:275830 // Issue the first request with Authorize headers. There should be a
5831 // password prompt for first_realm waiting to be filled in after the
5832 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275833 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275834 EXPECT_EQ(ERR_IO_PENDING, rv);
5835 rv = callback1.WaitForResult();
5836 EXPECT_EQ(OK, rv);
5837 const HttpResponseInfo* response = trans->GetResponseInfo();
5838 ASSERT_FALSE(response == NULL);
5839 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5840 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5841 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5842 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5843
5844 // Issue the second request with an incorrect password. There should be a
5845 // password prompt for second_realm waiting to be filled in after the
5846 // transaction completes.
5847 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445848 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275849 EXPECT_EQ(ERR_IO_PENDING, rv);
5850 rv = callback2.WaitForResult();
5851 EXPECT_EQ(OK, rv);
5852 response = trans->GetResponseInfo();
5853 ASSERT_FALSE(response == NULL);
5854 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5855 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5856 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5857 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5858
5859 // Issue the third request with another incorrect password. There should be
5860 // a password prompt for first_realm waiting to be filled in. If the password
5861 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5862 // first_realm was not correctly removed.
5863 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445864 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275865 EXPECT_EQ(ERR_IO_PENDING, rv);
5866 rv = callback3.WaitForResult();
5867 EXPECT_EQ(OK, rv);
5868 response = trans->GetResponseInfo();
5869 ASSERT_FALSE(response == NULL);
5870 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5871 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5872 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5873 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5874
5875 // Issue the fourth request with the correct password and username.
5876 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445877 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275878 EXPECT_EQ(ERR_IO_PENDING, rv);
5879 rv = callback4.WaitForResult();
5880 EXPECT_EQ(OK, rv);
5881 response = trans->GetResponseInfo();
5882 ASSERT_FALSE(response == NULL);
5883 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5884}
5885
[email protected]564b4912010-03-09 16:30:425886TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385887 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5888 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425889
[email protected]564b4912010-03-09 16:30:425890 SessionDependencies session_deps;
5891
5892 MockRead data_reads[] = {
5893 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355894 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425895 MockRead("hello world"),
5896 MockRead(false, OK),
5897 };
5898
5899 HttpRequestInfo request;
5900 request.method = "GET";
5901 request.url = GURL("http://www.google.com/");
5902 request.load_flags = 0;
5903
5904 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5905
5906 session_deps.socket_factory.AddSocketDataProvider(&data);
5907
5908 TestCompletionCallback callback;
5909
5910 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5911 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5912
[email protected]5a1d7ca2010-04-28 20:12:275913 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535915
[email protected]2fbaecf22010-07-22 22:20:355916 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425917 const HttpAlternateProtocols& alternate_protocols =
5918 session->alternate_protocols();
5919 EXPECT_FALSE(
5920 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5921
5922 EXPECT_EQ(OK, callback.WaitForResult());
5923
5924 const HttpResponseInfo* response = trans->GetResponseInfo();
5925 ASSERT_TRUE(response != NULL);
5926 ASSERT_TRUE(response->headers != NULL);
5927 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535928 EXPECT_FALSE(response->was_fetched_via_spdy);
5929 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575930 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425931
5932 std::string response_data;
5933 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5934 EXPECT_EQ("hello world", response_data);
5935
5936 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5937 const HttpAlternateProtocols::PortProtocolPair alternate =
5938 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5939 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5940 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355941 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425942 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425943
[email protected]8e6441ca2010-08-19 05:56:385944 HttpStreamFactory::set_use_alternate_protocols(false);
5945 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:425946}
5947
5948TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:385949 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:425950 SessionDependencies session_deps;
5951
5952 HttpRequestInfo request;
5953 request.method = "GET";
5954 request.url = GURL("http://www.google.com/");
5955 request.load_flags = 0;
5956
5957 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5958 StaticSocketDataProvider first_data;
5959 first_data.set_connect_data(mock_connect);
5960 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5961
5962 MockRead data_reads[] = {
5963 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5964 MockRead("hello world"),
5965 MockRead(true, OK),
5966 };
5967 StaticSocketDataProvider second_data(
5968 data_reads, arraysize(data_reads), NULL, 0);
5969 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5970
5971 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5972 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5973 // http://crbug.com/37454.
5974 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5975
5976 TestCompletionCallback callback;
5977
5978 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5979
[email protected]2fbaecf22010-07-22 22:20:355980 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425981 HttpAlternateProtocols* alternate_protocols =
5982 session->mutable_alternate_protocols();
5983 alternate_protocols->SetAlternateProtocolFor(
5984 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355985 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425986
5987 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5988
[email protected]5a1d7ca2010-04-28 20:12:275989 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425990 EXPECT_EQ(ERR_IO_PENDING, rv);
5991 EXPECT_EQ(OK, callback.WaitForResult());
5992
5993 const HttpResponseInfo* response = trans->GetResponseInfo();
5994 ASSERT_TRUE(response != NULL);
5995 ASSERT_TRUE(response->headers != NULL);
5996 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5997
5998 std::string response_data;
5999 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6000 EXPECT_EQ("hello world", response_data);
6001
6002 ASSERT_TRUE(
6003 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6004 const HttpAlternateProtocols::PortProtocolPair alternate =
6005 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6006 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386007 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426008}
6009
6010// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6011// says that it does SPDY, but it just does the TLS handshake, but the NPN
6012// response does not indicate SPDY, so we just do standard HTTPS over the port.
6013// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6014// on the original port.
[email protected]a2cb8122010-03-10 17:22:426015// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6016// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536017//
[email protected]a2cb8122010-03-10 17:22:426018// HttpRequestInfo request;
6019// request.method = "GET";
6020// request.url = GURL("http://www.google.com/");
6021// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536022//
[email protected]a2cb8122010-03-10 17:22:426023// MockRead data_reads[] = {
6024// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6025// MockRead("hello world"),
6026// MockRead(true, OK),
6027// };
6028// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6029// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536030//
[email protected]a2cb8122010-03-10 17:22:426031// SSLSocketDataProvider ssl(true, OK);
6032// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536033//
[email protected]a2cb8122010-03-10 17:22:426034// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536035//
[email protected]a2cb8122010-03-10 17:22:426036// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536037//
[email protected]a2cb8122010-03-10 17:22:426038// HostPortPair http_host_port_pair;
6039// http_host_port_pair.host = "www.google.com";
6040// http_host_port_pair.port = 80;
6041// HttpAlternateProtocols* alternate_protocols =
6042// session->mutable_alternate_protocols();
6043// alternate_protocols->SetAlternateProtocolFor(
6044// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066045// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536046//
[email protected]a2cb8122010-03-10 17:22:426047// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536048//
[email protected]5a1d7ca2010-04-28 20:12:276049// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426050// EXPECT_EQ(ERR_IO_PENDING, rv);
6051// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536052//
[email protected]a2cb8122010-03-10 17:22:426053// const HttpResponseInfo* response = trans->GetResponseInfo();
6054// ASSERT_TRUE(response != NULL);
6055// ASSERT_TRUE(response->headers != NULL);
6056// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536057//
[email protected]a2cb8122010-03-10 17:22:426058// std::string response_data;
6059// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6060// EXPECT_EQ("hello world", response_data);
6061// }
6062
6063TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386064 HttpStreamFactory::set_use_alternate_protocols(true);
6065 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426066 SessionDependencies session_deps;
6067
6068 HttpRequestInfo request;
6069 request.method = "GET";
6070 request.url = GURL("http://www.google.com/");
6071 request.load_flags = 0;
6072
[email protected]a2cb8122010-03-10 17:22:426073 StaticSocketDataProvider first_tcp_connect;
6074 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6075
6076 SSLSocketDataProvider ssl(true, OK);
6077 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6078
[email protected]564b4912010-03-09 16:30:426079 MockRead data_reads[] = {
6080 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6081 MockRead("hello world"),
6082 MockRead(true, OK),
6083 };
[email protected]a2cb8122010-03-10 17:22:426084 StaticSocketDataProvider fallback_data(
6085 data_reads, arraysize(data_reads), NULL, 0);
6086 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426087
6088 TestCompletionCallback callback;
6089
6090 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6091
[email protected]2fbaecf22010-07-22 22:20:356092 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426093 HttpAlternateProtocols* alternate_protocols =
6094 session->mutable_alternate_protocols();
6095 alternate_protocols->SetAlternateProtocolFor(
6096 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356097 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426098
6099 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6100
[email protected]5a1d7ca2010-04-28 20:12:276101 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426102 EXPECT_EQ(ERR_IO_PENDING, rv);
6103 EXPECT_EQ(OK, callback.WaitForResult());
6104
6105 const HttpResponseInfo* response = trans->GetResponseInfo();
6106 ASSERT_TRUE(response != NULL);
6107 ASSERT_TRUE(response->headers != NULL);
6108 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6109
6110 std::string response_data;
6111 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6112 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386113 HttpStreamFactory::set_next_protos("");
6114 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546115}
6116
6117TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386118 HttpStreamFactory::set_use_alternate_protocols(true);
6119 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546120 SessionDependencies session_deps;
6121
6122 HttpRequestInfo request;
6123 request.method = "GET";
6124 request.url = GURL("http://www.google.com/");
6125 request.load_flags = 0;
6126
6127 MockRead data_reads[] = {
6128 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356129 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546130 MockRead("hello world"),
6131 MockRead(true, OK),
6132 };
6133
6134 StaticSocketDataProvider first_transaction(
6135 data_reads, arraysize(data_reads), NULL, 0);
6136 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6137
6138 SSLSocketDataProvider ssl(true, OK);
6139 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356140 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536141 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546142 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6143
[email protected]2bd93022010-07-17 00:58:446144 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136145 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546146
[email protected]2bd93022010-07-17 00:58:446147 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6148 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546149 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136150 CreateMockRead(*resp),
6151 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546152 MockRead(true, 0, 0),
6153 };
6154
6155 scoped_refptr<DelayedSocketData> spdy_data(
6156 new DelayedSocketData(
6157 1, // wait for one write to finish before reading.
6158 spdy_reads, arraysize(spdy_reads),
6159 spdy_writes, arraysize(spdy_writes)));
6160 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6161
6162 TestCompletionCallback callback;
6163
6164 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6165 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6166
[email protected]5a1d7ca2010-04-28 20:12:276167 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546168 EXPECT_EQ(ERR_IO_PENDING, rv);
6169 EXPECT_EQ(OK, callback.WaitForResult());
6170
6171 const HttpResponseInfo* response = trans->GetResponseInfo();
6172 ASSERT_TRUE(response != NULL);
6173 ASSERT_TRUE(response->headers != NULL);
6174 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6175
6176 std::string response_data;
6177 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6178 EXPECT_EQ("hello world", response_data);
6179
6180 trans.reset(new HttpNetworkTransaction(session));
6181
[email protected]5a1d7ca2010-04-28 20:12:276182 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546183 EXPECT_EQ(ERR_IO_PENDING, rv);
6184 EXPECT_EQ(OK, callback.WaitForResult());
6185
6186 response = trans->GetResponseInfo();
6187 ASSERT_TRUE(response != NULL);
6188 ASSERT_TRUE(response->headers != NULL);
6189 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536190 EXPECT_TRUE(response->was_fetched_via_spdy);
6191 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576192 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546193
6194 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6195 EXPECT_EQ("hello!", response_data);
6196
[email protected]8e6441ca2010-08-19 05:56:386197 HttpStreamFactory::set_next_protos("");
6198 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546199}
6200
[email protected]631f1322010-04-30 17:59:116201class CapturingProxyResolver : public ProxyResolver {
6202 public:
6203 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6204 virtual ~CapturingProxyResolver() {}
6205
6206 virtual int GetProxyForURL(const GURL& url,
6207 ProxyInfo* results,
6208 CompletionCallback* callback,
6209 RequestHandle* request,
6210 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406211 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6212 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426213 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116214 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426215 return OK;
[email protected]631f1322010-04-30 17:59:116216 }
6217
6218 virtual void CancelRequest(RequestHandle request) {
6219 NOTREACHED();
6220 }
6221
[email protected]24476402010-07-20 20:55:176222 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116223 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426224 return OK;
[email protected]631f1322010-04-30 17:59:116225 }
6226
[email protected]24476402010-07-20 20:55:176227 const std::vector<GURL>& resolved() const { return resolved_; }
6228
6229 private:
[email protected]631f1322010-04-30 17:59:116230 std::vector<GURL> resolved_;
6231
6232 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6233};
6234
[email protected]631f1322010-04-30 17:59:116235TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386236 HttpStreamFactory::set_use_alternate_protocols(true);
6237 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116238
6239 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426240 proxy_config.set_auto_detect(true);
6241 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116242
[email protected]631f1322010-04-30 17:59:116243 CapturingProxyResolver* capturing_proxy_resolver =
6244 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386245 SessionDependencies session_deps(new ProxyService(
6246 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6247 NULL));
[email protected]631f1322010-04-30 17:59:116248
6249 HttpRequestInfo request;
6250 request.method = "GET";
6251 request.url = GURL("http://www.google.com/");
6252 request.load_flags = 0;
6253
6254 MockRead data_reads[] = {
6255 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356256 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116257 MockRead("hello world"),
6258 MockRead(true, OK),
6259 };
6260
6261 StaticSocketDataProvider first_transaction(
6262 data_reads, arraysize(data_reads), NULL, 0);
6263 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6264
6265 SSLSocketDataProvider ssl(true, OK);
6266 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356267 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536268 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116269 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6270
[email protected]2bd93022010-07-17 00:58:446271 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116272 MockWrite spdy_writes[] = {
6273 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6274 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426275 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136276 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116277 };
6278
[email protected]d911f1b2010-05-05 22:39:426279 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6280
[email protected]2bd93022010-07-17 00:58:446281 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6282 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116283 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426284 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136285 CreateMockRead(*resp.get(), 4), // 2, 4
6286 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426287 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116288 };
6289
[email protected]d911f1b2010-05-05 22:39:426290 scoped_refptr<OrderedSocketData> spdy_data(
6291 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116292 spdy_reads, arraysize(spdy_reads),
6293 spdy_writes, arraysize(spdy_writes)));
6294 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6295
6296 TestCompletionCallback callback;
6297
6298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6299 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6300
6301 int rv = trans->Start(&request, &callback, BoundNetLog());
6302 EXPECT_EQ(ERR_IO_PENDING, rv);
6303 EXPECT_EQ(OK, callback.WaitForResult());
6304
6305 const HttpResponseInfo* response = trans->GetResponseInfo();
6306 ASSERT_TRUE(response != NULL);
6307 ASSERT_TRUE(response->headers != NULL);
6308 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536309 EXPECT_FALSE(response->was_fetched_via_spdy);
6310 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116311
6312 std::string response_data;
6313 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6314 EXPECT_EQ("hello world", response_data);
6315
6316 trans.reset(new HttpNetworkTransaction(session));
6317
6318 rv = trans->Start(&request, &callback, BoundNetLog());
6319 EXPECT_EQ(ERR_IO_PENDING, rv);
6320 EXPECT_EQ(OK, callback.WaitForResult());
6321
6322 response = trans->GetResponseInfo();
6323 ASSERT_TRUE(response != NULL);
6324 ASSERT_TRUE(response->headers != NULL);
6325 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536326 EXPECT_TRUE(response->was_fetched_via_spdy);
6327 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116328
6329 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6330 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426331 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6332 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116333 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426334 EXPECT_EQ("https://www.google.com/",
6335 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116336
[email protected]8e6441ca2010-08-19 05:56:386337 HttpStreamFactory::set_next_protos("");
6338 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116339}
[email protected]631f1322010-04-30 17:59:116340
[email protected]2ff8b312010-04-26 22:20:546341TEST_F(HttpNetworkTransactionTest,
6342 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386343 HttpStreamFactory::set_use_alternate_protocols(true);
6344 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546345 SessionDependencies session_deps;
6346
6347 HttpRequestInfo request;
6348 request.method = "GET";
6349 request.url = GURL("http://www.google.com/");
6350 request.load_flags = 0;
6351
6352 MockRead data_reads[] = {
6353 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356354 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546355 MockRead("hello world"),
6356 MockRead(true, OK),
6357 };
6358
6359 StaticSocketDataProvider first_transaction(
6360 data_reads, arraysize(data_reads), NULL, 0);
6361 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6362
6363 SSLSocketDataProvider ssl(true, OK);
6364 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356365 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536366 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546367 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536368 // Make sure we use ssl for spdy here.
6369 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546370
[email protected]2bd93022010-07-17 00:58:446371 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136372 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546373
[email protected]2bd93022010-07-17 00:58:446374 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6375 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546376 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136377 CreateMockRead(*resp),
6378 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546379 MockRead(true, 0, 0),
6380 };
6381
6382 scoped_refptr<DelayedSocketData> spdy_data(
6383 new DelayedSocketData(
6384 1, // wait for one write to finish before reading.
6385 spdy_reads, arraysize(spdy_reads),
6386 spdy_writes, arraysize(spdy_writes)));
6387 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6388
6389 TestCompletionCallback callback;
6390
6391 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6392
6393 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6394
[email protected]5a1d7ca2010-04-28 20:12:276395 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546396 EXPECT_EQ(ERR_IO_PENDING, rv);
6397 EXPECT_EQ(OK, callback.WaitForResult());
6398
6399 const HttpResponseInfo* response = trans->GetResponseInfo();
6400 ASSERT_TRUE(response != NULL);
6401 ASSERT_TRUE(response->headers != NULL);
6402 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6403
6404 std::string response_data;
6405 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6406 EXPECT_EQ("hello world", response_data);
6407
6408 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386409 HostPortPair host_port_pair("www.google.com", 443);
6410 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546411 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276412 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6413 BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:216414 scoped_refptr<TCPSocketParams> tcp_params =
6415 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:386416
6417 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6418 EXPECT_EQ(ERR_IO_PENDING,
6419 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6420 &callback, session->tcp_socket_pool(),
6421 BoundNetLog()));
6422 EXPECT_EQ(OK, callback.WaitForResult());
6423
6424 SSLConfig ssl_config;
6425 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6426 ClientSocket* socket = connection->release_socket();
[email protected]563ee902010-09-27 16:16:176427 socket = session->socket_factory()->CreateSSLClientSocket(socket, "" ,
6428 ssl_config);
[email protected]02b0c342010-09-25 21:09:386429 connection->set_socket(socket);
6430 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6431 EXPECT_EQ(OK, callback.WaitForResult());
6432
6433 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6434 true, OK));
6435
[email protected]2ff8b312010-04-26 22:20:546436 trans.reset(new HttpNetworkTransaction(session));
6437
[email protected]5a1d7ca2010-04-28 20:12:276438 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546439 EXPECT_EQ(ERR_IO_PENDING, rv);
6440 EXPECT_EQ(OK, callback.WaitForResult());
6441
6442 response = trans->GetResponseInfo();
6443 ASSERT_TRUE(response != NULL);
6444 ASSERT_TRUE(response->headers != NULL);
6445 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536446 EXPECT_TRUE(response->was_fetched_via_spdy);
6447 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576448 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546449
6450 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6451 EXPECT_EQ("hello!", response_data);
6452
[email protected]8e6441ca2010-08-19 05:56:386453 HttpStreamFactory::set_next_protos("");
6454 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426455}
6456
[email protected]044de0642010-06-17 10:42:156457// GenerateAuthToken is a mighty big test.
6458// It tests all permutation of GenerateAuthToken behavior:
6459// - Synchronous and Asynchronous completion.
6460// - OK or error on completion.
6461// - Direct connection, non-authenticating proxy, and authenticating proxy.
6462// - HTTP or HTTPS backend (to include proxy tunneling).
6463// - Non-authenticating and authenticating backend.
6464//
6465// In all, there are 44 reasonable permuations (for example, if there are
6466// problems generating an auth token for an authenticating proxy, we don't
6467// need to test all permutations of the backend server).
6468//
6469// The test proceeds by going over each of the configuration cases, and
6470// potentially running up to three rounds in each of the tests. The TestConfig
6471// specifies both the configuration for the test as well as the expectations
6472// for the results.
6473TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506474 static const char kServer[] = "http://www.example.com";
6475 static const char kSecureServer[] = "https://www.example.com";
6476 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156477 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6478
6479 enum AuthTiming {
6480 AUTH_NONE,
6481 AUTH_SYNC,
6482 AUTH_ASYNC,
6483 };
6484
6485 const MockWrite kGet(
6486 "GET / HTTP/1.1\r\n"
6487 "Host: www.example.com\r\n"
6488 "Connection: keep-alive\r\n\r\n");
6489 const MockWrite kGetProxy(
6490 "GET http://www.example.com/ HTTP/1.1\r\n"
6491 "Host: www.example.com\r\n"
6492 "Proxy-Connection: keep-alive\r\n\r\n");
6493 const MockWrite kGetAuth(
6494 "GET / HTTP/1.1\r\n"
6495 "Host: www.example.com\r\n"
6496 "Connection: keep-alive\r\n"
6497 "Authorization: auth_token\r\n\r\n");
6498 const MockWrite kGetProxyAuth(
6499 "GET http://www.example.com/ HTTP/1.1\r\n"
6500 "Host: www.example.com\r\n"
6501 "Proxy-Connection: keep-alive\r\n"
6502 "Proxy-Authorization: auth_token\r\n\r\n");
6503 const MockWrite kGetAuthThroughProxy(
6504 "GET http://www.example.com/ HTTP/1.1\r\n"
6505 "Host: www.example.com\r\n"
6506 "Proxy-Connection: keep-alive\r\n"
6507 "Authorization: auth_token\r\n\r\n");
6508 const MockWrite kGetAuthWithProxyAuth(
6509 "GET http://www.example.com/ HTTP/1.1\r\n"
6510 "Host: www.example.com\r\n"
6511 "Proxy-Connection: keep-alive\r\n"
6512 "Proxy-Authorization: auth_token\r\n"
6513 "Authorization: auth_token\r\n\r\n");
6514 const MockWrite kConnect(
6515 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6516 "Host: www.example.com\r\n"
6517 "Proxy-Connection: keep-alive\r\n\r\n");
6518 const MockWrite kConnectProxyAuth(
6519 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6520 "Host: www.example.com\r\n"
6521 "Proxy-Connection: keep-alive\r\n"
6522 "Proxy-Authorization: auth_token\r\n\r\n");
6523
6524 const MockRead kSuccess(
6525 "HTTP/1.1 200 OK\r\n"
6526 "Content-Type: text/html; charset=iso-8859-1\r\n"
6527 "Content-Length: 3\r\n\r\n"
6528 "Yes");
6529 const MockRead kFailure(
6530 "Should not be called.");
6531 const MockRead kServerChallenge(
6532 "HTTP/1.1 401 Unauthorized\r\n"
6533 "WWW-Authenticate: Mock realm=server\r\n"
6534 "Content-Type: text/html; charset=iso-8859-1\r\n"
6535 "Content-Length: 14\r\n\r\n"
6536 "Unauthorized\r\n");
6537 const MockRead kProxyChallenge(
6538 "HTTP/1.1 407 Unauthorized\r\n"
6539 "Proxy-Authenticate: Mock realm=proxy\r\n"
6540 "Proxy-Connection: close\r\n"
6541 "Content-Type: text/html; charset=iso-8859-1\r\n"
6542 "Content-Length: 14\r\n\r\n"
6543 "Unauthorized\r\n");
6544 const MockRead kProxyConnected(
6545 "HTTP/1.1 200 Connection Established\r\n\r\n");
6546
6547 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6548 // no constructors, but the C++ compiler on Windows warns about
6549 // unspecified data in compound literals. So, moved to using constructors,
6550 // and TestRound's created with the default constructor should not be used.
6551 struct TestRound {
6552 TestRound()
6553 : expected_rv(ERR_UNEXPECTED),
6554 extra_write(NULL),
6555 extra_read(NULL) {
6556 }
6557 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6558 int expected_rv_arg)
6559 : write(write_arg),
6560 read(read_arg),
6561 expected_rv(expected_rv_arg),
6562 extra_write(NULL),
6563 extra_read(NULL) {
6564 }
6565 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6566 int expected_rv_arg, const MockWrite* extra_write_arg,
6567 const MockWrite* extra_read_arg)
6568 : write(write_arg),
6569 read(read_arg),
6570 expected_rv(expected_rv_arg),
6571 extra_write(extra_write_arg),
6572 extra_read(extra_read_arg) {
6573 }
6574 MockWrite write;
6575 MockRead read;
6576 int expected_rv;
6577 const MockWrite* extra_write;
6578 const MockRead* extra_read;
6579 };
6580
6581 static const int kNoSSL = 500;
6582
6583 struct TestConfig {
6584 const char* proxy_url;
6585 AuthTiming proxy_auth_timing;
6586 int proxy_auth_rv;
6587 const char* server_url;
6588 AuthTiming server_auth_timing;
6589 int server_auth_rv;
6590 int num_auth_rounds;
6591 int first_ssl_round;
6592 TestRound rounds[3];
6593 } test_configs[] = {
6594 // Non-authenticating HTTP server with a direct connection.
6595 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6596 { TestRound(kGet, kSuccess, OK)}},
6597 // Authenticating HTTP server with a direct connection.
6598 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6599 { TestRound(kGet, kServerChallenge, OK),
6600 TestRound(kGetAuth, kSuccess, OK)}},
6601 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6602 { TestRound(kGet, kServerChallenge, OK),
6603 TestRound(kGetAuth, kFailure, kAuthErr)}},
6604 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6605 { TestRound(kGet, kServerChallenge, OK),
6606 TestRound(kGetAuth, kSuccess, OK)}},
6607 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6608 { TestRound(kGet, kServerChallenge, OK),
6609 TestRound(kGetAuth, kFailure, kAuthErr)}},
6610 // Non-authenticating HTTP server through a non-authenticating proxy.
6611 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6612 { TestRound(kGetProxy, kSuccess, OK)}},
6613 // Authenticating HTTP server through a non-authenticating proxy.
6614 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6615 { TestRound(kGetProxy, kServerChallenge, OK),
6616 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6617 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6618 { TestRound(kGetProxy, kServerChallenge, OK),
6619 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6620 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6621 { TestRound(kGetProxy, kServerChallenge, OK),
6622 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6623 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6624 { TestRound(kGetProxy, kServerChallenge, OK),
6625 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6626 // Non-authenticating HTTP server through an authenticating proxy.
6627 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6628 { TestRound(kGetProxy, kProxyChallenge, OK),
6629 TestRound(kGetProxyAuth, kSuccess, OK)}},
6630 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6631 { TestRound(kGetProxy, kProxyChallenge, OK),
6632 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6633 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6634 { TestRound(kGetProxy, kProxyChallenge, OK),
6635 TestRound(kGetProxyAuth, kSuccess, OK)}},
6636 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6637 { TestRound(kGetProxy, kProxyChallenge, OK),
6638 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6639 // Authenticating HTTP server through an authenticating proxy.
6640 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6641 { TestRound(kGetProxy, kProxyChallenge, OK),
6642 TestRound(kGetProxyAuth, kServerChallenge, OK),
6643 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6644 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6645 { TestRound(kGetProxy, kProxyChallenge, OK),
6646 TestRound(kGetProxyAuth, kServerChallenge, OK),
6647 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6648 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6649 { TestRound(kGetProxy, kProxyChallenge, OK),
6650 TestRound(kGetProxyAuth, kServerChallenge, OK),
6651 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6652 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6653 { TestRound(kGetProxy, kProxyChallenge, OK),
6654 TestRound(kGetProxyAuth, kServerChallenge, OK),
6655 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6656 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6657 { TestRound(kGetProxy, kProxyChallenge, OK),
6658 TestRound(kGetProxyAuth, kServerChallenge, OK),
6659 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6660 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6661 { TestRound(kGetProxy, kProxyChallenge, OK),
6662 TestRound(kGetProxyAuth, kServerChallenge, OK),
6663 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6664 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6665 { TestRound(kGetProxy, kProxyChallenge, OK),
6666 TestRound(kGetProxyAuth, kServerChallenge, OK),
6667 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6668 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6669 { TestRound(kGetProxy, kProxyChallenge, OK),
6670 TestRound(kGetProxyAuth, kServerChallenge, OK),
6671 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6672 // Non-authenticating HTTPS server with a direct connection.
6673 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6674 { TestRound(kGet, kSuccess, OK)}},
6675 // Authenticating HTTPS server with a direct connection.
6676 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6677 { TestRound(kGet, kServerChallenge, OK),
6678 TestRound(kGetAuth, kSuccess, OK)}},
6679 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6680 { TestRound(kGet, kServerChallenge, OK),
6681 TestRound(kGetAuth, kFailure, kAuthErr)}},
6682 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6683 { TestRound(kGet, kServerChallenge, OK),
6684 TestRound(kGetAuth, kSuccess, OK)}},
6685 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6686 { TestRound(kGet, kServerChallenge, OK),
6687 TestRound(kGetAuth, kFailure, kAuthErr)}},
6688 // Non-authenticating HTTPS server with a non-authenticating proxy.
6689 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6690 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6691 // Authenticating HTTPS server through a non-authenticating proxy.
6692 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6693 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6694 TestRound(kGetAuth, kSuccess, OK)}},
6695 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6696 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6697 TestRound(kGetAuth, kFailure, kAuthErr)}},
6698 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6699 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6700 TestRound(kGetAuth, kSuccess, OK)}},
6701 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6702 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6703 TestRound(kGetAuth, kFailure, kAuthErr)}},
6704 // Non-Authenticating HTTPS server through an authenticating proxy.
6705 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6706 { TestRound(kConnect, kProxyChallenge, OK),
6707 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6708 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6709 { TestRound(kConnect, kProxyChallenge, OK),
6710 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6711 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6712 { TestRound(kConnect, kProxyChallenge, OK),
6713 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6714 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6715 { TestRound(kConnect, kProxyChallenge, OK),
6716 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6717 // Authenticating HTTPS server through an authenticating proxy.
6718 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6719 { TestRound(kConnect, kProxyChallenge, OK),
6720 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6721 &kGet, &kServerChallenge),
6722 TestRound(kGetAuth, kSuccess, OK)}},
6723 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6724 { TestRound(kConnect, kProxyChallenge, OK),
6725 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6726 &kGet, &kServerChallenge),
6727 TestRound(kGetAuth, kFailure, kAuthErr)}},
6728 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6729 { TestRound(kConnect, kProxyChallenge, OK),
6730 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6731 &kGet, &kServerChallenge),
6732 TestRound(kGetAuth, kSuccess, OK)}},
6733 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6734 { TestRound(kConnect, kProxyChallenge, OK),
6735 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6736 &kGet, &kServerChallenge),
6737 TestRound(kGetAuth, kFailure, kAuthErr)}},
6738 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6739 { TestRound(kConnect, kProxyChallenge, OK),
6740 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6741 &kGet, &kServerChallenge),
6742 TestRound(kGetAuth, kSuccess, OK)}},
6743 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6744 { TestRound(kConnect, kProxyChallenge, OK),
6745 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6746 &kGet, &kServerChallenge),
6747 TestRound(kGetAuth, kFailure, kAuthErr)}},
6748 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6749 { TestRound(kConnect, kProxyChallenge, OK),
6750 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6751 &kGet, &kServerChallenge),
6752 TestRound(kGetAuth, kSuccess, OK)}},
6753 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6754 { TestRound(kConnect, kProxyChallenge, OK),
6755 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6756 &kGet, &kServerChallenge),
6757 TestRound(kGetAuth, kFailure, kAuthErr)}},
6758 };
6759
6760 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:006761 HttpAuthHandlerMock::Factory* auth_factory(
6762 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156763 session_deps.http_auth_handler_factory.reset(auth_factory);
6764
6765 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6766 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266767
6768 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156769 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006770 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156771 std::string auth_challenge = "Mock realm=proxy";
6772 GURL origin(test_config.proxy_url);
6773 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6774 auth_challenge.end());
6775 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6776 origin, BoundNetLog());
6777 auth_handler->SetGenerateExpectation(
6778 test_config.proxy_auth_timing == AUTH_ASYNC,
6779 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156780 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6781 }
6782 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006783 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156784 std::string auth_challenge = "Mock realm=server";
6785 GURL origin(test_config.server_url);
6786 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6787 auth_challenge.end());
6788 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6789 origin, BoundNetLog());
6790 auth_handler->SetGenerateExpectation(
6791 test_config.server_auth_timing == AUTH_ASYNC,
6792 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156793 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6794 }
6795 if (test_config.proxy_url) {
6796 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:006797 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:156798 } else {
[email protected]ebeefff32010-09-15 05:10:026799 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:156800 }
6801
6802 HttpRequestInfo request;
6803 request.method = "GET";
6804 request.url = GURL(test_config.server_url);
6805 request.load_flags = 0;
6806
[email protected]0b0bf032010-09-21 18:08:506807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6808 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:156809
6810 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6811 const TestRound& read_write_round = test_config.rounds[round];
6812
6813 // Set up expected reads and writes.
6814 MockRead reads[2];
6815 reads[0] = read_write_round.read;
6816 size_t length_reads = 1;
6817 if (read_write_round.extra_read) {
6818 reads[1] = *read_write_round.extra_read;
6819 length_reads = 2;
6820 }
6821
6822 MockWrite writes[2];
6823 writes[0] = read_write_round.write;
6824 size_t length_writes = 1;
6825 if (read_write_round.extra_write) {
6826 writes[1] = *read_write_round.extra_write;
6827 length_writes = 2;
6828 }
6829 StaticSocketDataProvider data_provider(
6830 reads, length_reads, writes, length_writes);
6831 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6832
6833 // Add an SSL sequence if necessary.
6834 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6835 if (round >= test_config.first_ssl_round)
6836 session_deps.socket_factory.AddSSLSocketDataProvider(
6837 &ssl_socket_data_provider);
6838
6839 // Start or restart the transaction.
6840 TestCompletionCallback callback;
6841 int rv;
6842 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:506843 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:156844 } else {
[email protected]0b0bf032010-09-21 18:08:506845 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156846 }
6847 if (rv == ERR_IO_PENDING)
6848 rv = callback.WaitForResult();
6849
6850 // Compare results with expected data.
6851 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:506852 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:156853 if (read_write_round.expected_rv == OK) {
6854 EXPECT_FALSE(response == NULL);
6855 } else {
6856 EXPECT_TRUE(response == NULL);
6857 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6858 continue;
6859 }
6860 if (round + 1 < test_config.num_auth_rounds) {
6861 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6862 } else {
6863 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6864 }
6865 }
[email protected]e5ae96a2010-04-14 20:12:456866 }
6867}
6868
[email protected]c871bce92010-07-15 21:51:146869TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6870 // Do multi-round authentication and make sure it works correctly.
6871 SessionDependencies session_deps;
6872 HttpAuthHandlerMock::Factory* auth_factory(
6873 new HttpAuthHandlerMock::Factory());
6874 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:026875 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:146876 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6877 session_deps.host_resolver->set_synchronous_mode(true);
6878
6879 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6880 auth_handler->set_connection_based(true);
6881 std::string auth_challenge = "Mock realm=server";
6882 GURL origin("http://www.example.com");
6883 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6884 auth_challenge.end());
6885 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6886 origin, BoundNetLog());
6887 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6888
6889 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6890 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6891
6892 int rv = OK;
6893 const HttpResponseInfo* response = NULL;
6894 HttpRequestInfo request;
6895 request.method = "GET";
6896 request.url = origin;
6897 request.load_flags = 0;
6898 TestCompletionCallback callback;
6899
6900 const MockWrite kGet(
6901 "GET / HTTP/1.1\r\n"
6902 "Host: www.example.com\r\n"
6903 "Connection: keep-alive\r\n\r\n");
6904 const MockWrite kGetAuth(
6905 "GET / HTTP/1.1\r\n"
6906 "Host: www.example.com\r\n"
6907 "Connection: keep-alive\r\n"
6908 "Authorization: auth_token\r\n\r\n");
6909
6910 const MockRead kServerChallenge(
6911 "HTTP/1.1 401 Unauthorized\r\n"
6912 "WWW-Authenticate: Mock realm=server\r\n"
6913 "Content-Type: text/html; charset=iso-8859-1\r\n"
6914 "Content-Length: 14\r\n\r\n"
6915 "Unauthorized\r\n");
6916 const MockRead kSuccess(
6917 "HTTP/1.1 200 OK\r\n"
6918 "Content-Type: text/html; charset=iso-8859-1\r\n"
6919 "Content-Length: 3\r\n\r\n"
6920 "Yes");
6921
6922 MockWrite writes[] = {
6923 // First round
6924 kGet,
6925 // Second round
6926 kGetAuth,
6927 // Third round
6928 kGetAuth,
[email protected]eca50e122010-09-11 14:03:306929 // Fourth round
6930 kGetAuth
[email protected]c871bce92010-07-15 21:51:146931 };
6932 MockRead reads[] = {
6933 // First round
6934 kServerChallenge,
6935 // Second round
6936 kServerChallenge,
6937 // Third round
[email protected]eca50e122010-09-11 14:03:306938 kServerChallenge,
6939 // Fourth round
[email protected]c871bce92010-07-15 21:51:146940 kSuccess,
6941 };
6942 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6943 writes, arraysize(writes));
6944 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6945
6946 // First round
6947 auth_handler->SetGenerateExpectation(false, OK);
6948 rv = trans->Start(&request, &callback, BoundNetLog());
6949 if (rv == ERR_IO_PENDING)
6950 rv = callback.WaitForResult();
6951 EXPECT_EQ(OK, rv);
6952 response = trans->GetResponseInfo();
6953 ASSERT_FALSE(response == NULL);
6954 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6955
6956 // Second round
6957 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446958 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146959 if (rv == ERR_IO_PENDING)
6960 rv = callback.WaitForResult();
6961 EXPECT_EQ(OK, rv);
6962 response = trans->GetResponseInfo();
6963 ASSERT_FALSE(response == NULL);
6964 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6965
6966 // Third round
6967 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446968 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146969 if (rv == ERR_IO_PENDING)
6970 rv = callback.WaitForResult();
6971 EXPECT_EQ(OK, rv);
6972 response = trans->GetResponseInfo();
6973 ASSERT_FALSE(response == NULL);
6974 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:306975
6976 // Fourth round
6977 auth_handler->SetGenerateExpectation(false, OK);
6978 rv = trans->RestartWithAuth(string16(), string16(), &callback);
6979 if (rv == ERR_IO_PENDING)
6980 rv = callback.WaitForResult();
6981 EXPECT_EQ(OK, rv);
6982 response = trans->GetResponseInfo();
6983 ASSERT_FALSE(response == NULL);
6984 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:146985}
6986
[email protected]aeaca1f2010-04-20 22:05:216987class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6988 public:
[email protected]06650c52010-06-03 00:49:176989 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216990 : fail_all_(fail_all) {
6991 }
6992
6993 virtual MockRead GetNextRead() {
6994 if (fail_all_)
6995 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6996
6997 return MockRead(false /* async */,
6998 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6999 }
7000
7001 virtual MockWriteResult OnWrite(const std::string& data) {
7002 return MockWriteResult(false /* async */, data.size());
7003 }
7004
7005 void Reset() {
7006 }
7007
7008 private:
7009 const bool fail_all_;
7010};
7011
7012// Test that we restart a connection when we see a decompression failure from
7013// the peer during the handshake. (In the real world we'll restart with SSLv3
7014// and we won't offer DEFLATE in that case.)
7015TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7016 HttpRequestInfo request;
7017 request.method = "GET";
7018 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7019 request.load_flags = 0;
7020
7021 SessionDependencies session_deps;
7022 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7023 false /* fail all reads */);
7024 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7025 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117026 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217027 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7028 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7029 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7030 session_deps.socket_factory.AddSSLSocketDataProvider(
7031 &ssl_socket_data_provider1);
7032 session_deps.socket_factory.AddSSLSocketDataProvider(
7033 &ssl_socket_data_provider2);
7034
[email protected]e60e47a2010-07-14 03:37:187035 // Work around http://crbug.com/37454
7036 StaticSocketDataProvider bug37454_connection;
7037 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7038 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7039
[email protected]aeaca1f2010-04-20 22:05:217040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7041 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7042 TestCompletionCallback callback;
7043
[email protected]5a1d7ca2010-04-28 20:12:277044 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217045 EXPECT_EQ(ERR_IO_PENDING, rv);
7046 EXPECT_EQ(OK, callback.WaitForResult());
7047
7048 const HttpResponseInfo* response = trans->GetResponseInfo();
7049 ASSERT_TRUE(response != NULL);
7050 ASSERT_TRUE(response->headers != NULL);
7051 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7052
7053 std::string response_data;
7054 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7055 EXPECT_EQ("ok.", response_data);
7056}
7057
7058// Test that we restart a connection if we get a decompression failure from the
7059// peer while reading the first bytes from the connection. This occurs when the
7060// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7061// in the handshake.
7062TEST_F(HttpNetworkTransactionTest,
7063 RestartAfterTLSDecompressionFailureWithFalseStart) {
7064 HttpRequestInfo request;
7065 request.method = "GET";
7066 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7067 request.load_flags = 0;
7068
7069 SessionDependencies session_deps;
7070 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7071 true /* fail all reads */);
7072 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7073 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7074 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7075 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7076 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7077 session_deps.socket_factory.AddSSLSocketDataProvider(
7078 &ssl_socket_data_provider1);
7079 session_deps.socket_factory.AddSSLSocketDataProvider(
7080 &ssl_socket_data_provider2);
7081
7082 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7083 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7084 TestCompletionCallback callback;
7085
[email protected]5a1d7ca2010-04-28 20:12:277086 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217087 EXPECT_EQ(ERR_IO_PENDING, rv);
7088 EXPECT_EQ(OK, callback.WaitForResult());
7089
7090 const HttpResponseInfo* response = trans->GetResponseInfo();
7091 ASSERT_TRUE(response != NULL);
7092 ASSERT_TRUE(response->headers != NULL);
7093 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7094
7095 std::string response_data;
7096 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7097 EXPECT_EQ("ok.", response_data);
7098}
7099
[email protected]65041fa2010-05-21 06:56:537100// This tests the case that a request is issued via http instead of spdy after
7101// npn is negotiated.
7102TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387103 HttpStreamFactory::set_use_alternate_protocols(true);
7104 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537105 SessionDependencies session_deps;
7106 HttpRequestInfo request;
7107 request.method = "GET";
7108 request.url = GURL("https://www.google.com/");
7109 request.load_flags = 0;
7110
7111 MockWrite data_writes[] = {
7112 MockWrite("GET / HTTP/1.1\r\n"
7113 "Host: www.google.com\r\n"
7114 "Connection: keep-alive\r\n\r\n"),
7115 };
7116
7117 MockRead data_reads[] = {
7118 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357119 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537120 MockRead("hello world"),
7121 MockRead(false, OK),
7122 };
7123
7124 SSLSocketDataProvider ssl(true, OK);
7125 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7126 ssl.next_proto = "http/1.1";
7127
7128 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7129
7130 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7131 data_writes, arraysize(data_writes));
7132 session_deps.socket_factory.AddSocketDataProvider(&data);
7133
7134 TestCompletionCallback callback;
7135
7136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7137 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7138
7139 int rv = trans->Start(&request, &callback, BoundNetLog());
7140
7141 EXPECT_EQ(ERR_IO_PENDING, rv);
7142 EXPECT_EQ(OK, callback.WaitForResult());
7143
7144 const HttpResponseInfo* response = trans->GetResponseInfo();
7145 ASSERT_TRUE(response != NULL);
7146 ASSERT_TRUE(response->headers != NULL);
7147 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7148
7149 std::string response_data;
7150 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7151 EXPECT_EQ("hello world", response_data);
7152
7153 EXPECT_FALSE(response->was_fetched_via_spdy);
7154 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577155 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537156
[email protected]8e6441ca2010-08-19 05:56:387157 HttpStreamFactory::set_next_protos("");
7158 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537159}
[email protected]26ef6582010-06-24 02:30:477160
7161TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7162 // Simulate the SSL handshake completing with an NPN negotiation
7163 // followed by an immediate server closing of the socket.
7164 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387165 HttpStreamFactory::set_use_alternate_protocols(true);
7166 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477167 SessionDependencies session_deps;
7168
7169 HttpRequestInfo request;
7170 request.method = "GET";
7171 request.url = GURL("https://www.google.com/");
7172 request.load_flags = 0;
7173
7174 SSLSocketDataProvider ssl(true, OK);
7175 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357176 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477177 ssl.was_npn_negotiated = true;
7178 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7179
[email protected]2bd93022010-07-17 00:58:447180 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137181 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477182
7183 MockRead spdy_reads[] = {
7184 MockRead(false, 0, 0) // Not async - return 0 immediately.
7185 };
7186
7187 scoped_refptr<DelayedSocketData> spdy_data(
7188 new DelayedSocketData(
7189 0, // don't wait in this case, immediate hangup.
7190 spdy_reads, arraysize(spdy_reads),
7191 spdy_writes, arraysize(spdy_writes)));
7192 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7193
7194 TestCompletionCallback callback;
7195
7196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7197 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7198
7199 int rv = trans->Start(&request, &callback, BoundNetLog());
7200 EXPECT_EQ(ERR_IO_PENDING, rv);
7201 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7202
[email protected]8e6441ca2010-08-19 05:56:387203 HttpStreamFactory::set_next_protos("");
7204 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477205}
[email protected]65d34382010-07-01 18:12:267206
[email protected]f45c1ee2010-08-03 00:54:307207TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7208 // This test ensures that the URL passed into the proxy is upgraded
7209 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387210 HttpStreamFactory::set_use_alternate_protocols(true);
7211 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307212 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7213
[email protected]81cdfcd2010-10-16 00:49:007214 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307215 HttpAuthHandlerMock::Factory* auth_factory =
7216 new HttpAuthHandlerMock::Factory();
7217 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7218 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7219 auth_factory->set_do_init_from_challenge(true);
7220 session_deps.http_auth_handler_factory.reset(auth_factory);
7221
7222 HttpRequestInfo request;
7223 request.method = "GET";
7224 request.url = GURL("http://www.google.com");
7225 request.load_flags = 0;
7226
7227 // First round goes unauthenticated through the proxy.
7228 MockWrite data_writes_1[] = {
7229 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7230 "Host: www.google.com\r\n"
7231 "Proxy-Connection: keep-alive\r\n"
7232 "\r\n"),
7233 };
7234 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597235 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307236 MockRead("HTTP/1.1 200 OK\r\n"
7237 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7238 "Proxy-Connection: close\r\n"
7239 "\r\n"),
7240 };
7241 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7242 data_writes_1, arraysize(data_writes_1));
7243
7244 // Second round tries to tunnel to www.google.com due to the
7245 // Alternate-Protocol announcement in the first round. It fails due
7246 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597247 // After the failure, a tunnel is established to www.google.com using
7248 // Proxy-Authorization headers. There is then a SPDY request round.
7249 //
7250 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7251 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7252 // does a Disconnect and Connect on the same socket, rather than trying
7253 // to obtain a new one.
7254 //
7255 // NOTE: Originally, the proxy response to the second CONNECT request
7256 // simply returned another 407 so the unit test could skip the SSL connection
7257 // establishment and SPDY framing issues. Alas, the
7258 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307259 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597260
[email protected]f45c1ee2010-08-03 00:54:307261 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7262 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7263 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7264
[email protected]394816e92010-08-03 07:38:597265 MockWrite data_writes_2[] = {
7266 // First connection attempt without Proxy-Authorization.
7267 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7268 "Host: www.google.com\r\n"
7269 "Proxy-Connection: keep-alive\r\n"
7270 "\r\n"),
7271
7272 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307273 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7274 "Host: www.google.com\r\n"
7275 "Proxy-Connection: keep-alive\r\n"
7276 "Proxy-Authorization: auth_token\r\n"
7277 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307278
[email protected]394816e92010-08-03 07:38:597279 // SPDY request
7280 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307281 };
[email protected]394816e92010-08-03 07:38:597282 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7283 "Proxy-Authenticate: Mock\r\n"
7284 "Proxy-Connection: close\r\n"
7285 "\r\n");
7286 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7287 MockRead data_reads_2[] = {
7288 // First connection attempt fails
7289 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7290 MockRead(true, kRejectConnectResponse,
7291 arraysize(kRejectConnectResponse) - 1, 1),
7292
7293 // Second connection attempt passes
7294 MockRead(true, kAcceptConnectResponse,
7295 arraysize(kAcceptConnectResponse) -1, 4),
7296
7297 // SPDY response
7298 CreateMockRead(*resp.get(), 6),
7299 CreateMockRead(*data.get(), 6),
7300 MockRead(true, 0, 0, 6),
7301 };
7302 scoped_refptr<OrderedSocketData> data_2(
7303 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7304 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307305
7306 SSLSocketDataProvider ssl(true, OK);
7307 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7308 ssl.next_proto = "spdy/2";
7309 ssl.was_npn_negotiated = true;
7310
7311 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597312 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307313 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7314 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7315
7316 // First round should work and provide the Alternate-Protocol state.
7317 TestCompletionCallback callback_1;
7318 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7319 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7320 EXPECT_EQ(ERR_IO_PENDING, rv);
7321 EXPECT_EQ(OK, callback_1.WaitForResult());
7322
7323 // Second round should attempt a tunnel connect and get an auth challenge.
7324 TestCompletionCallback callback_2;
7325 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7326 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7327 EXPECT_EQ(ERR_IO_PENDING, rv);
7328 EXPECT_EQ(OK, callback_2.WaitForResult());
7329 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7330 ASSERT_FALSE(response == NULL);
7331 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7332
7333 // Restart with auth. Tunnel should work and response received.
7334 TestCompletionCallback callback_3;
7335 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7336 EXPECT_EQ(ERR_IO_PENDING, rv);
7337 EXPECT_EQ(OK, callback_3.WaitForResult());
7338
7339 // After all that work, these two lines (or actually, just the scheme) are
7340 // what this test is all about. Make sure it happens correctly.
7341 const GURL& request_url = auth_handler->request_url();
7342 EXPECT_EQ("https", request_url.scheme());
7343 EXPECT_EQ("www.google.com", request_url.host());
7344
[email protected]8e6441ca2010-08-19 05:56:387345 HttpStreamFactory::set_next_protos("");
7346 HttpStreamFactory::set_use_alternate_protocols(false);
7347}
7348
7349// Test that if we cancel the transaction as the connection is completing, that
7350// everything tears down correctly.
7351TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7352 // Setup everything about the connection to complete synchronously, so that
7353 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7354 // for is the callback from the HttpStreamRequest.
7355 // Then cancel the transaction.
7356 // Verify that we don't crash.
7357 MockConnect mock_connect(false, OK);
7358 MockRead data_reads[] = {
7359 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7360 MockRead(false, "hello world"),
7361 MockRead(false, OK),
7362 };
7363
7364 SessionDependencies session_deps;
7365 session_deps.host_resolver->set_synchronous_mode(true);
7366 scoped_ptr<HttpTransaction> trans(
7367 new HttpNetworkTransaction(CreateSession(&session_deps)));
7368
7369 HttpRequestInfo request;
7370 request.method = "GET";
7371 request.url = GURL("http://www.google.com/");
7372 request.load_flags = 0;
7373
7374 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7375 data.set_connect_data(mock_connect);
7376 session_deps.socket_factory.AddSocketDataProvider(&data);
7377
7378 TestCompletionCallback callback;
7379
7380 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7381 int rv = trans->Start(&request, &callback, log.bound());
7382 EXPECT_EQ(ERR_IO_PENDING, rv);
7383 trans.reset(); // Cancel the transaction here.
7384
7385 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307386}
7387
[email protected]76a505b2010-08-25 06:23:007388// Test a basic GET request through a proxy.
7389TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007390 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007391 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7392 session_deps.net_log = log.bound().net_log();
7393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7394
[email protected]76a505b2010-08-25 06:23:007395 HttpRequestInfo request;
7396 request.method = "GET";
7397 request.url = GURL("http://www.google.com/");
7398
7399 MockWrite data_writes1[] = {
7400 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7401 "Host: www.google.com\r\n"
7402 "Proxy-Connection: keep-alive\r\n\r\n"),
7403 };
7404
7405 MockRead data_reads1[] = {
7406 MockRead("HTTP/1.1 200 OK\r\n"),
7407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7408 MockRead("Content-Length: 100\r\n\r\n"),
7409 MockRead(false, OK),
7410 };
7411
7412 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7413 data_writes1, arraysize(data_writes1));
7414 session_deps.socket_factory.AddSocketDataProvider(&data1);
7415
7416 TestCompletionCallback callback1;
7417
[email protected]0b0bf032010-09-21 18:08:507418 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7419
[email protected]76a505b2010-08-25 06:23:007420 int rv = trans->Start(&request, &callback1, log.bound());
7421 EXPECT_EQ(ERR_IO_PENDING, rv);
7422
7423 rv = callback1.WaitForResult();
7424 EXPECT_EQ(OK, rv);
7425
7426 const HttpResponseInfo* response = trans->GetResponseInfo();
7427 ASSERT_FALSE(response == NULL);
7428
7429 EXPECT_TRUE(response->headers->IsKeepAlive());
7430 EXPECT_EQ(200, response->headers->response_code());
7431 EXPECT_EQ(100, response->headers->GetContentLength());
7432 EXPECT_TRUE(response->was_fetched_via_proxy);
7433 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7434}
7435
7436// Test a basic HTTPS GET request through a proxy.
7437TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007438 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007439 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7440 session_deps.net_log = log.bound().net_log();
7441 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7442
[email protected]76a505b2010-08-25 06:23:007443 HttpRequestInfo request;
7444 request.method = "GET";
7445 request.url = GURL("https://www.google.com/");
7446
7447 // Since we have proxy, should try to establish tunnel.
7448 MockWrite data_writes1[] = {
7449 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7450 "Host: www.google.com\r\n"
7451 "Proxy-Connection: keep-alive\r\n\r\n"),
7452
7453 MockWrite("GET / HTTP/1.1\r\n"
7454 "Host: www.google.com\r\n"
7455 "Connection: keep-alive\r\n\r\n"),
7456 };
7457
7458 MockRead data_reads1[] = {
7459 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7460
7461 MockRead("HTTP/1.1 200 OK\r\n"),
7462 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7463 MockRead("Content-Length: 100\r\n\r\n"),
7464 MockRead(false, OK),
7465 };
7466
7467 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7468 data_writes1, arraysize(data_writes1));
7469 session_deps.socket_factory.AddSocketDataProvider(&data1);
7470 SSLSocketDataProvider ssl(true, OK);
7471 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7472
7473 TestCompletionCallback callback1;
7474
[email protected]0b0bf032010-09-21 18:08:507475 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7476
[email protected]76a505b2010-08-25 06:23:007477 int rv = trans->Start(&request, &callback1, log.bound());
7478 EXPECT_EQ(ERR_IO_PENDING, rv);
7479
7480 rv = callback1.WaitForResult();
7481 EXPECT_EQ(OK, rv);
7482 size_t pos = ExpectLogContainsSomewhere(
7483 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7484 NetLog::PHASE_NONE);
7485 ExpectLogContainsSomewhere(
7486 log.entries(), pos,
7487 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7488 NetLog::PHASE_NONE);
7489
7490 const HttpResponseInfo* response = trans->GetResponseInfo();
7491 ASSERT_FALSE(response == NULL);
7492
7493 EXPECT_TRUE(response->headers->IsKeepAlive());
7494 EXPECT_EQ(200, response->headers->response_code());
7495 EXPECT_EQ(100, response->headers->GetContentLength());
7496 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7497 EXPECT_TRUE(response->was_fetched_via_proxy);
7498}
7499
7500// Test a basic HTTPS GET request through a proxy, but the server hangs up
7501// while establishing the tunnel.
7502TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:007503 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007504 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7505 session_deps.net_log = log.bound().net_log();
7506 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7507
[email protected]76a505b2010-08-25 06:23:007508 HttpRequestInfo request;
7509 request.method = "GET";
7510 request.url = GURL("https://www.google.com/");
7511
7512 // Since we have proxy, should try to establish tunnel.
7513 MockWrite data_writes1[] = {
7514 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7515 "Host: www.google.com\r\n"
7516 "Proxy-Connection: keep-alive\r\n\r\n"),
7517
7518 MockWrite("GET / HTTP/1.1\r\n"
7519 "Host: www.google.com\r\n"
7520 "Connection: keep-alive\r\n\r\n"),
7521 };
7522
7523 MockRead data_reads1[] = {
7524 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7525 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7526 MockRead(true, 0, 0), // EOF
7527 };
7528
7529 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7530 data_writes1, arraysize(data_writes1));
7531 session_deps.socket_factory.AddSocketDataProvider(&data1);
7532 SSLSocketDataProvider ssl(true, OK);
7533 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7534
7535 TestCompletionCallback callback1;
7536
[email protected]0b0bf032010-09-21 18:08:507537 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7538
[email protected]76a505b2010-08-25 06:23:007539 int rv = trans->Start(&request, &callback1, log.bound());
7540 EXPECT_EQ(ERR_IO_PENDING, rv);
7541
7542 rv = callback1.WaitForResult();
7543 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7544 size_t pos = ExpectLogContainsSomewhere(
7545 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7546 NetLog::PHASE_NONE);
7547 ExpectLogContainsSomewhere(
7548 log.entries(), pos,
7549 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7550 NetLog::PHASE_NONE);
7551}
7552
[email protected]749eefa82010-09-13 22:14:037553// Test for crbug.com/55424.
7554TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7555 SessionDependencies session_deps;
7556
7557 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7558 "https://www.google.com", false, 1, LOWEST));
7559 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7560
7561 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7562 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7563 MockRead spdy_reads[] = {
7564 CreateMockRead(*resp),
7565 CreateMockRead(*data),
7566 MockRead(true, 0, 0),
7567 };
7568
7569 scoped_refptr<DelayedSocketData> spdy_data(
7570 new DelayedSocketData(
7571 1, // wait for one write to finish before reading.
7572 spdy_reads, arraysize(spdy_reads),
7573 spdy_writes, arraysize(spdy_writes)));
7574 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7575
7576 SSLSocketDataProvider ssl(true, OK);
7577 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7578 ssl.next_proto = "spdy/2";
7579 ssl.was_npn_negotiated = true;
7580 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7581
7582 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7583
7584 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387585 HostPortPair host_port_pair("www.google.com", 443);
7586 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037587 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277588 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7589 BoundNetLog());
[email protected]749eefa82010-09-13 22:14:037590 scoped_refptr<TCPSocketParams> tcp_params =
7591 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:387592 TestCompletionCallback callback;
7593
7594 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7595 EXPECT_EQ(ERR_IO_PENDING,
7596 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7597 &callback, session->tcp_socket_pool(),
7598 BoundNetLog()));
7599 EXPECT_EQ(OK, callback.WaitForResult());
7600 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037601
7602 HttpRequestInfo request;
7603 request.method = "GET";
7604 request.url = GURL("https://www.google.com/");
7605 request.load_flags = 0;
7606
7607 // This is the important line that marks this as a preconnect.
7608 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7609
7610 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7611
[email protected]749eefa82010-09-13 22:14:037612 int rv = trans->Start(&request, &callback, BoundNetLog());
7613 EXPECT_EQ(ERR_IO_PENDING, rv);
7614 EXPECT_EQ(OK, callback.WaitForResult());
7615}
7616
[email protected]89ceba9a2009-03-21 03:46:067617} // namespace net