blob: 9985d94294546dbc1e1b07662abbab62b7316587 [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]169d0012010-05-10 23:20:1215#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3217#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/net_log.h"
19#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3120#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4221#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "net/base/test_completion_callback.h"
24#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1225#include "net/http/http_auth_handler_digest.h"
[email protected]385a4672009-03-11 22:21:2926#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5727#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5228#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5729#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5331#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1132#include "net/proxy/proxy_resolver.h"
33#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4434#include "net/socket/client_socket_factory.h"
35#include "net/socket/socket_test_util.h"
36#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5437#include "net/spdy/spdy_framer.h"
38#include "net/spdy/spdy_session.h"
39#include "net/spdy/spdy_session_pool.h"
40#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5241#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1542#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5243
44//-----------------------------------------------------------------------------
45
[email protected]89ceba9a2009-03-21 03:46:0646namespace net {
47
[email protected]2d731a32010-04-29 01:04:0648class HttpNetworkSessionPeer {
49 public:
50 explicit HttpNetworkSessionPeer(
51 const scoped_refptr<HttpNetworkSession>& session)
52 : session_(session) {}
53
54 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
55 session_->tcp_socket_pool_ = pool;
56 }
57
58 void SetSocketPoolForSOCKSProxy(
59 const HostPortPair& socks_proxy,
60 const scoped_refptr<SOCKSClientSocketPool>& pool) {
61 session_->socks_socket_pool_[socks_proxy] = pool;
62 }
63
64 void SetSocketPoolForHTTPProxy(
65 const HostPortPair& http_proxy,
66 const scoped_refptr<TCPClientSocketPool>& pool) {
67 session_->http_proxy_socket_pool_[http_proxy] = pool;
68 }
69
70 private:
71 const scoped_refptr<HttpNetworkSession> session_;
72
73 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
74};
75
[email protected]e44de5d2009-06-05 20:12:4576// Helper to manage the lifetimes of the dependencies for a
77// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5978class SessionDependencies {
79 public:
80 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4281 SessionDependencies()
82 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3783 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1084 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]d510a782010-05-17 05:35:0685 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()) {}
[email protected]228ff742009-06-05 01:19:5986
87 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4588 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4289 : host_resolver(new MockHostResolver),
90 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1091 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]d510a782010-05-17 05:35:0692 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()) {}
[email protected]228ff742009-06-05 01:19:5993
[email protected]a2c2fb92009-07-18 07:31:0494 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0995 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4296 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5997 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5098 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]228ff742009-06-05 01:19:5999};
100
[email protected]1c773ea12009-04-28 19:58:42101ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50102 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48103 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39104 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53105}
106
[email protected]228ff742009-06-05 01:19:59107HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:51108 return new HttpNetworkSession(NULL,
109 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09110 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42111 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10112 session_deps->ssl_config_service,
[email protected]fa55e192010-02-15 14:25:50113 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:14114}
115
[email protected]89836e22008-09-25 20:33:42116class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52117 public:
[email protected]2ff8b312010-04-26 22:20:54118 virtual void SetUp() {
119 spdy::SpdyFramer::set_enable_compression_default(false);
120 }
121
[email protected]0e75a732008-10-16 20:36:09122 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54123 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09124 // Empty the current queue.
125 MessageLoop::current()->RunAllPending();
126 PlatformTest::TearDown();
127 }
128
[email protected]3d2a59b2008-09-26 19:44:25129 protected:
130 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52131
[email protected]ff007e162009-05-23 09:13:15132 struct SimpleGetHelperResult {
133 int rv;
134 std::string status_line;
135 std::string response_data;
136 };
initial.commit586acc5fe2008-07-26 22:42:52137
[email protected]31a2bfe2010-02-09 08:03:39138 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
139 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15140 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52141
[email protected]228ff742009-06-05 01:19:59142 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40143 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43144 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]ff007e162009-05-23 09:13:15146 HttpRequestInfo request;
147 request.method = "GET";
148 request.url = GURL("http://www.google.com/");
149 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]31a2bfe2010-02-09 08:03:39151 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59152 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]ff007e162009-05-23 09:13:15154 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]169d0012010-05-10 23:20:12156 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
157 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15158 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52159
[email protected]ff007e162009-05-23 09:13:15160 out.rv = callback.WaitForResult();
161 if (out.rv != OK)
162 return out;
163
164 const HttpResponseInfo* response = trans->GetResponseInfo();
165 EXPECT_TRUE(response != NULL);
166
167 EXPECT_TRUE(response->headers != NULL);
168 out.status_line = response->headers->GetStatusLine();
169
170 rv = ReadTransaction(trans.get(), &out.response_data);
171 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39172 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12173 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
174 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39175 ExpectLogContainsSomewhere(
176 log.entries(), pos,
177 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
178 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15179
[email protected]aecfbf22008-10-16 02:02:47180 return out;
[email protected]ff007e162009-05-23 09:13:15181 }
initial.commit586acc5fe2008-07-26 22:42:52182
[email protected]ff007e162009-05-23 09:13:15183 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
184 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52185
[email protected]ff007e162009-05-23 09:13:15186 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15187};
[email protected]231d5a32008-09-13 00:45:27188
[email protected]15a5ccf82008-10-23 19:57:43189// Fill |str| with a long header list that consumes >= |size| bytes.
190void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19191 const char* row =
192 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
193 const int sizeof_row = strlen(row);
194 const int num_rows = static_cast<int>(
195 ceil(static_cast<float>(size) / sizeof_row));
196 const int sizeof_data = num_rows * sizeof_row;
197 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43198 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51199
[email protected]4ddaf2502008-10-23 18:26:19200 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43201 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19202}
203
[email protected]385a4672009-03-11 22:21:29204// Alternative functions that eliminate randomness and dependency on the local
205// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20206void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29207 static const uint8 bytes[] = {
208 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
209 };
210 static size_t current_byte = 0;
211 for (size_t i = 0; i < n; ++i) {
212 output[i] = bytes[current_byte++];
213 current_byte %= arraysize(bytes);
214 }
215}
216
[email protected]fe2bc6a2009-03-23 16:52:20217void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29218 static const uint8 bytes[] = {
219 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
220 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
221 };
222 static size_t current_byte = 0;
223 for (size_t i = 0; i < n; ++i) {
224 output[i] = bytes[current_byte++];
225 current_byte %= arraysize(bytes);
226 }
227}
228
[email protected]fe2bc6a2009-03-23 16:52:20229std::string MockGetHostName() {
230 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29231}
232
[email protected]2d731a32010-04-29 01:04:06233template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26234class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31235 public:
[email protected]2d731a32010-04-29 01:04:06236 CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]a796bcec2010-03-22 17:17:26237 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
[email protected]d510a782010-05-17 05:35:06238 session->host_resolver(), NULL) {}
[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,
253 const ClientSocketHandle* handle) { }
254 virtual void ReleaseSocket(const std::string& group_name,
255 ClientSocket* socket) {}
256 virtual void CloseIdleSockets() {}
257 virtual HostResolver* GetHostResolver() const {
258 return NULL;
259 }
260 virtual int IdleSocketCount() const {
261 return 0;
262 }
263 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
264 return 0;
265 }
266 virtual LoadState GetLoadState(const std::string& group_name,
267 const ClientSocketHandle* handle) const {
268 return LOAD_STATE_IDLE;
269 }
[email protected]a796bcec2010-03-22 17:17:26270 virtual base::TimeDelta ConnectionTimeout() const {
271 return base::TimeDelta();
272 }
[email protected]d80a4322009-08-14 07:07:49273
274 private:
[email protected]04e5be32009-06-26 20:00:31275 std::string last_group_name_;
276};
277
[email protected]2d731a32010-04-29 01:04:06278typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11279CaptureGroupNameTCPSocketPool;
[email protected]2d731a32010-04-29 01:04:06280typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11281CaptureGroupNameSOCKSSocketPool;
282
[email protected]231d5a32008-09-13 00:45:27283//-----------------------------------------------------------------------------
284
285TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59286 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40287 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43288 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27289}
290
291TEST_F(HttpNetworkTransactionTest, SimpleGET) {
292 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35293 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
294 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42295 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27296 };
[email protected]31a2bfe2010-02-09 08:03:39297 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
298 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42299 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27300 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
301 EXPECT_EQ("hello world", out.response_data);
302}
303
304// Response with no status line.
305TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
306 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35307 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42308 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27309 };
[email protected]31a2bfe2010-02-09 08:03:39310 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
311 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42312 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27313 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
314 EXPECT_EQ("hello world", out.response_data);
315}
316
317// Allow up to 4 bytes of junk to precede status line.
318TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
319 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35320 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[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 404 Not Found", out.status_line);
327 EXPECT_EQ("DATA", out.response_data);
328}
329
330// Allow up to 4 bytes of junk to precede status line.
331TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
332 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35333 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[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/1.0 404 Not Found", out.status_line);
340 EXPECT_EQ("DATA", out.response_data);
341}
342
343// Beyond 4 bytes of slop and it should fail to find a status line.
344TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
345 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35346 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[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]3d2a59b2008-09-26 19:44:25352 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
353 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27354}
355
356// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
357TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
358 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35359 MockRead("\n"),
360 MockRead("\n"),
361 MockRead("Q"),
362 MockRead("J"),
363 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42364 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27365 };
[email protected]31a2bfe2010-02-09 08:03:39366 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
367 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42368 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27369 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
370 EXPECT_EQ("DATA", out.response_data);
371}
372
373// Close the connection before enough bytes to have a status line.
374TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
375 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35376 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42377 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27378 };
[email protected]31a2bfe2010-02-09 08:03:39379 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
380 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42381 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27382 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
383 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52384}
385
[email protected]f9d44aa2008-09-23 23:57:17386// Simulate a 204 response, lacking a Content-Length header, sent over a
387// persistent connection. The response should still terminate since a 204
388// cannot have a response body.
389TEST_F(HttpNetworkTransactionTest, StopsReading204) {
390 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35391 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
392 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42393 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17394 };
[email protected]31a2bfe2010-02-09 08:03:39395 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
396 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42397 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17398 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
399 EXPECT_EQ("", out.response_data);
400}
401
[email protected]0877e3d2009-10-17 22:29:57402// A simple request using chunked encoding with some extra data after.
403// (Like might be seen in a pipelined response.)
404TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
405 MockRead data_reads[] = {
406 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
407 MockRead("5\r\nHello\r\n"),
408 MockRead("1\r\n"),
409 MockRead(" \r\n"),
410 MockRead("5\r\nworld\r\n"),
411 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
412 MockRead(false, OK),
413 };
[email protected]31a2bfe2010-02-09 08:03:39414 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
415 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57416 EXPECT_EQ(OK, out.rv);
417 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
418 EXPECT_EQ("Hello world", out.response_data);
419}
420
[email protected]ef0faf2e72009-03-05 23:27:23421// Do a request using the HEAD method. Verify that we don't try to read the
422// message body (since HEAD has none).
423TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59424 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40425 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43426 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23427
[email protected]1c773ea12009-04-28 19:58:42428 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23429 request.method = "HEAD";
430 request.url = GURL("http://www.google.com/");
431 request.load_flags = 0;
432
433 MockWrite data_writes1[] = {
434 MockWrite("HEAD / HTTP/1.1\r\n"
435 "Host: www.google.com\r\n"
436 "Connection: keep-alive\r\n"
437 "Content-Length: 0\r\n\r\n"),
438 };
439 MockRead data_reads1[] = {
440 MockRead("HTTP/1.1 404 Not Found\r\n"),
441 MockRead("Server: Blah\r\n"),
442 MockRead("Content-Length: 1234\r\n\r\n"),
443
444 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42445 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23446 };
447
[email protected]31a2bfe2010-02-09 08:03:39448 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
449 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59450 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23451
452 TestCompletionCallback callback1;
453
[email protected]5a1d7ca2010-04-28 20:12:27454 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42455 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23456
457 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42458 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23459
[email protected]1c773ea12009-04-28 19:58:42460 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23461 EXPECT_FALSE(response == NULL);
462
463 // Check that the headers got parsed.
464 EXPECT_TRUE(response->headers != NULL);
465 EXPECT_EQ(1234, response->headers->GetContentLength());
466 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
467
468 std::string server_header;
469 void* iter = NULL;
470 bool has_server_header = response->headers->EnumerateHeader(
471 &iter, "Server", &server_header);
472 EXPECT_TRUE(has_server_header);
473 EXPECT_EQ("Blah", server_header);
474
475 // Reading should give EOF right away, since there is no message body
476 // (despite non-zero content-length).
477 std::string response_data;
478 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42479 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23480 EXPECT_EQ("", response_data);
481}
482
initial.commit586acc5fe2008-07-26 22:42:52483TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59484 SessionDependencies session_deps;
485 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52486
487 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35488 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
489 MockRead("hello"),
490 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
491 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42492 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52493 };
[email protected]31a2bfe2010-02-09 08:03:39494 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59495 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52496
497 const char* kExpectedResponseData[] = {
498 "hello", "world"
499 };
500
501 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43502 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52503
[email protected]1c773ea12009-04-28 19:58:42504 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52505 request.method = "GET";
506 request.url = GURL("http://www.google.com/");
507 request.load_flags = 0;
508
509 TestCompletionCallback callback;
510
[email protected]5a1d7ca2010-04-28 20:12:27511 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42512 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52513
514 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42515 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52516
[email protected]1c773ea12009-04-28 19:58:42517 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52518 EXPECT_TRUE(response != NULL);
519
520 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25521 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52522
523 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57524 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42525 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25526 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52527 }
528}
529
530TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59531 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40532 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43533 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52534
[email protected]1c773ea12009-04-28 19:58:42535 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52536 request.method = "POST";
537 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42538 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52539 request.upload_data->AppendBytes("foo", 3);
540 request.load_flags = 0;
541
542 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35543 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
544 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
545 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42546 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52547 };
[email protected]31a2bfe2010-02-09 08:03:39548 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59549 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52550
551 TestCompletionCallback callback;
552
[email protected]5a1d7ca2010-04-28 20:12:27553 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42554 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52555
556 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42557 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52558
[email protected]1c773ea12009-04-28 19:58:42559 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52560 EXPECT_TRUE(response != NULL);
561
562 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25563 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52564
565 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57566 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42567 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25568 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52569}
570
[email protected]3a2d3662009-03-27 03:49:14571// This test is almost the same as Ignores100 above, but the response contains
572// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57573// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14574TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59575 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40576 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43577 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14578
[email protected]1c773ea12009-04-28 19:58:42579 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14580 request.method = "GET";
581 request.url = GURL("http://www.foo.com/");
582 request.load_flags = 0;
583
584 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57585 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
586 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14587 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42588 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14589 };
[email protected]31a2bfe2010-02-09 08:03:39590 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59591 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14592
593 TestCompletionCallback callback;
594
[email protected]5a1d7ca2010-04-28 20:12:27595 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42596 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14597
598 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42599 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14600
[email protected]1c773ea12009-04-28 19:58:42601 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14602 EXPECT_TRUE(response != NULL);
603
604 EXPECT_TRUE(response->headers != NULL);
605 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
606
607 std::string response_data;
608 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42609 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14610 EXPECT_EQ("hello world", response_data);
611}
612
[email protected]ee9410e72010-01-07 01:42:38613TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
614 SessionDependencies session_deps;
615 scoped_ptr<HttpTransaction> trans(
616 new HttpNetworkTransaction(CreateSession(&session_deps)));
617
618 HttpRequestInfo request;
619 request.method = "POST";
620 request.url = GURL("http://www.foo.com/");
621 request.load_flags = 0;
622
623 MockRead data_reads[] = {
624 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
625 MockRead(true, 0),
626 };
[email protected]31a2bfe2010-02-09 08:03:39627 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38628 session_deps.socket_factory.AddSocketDataProvider(&data);
629
630 TestCompletionCallback callback;
631
[email protected]5a1d7ca2010-04-28 20:12:27632 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38633 EXPECT_EQ(ERR_IO_PENDING, rv);
634
635 rv = callback.WaitForResult();
636 EXPECT_EQ(OK, rv);
637
638 std::string response_data;
639 rv = ReadTransaction(trans.get(), &response_data);
640 EXPECT_EQ(OK, rv);
641 EXPECT_EQ("", response_data);
642}
643
644TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
645 SessionDependencies session_deps;
646 scoped_ptr<HttpTransaction> trans(
647 new HttpNetworkTransaction(CreateSession(&session_deps)));
648
649 HttpRequestInfo request;
650 request.method = "POST";
651 request.url = GURL("http://www.foo.com/");
652 request.load_flags = 0;
653
654 MockRead data_reads[] = {
655 MockRead(true, 0),
656 };
[email protected]31a2bfe2010-02-09 08:03:39657 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38658 session_deps.socket_factory.AddSocketDataProvider(&data);
659
660 TestCompletionCallback callback;
661
[email protected]5a1d7ca2010-04-28 20:12:27662 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38663 EXPECT_EQ(ERR_IO_PENDING, rv);
664
665 rv = callback.WaitForResult();
666 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
667}
668
[email protected]3d2a59b2008-09-26 19:44:25669// read_failure specifies a read failure that should cause the network
670// transaction to resend the request.
671void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
672 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59673 SessionDependencies session_deps;
674 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52675
[email protected]1c773ea12009-04-28 19:58:42676 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52677 request.method = "GET";
678 request.url = GURL("http://www.foo.com/");
679 request.load_flags = 0;
680
681 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35682 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
683 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25684 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52685 };
[email protected]31a2bfe2010-02-09 08:03:39686 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59687 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52688
689 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35690 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
691 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42692 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52693 };
[email protected]31a2bfe2010-02-09 08:03:39694 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59695 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52696
697 const char* kExpectedResponseData[] = {
698 "hello", "world"
699 };
700
701 for (int i = 0; i < 2; ++i) {
702 TestCompletionCallback callback;
703
[email protected]5695b8c2009-09-30 21:36:43704 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52705
[email protected]5a1d7ca2010-04-28 20:12:27706 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42707 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52708
709 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42710 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52711
[email protected]1c773ea12009-04-28 19:58:42712 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52713 EXPECT_TRUE(response != NULL);
714
715 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25716 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52717
718 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57719 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42720 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25721 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52722 }
723}
[email protected]3d2a59b2008-09-26 19:44:25724
725TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42726 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25727 KeepAliveConnectionResendRequestTest(read_failure);
728}
729
730TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42731 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25732 KeepAliveConnectionResendRequestTest(read_failure);
733}
734
735TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59736 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40737 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43738 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25739
[email protected]1c773ea12009-04-28 19:58:42740 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25741 request.method = "GET";
742 request.url = GURL("http://www.google.com/");
743 request.load_flags = 0;
744
745 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42746 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35747 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
748 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42749 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25750 };
[email protected]31a2bfe2010-02-09 08:03:39751 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59752 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25753
754 TestCompletionCallback callback;
755
[email protected]5a1d7ca2010-04-28 20:12:27756 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42757 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25758
759 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42760 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25761
[email protected]1c773ea12009-04-28 19:58:42762 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25763 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25764}
765
766// What do various browsers do when the server closes a non-keepalive
767// connection without sending any response header or body?
768//
769// IE7: error page
770// Safari 3.1.2 (Windows): error page
771// Firefox 3.0.1: blank page
772// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42773// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
774// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25775TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
776 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42777 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35778 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
779 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42780 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25781 };
[email protected]31a2bfe2010-02-09 08:03:39782 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
783 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42784 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25785}
[email protected]038e9a32008-10-08 22:40:16786
787// Test the request-challenge-retry sequence for basic auth.
788// (basic auth is the easiest to mock, because it has no randomness).
789TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59790 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40791 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43792 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16793
[email protected]1c773ea12009-04-28 19:58:42794 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16795 request.method = "GET";
796 request.url = GURL("http://www.google.com/");
797 request.load_flags = 0;
798
[email protected]f9ee6b52008-11-08 06:46:23799 MockWrite data_writes1[] = {
800 MockWrite("GET / HTTP/1.1\r\n"
801 "Host: www.google.com\r\n"
802 "Connection: keep-alive\r\n\r\n"),
803 };
804
[email protected]038e9a32008-10-08 22:40:16805 MockRead data_reads1[] = {
806 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
807 // Give a couple authenticate options (only the middle one is actually
808 // supported).
[email protected]22927ad2009-09-21 19:56:19809 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16810 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
811 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
812 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
813 // Large content-length -- won't matter, as connection will be reset.
814 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42815 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16816 };
817
818 // After calling trans->RestartWithAuth(), this is the request we should
819 // be issuing -- the final header line contains the credentials.
820 MockWrite data_writes2[] = {
821 MockWrite("GET / HTTP/1.1\r\n"
822 "Host: www.google.com\r\n"
823 "Connection: keep-alive\r\n"
824 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
825 };
826
827 // Lastly, the server responds with the actual content.
828 MockRead data_reads2[] = {
829 MockRead("HTTP/1.0 200 OK\r\n"),
830 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
831 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42832 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16833 };
834
[email protected]31a2bfe2010-02-09 08:03:39835 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
836 data_writes1, arraysize(data_writes1));
837 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
838 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59839 session_deps.socket_factory.AddSocketDataProvider(&data1);
840 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16841
842 TestCompletionCallback callback1;
843
[email protected]5a1d7ca2010-04-28 20:12:27844 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42845 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16846
847 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42848 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16849
[email protected]1c773ea12009-04-28 19:58:42850 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16851 EXPECT_FALSE(response == NULL);
852
853 // The password prompt info should have been set in response->auth_challenge.
854 EXPECT_FALSE(response->auth_challenge.get() == NULL);
855
[email protected]71e4573a2009-05-21 22:03:00856 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16857 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
858 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
859
860 TestCompletionCallback callback2;
861
862 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42863 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16864
865 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42866 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16867
868 response = trans->GetResponseInfo();
869 EXPECT_FALSE(response == NULL);
870 EXPECT_TRUE(response->auth_challenge.get() == NULL);
871 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16872}
873
[email protected]861fcd52009-08-26 02:33:46874TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
875 SessionDependencies session_deps;
876 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43877 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46878
879 HttpRequestInfo request;
880 request.method = "GET";
881 request.url = GURL("http://www.google.com/");
882 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
883
884 MockWrite data_writes[] = {
885 MockWrite("GET / HTTP/1.1\r\n"
886 "Host: www.google.com\r\n"
887 "Connection: keep-alive\r\n\r\n"),
888 };
889
890 MockRead data_reads[] = {
891 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
892 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
893 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
894 // Large content-length -- won't matter, as connection will be reset.
895 MockRead("Content-Length: 10000\r\n\r\n"),
896 MockRead(false, ERR_FAILED),
897 };
898
[email protected]31a2bfe2010-02-09 08:03:39899 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
900 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59901 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46902 TestCompletionCallback callback;
903
[email protected]5a1d7ca2010-04-28 20:12:27904 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46905 EXPECT_EQ(ERR_IO_PENDING, rv);
906
907 rv = callback.WaitForResult();
908 EXPECT_EQ(0, rv);
909
910 const HttpResponseInfo* response = trans->GetResponseInfo();
911 ASSERT_FALSE(response == NULL);
912 EXPECT_TRUE(response->auth_challenge.get() == NULL);
913}
914
[email protected]2d2697f92009-02-18 21:00:32915// Test the request-challenge-retry sequence for basic auth, over a keep-alive
916// connection.
917TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59918 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40919 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43920 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32921
[email protected]1c773ea12009-04-28 19:58:42922 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32923 request.method = "GET";
924 request.url = GURL("http://www.google.com/");
925 request.load_flags = 0;
926
927 MockWrite data_writes1[] = {
928 MockWrite("GET / HTTP/1.1\r\n"
929 "Host: www.google.com\r\n"
930 "Connection: keep-alive\r\n\r\n"),
931
932 // After calling trans->RestartWithAuth(), this is the request we should
933 // be issuing -- the final header line contains the credentials.
934 MockWrite("GET / HTTP/1.1\r\n"
935 "Host: www.google.com\r\n"
936 "Connection: keep-alive\r\n"
937 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
938 };
939
940 MockRead data_reads1[] = {
941 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
942 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
943 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
944 MockRead("Content-Length: 14\r\n\r\n"),
945 MockRead("Unauthorized\r\n"),
946
947 // Lastly, the server responds with the actual content.
948 MockRead("HTTP/1.1 200 OK\r\n"),
949 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
950 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42951 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32952 };
953
[email protected]31a2bfe2010-02-09 08:03:39954 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
955 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59956 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32957
958 TestCompletionCallback callback1;
959
[email protected]5a1d7ca2010-04-28 20:12:27960 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42961 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32962
963 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42964 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32965
[email protected]1c773ea12009-04-28 19:58:42966 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32967 EXPECT_FALSE(response == NULL);
968
969 // The password prompt info should have been set in response->auth_challenge.
970 EXPECT_FALSE(response->auth_challenge.get() == NULL);
971
[email protected]71e4573a2009-05-21 22:03:00972 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32973 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
974 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
975
976 TestCompletionCallback callback2;
977
978 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42979 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32980
981 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42982 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32983
984 response = trans->GetResponseInfo();
985 EXPECT_FALSE(response == NULL);
986 EXPECT_TRUE(response->auth_challenge.get() == NULL);
987 EXPECT_EQ(100, response->headers->GetContentLength());
988}
989
990// Test the request-challenge-retry sequence for basic auth, over a keep-alive
991// connection and with no response body to drain.
992TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59993 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40994 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43995 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32996
[email protected]1c773ea12009-04-28 19:58:42997 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32998 request.method = "GET";
999 request.url = GURL("http://www.google.com/");
1000 request.load_flags = 0;
1001
1002 MockWrite data_writes1[] = {
1003 MockWrite("GET / HTTP/1.1\r\n"
1004 "Host: www.google.com\r\n"
1005 "Connection: keep-alive\r\n\r\n"),
1006
1007 // After calling trans->RestartWithAuth(), this is the request we should
1008 // be issuing -- the final header line contains the credentials.
1009 MockWrite("GET / HTTP/1.1\r\n"
1010 "Host: www.google.com\r\n"
1011 "Connection: keep-alive\r\n"
1012 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1013 };
1014
[email protected]2d2697f92009-02-18 21:00:321015 MockRead data_reads1[] = {
1016 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1017 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311018 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321019
1020 // Lastly, the server responds with the actual content.
1021 MockRead("HTTP/1.1 200 OK\r\n"),
1022 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1023 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421024 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321025 };
1026
[email protected]31a2bfe2010-02-09 08:03:391027 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1028 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591029 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321030
1031 TestCompletionCallback callback1;
1032
[email protected]5a1d7ca2010-04-28 20:12:271033 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421034 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321035
1036 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421037 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321038
[email protected]1c773ea12009-04-28 19:58:421039 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321040 EXPECT_FALSE(response == NULL);
1041
1042 // The password prompt info should have been set in response->auth_challenge.
1043 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1044
[email protected]71e4573a2009-05-21 22:03:001045 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321046 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1047 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1048
1049 TestCompletionCallback callback2;
1050
1051 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421052 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321053
1054 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421055 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321056
1057 response = trans->GetResponseInfo();
1058 EXPECT_FALSE(response == NULL);
1059 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1060 EXPECT_EQ(100, response->headers->GetContentLength());
1061}
1062
1063// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1064// connection and with a large response body to drain.
1065TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591066 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401067 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431068 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321069
[email protected]1c773ea12009-04-28 19:58:421070 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321071 request.method = "GET";
1072 request.url = GURL("http://www.google.com/");
1073 request.load_flags = 0;
1074
1075 MockWrite data_writes1[] = {
1076 MockWrite("GET / HTTP/1.1\r\n"
1077 "Host: www.google.com\r\n"
1078 "Connection: keep-alive\r\n\r\n"),
1079
1080 // After calling trans->RestartWithAuth(), this is the request we should
1081 // be issuing -- the final header line contains the credentials.
1082 MockWrite("GET / HTTP/1.1\r\n"
1083 "Host: www.google.com\r\n"
1084 "Connection: keep-alive\r\n"
1085 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1086 };
1087
1088 // Respond with 5 kb of response body.
1089 std::string large_body_string("Unauthorized");
1090 large_body_string.append(5 * 1024, ' ');
1091 large_body_string.append("\r\n");
1092
1093 MockRead data_reads1[] = {
1094 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1095 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1097 // 5134 = 12 + 5 * 1024 + 2
1098 MockRead("Content-Length: 5134\r\n\r\n"),
1099 MockRead(true, large_body_string.data(), large_body_string.size()),
1100
1101 // Lastly, the server responds with the actual content.
1102 MockRead("HTTP/1.1 200 OK\r\n"),
1103 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1104 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421105 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321106 };
1107
[email protected]31a2bfe2010-02-09 08:03:391108 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1109 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591110 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321111
1112 TestCompletionCallback callback1;
1113
[email protected]5a1d7ca2010-04-28 20:12:271114 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421115 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321116
1117 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421118 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321119
[email protected]1c773ea12009-04-28 19:58:421120 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321121 EXPECT_FALSE(response == NULL);
1122
1123 // The password prompt info should have been set in response->auth_challenge.
1124 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1125
[email protected]71e4573a2009-05-21 22:03:001126 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321127 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1128 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1129
1130 TestCompletionCallback callback2;
1131
1132 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421133 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321134
1135 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421136 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321137
1138 response = trans->GetResponseInfo();
1139 EXPECT_FALSE(response == NULL);
1140 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1141 EXPECT_EQ(100, response->headers->GetContentLength());
1142}
1143
1144// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311145// connection, but the server gets impatient and closes the connection.
1146TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1147 SessionDependencies session_deps;
1148 scoped_ptr<HttpTransaction> trans(
1149 new HttpNetworkTransaction(CreateSession(&session_deps)));
1150
1151 HttpRequestInfo request;
1152 request.method = "GET";
1153 request.url = GURL("http://www.google.com/");
1154 request.load_flags = 0;
1155
1156 MockWrite data_writes1[] = {
1157 MockWrite("GET / HTTP/1.1\r\n"
1158 "Host: www.google.com\r\n"
1159 "Connection: keep-alive\r\n\r\n"),
1160 // This simulates the seemingly successful write to a closed connection
1161 // if the bug is not fixed.
1162 MockWrite("GET / HTTP/1.1\r\n"
1163 "Host: www.google.com\r\n"
1164 "Connection: keep-alive\r\n"
1165 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1166 };
1167
1168 MockRead data_reads1[] = {
1169 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1170 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1171 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1172 MockRead("Content-Length: 14\r\n\r\n"),
1173 // Tell MockTCPClientSocket to simulate the server closing the connection.
1174 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1175 MockRead("Unauthorized\r\n"),
1176 MockRead(false, OK), // The server closes the connection.
1177 };
1178
1179 // After calling trans->RestartWithAuth(), this is the request we should
1180 // be issuing -- the final header line contains the credentials.
1181 MockWrite data_writes2[] = {
1182 MockWrite("GET / HTTP/1.1\r\n"
1183 "Host: www.google.com\r\n"
1184 "Connection: keep-alive\r\n"
1185 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1186 };
1187
1188 // Lastly, the server responds with the actual content.
1189 MockRead data_reads2[] = {
1190 MockRead("HTTP/1.1 200 OK\r\n"),
1191 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1192 MockRead("Content-Length: 100\r\n\r\n"),
1193 MockRead(false, OK),
1194 };
1195
[email protected]31a2bfe2010-02-09 08:03:391196 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1197 data_writes1, arraysize(data_writes1));
1198 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1199 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311200 session_deps.socket_factory.AddSocketDataProvider(&data1);
1201 session_deps.socket_factory.AddSocketDataProvider(&data2);
1202
1203 TestCompletionCallback callback1;
1204
[email protected]5a1d7ca2010-04-28 20:12:271205 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311206 EXPECT_EQ(ERR_IO_PENDING, rv);
1207
1208 rv = callback1.WaitForResult();
1209 EXPECT_EQ(OK, rv);
1210
1211 const HttpResponseInfo* response = trans->GetResponseInfo();
1212 EXPECT_FALSE(response == NULL);
1213
1214 // The password prompt info should have been set in response->auth_challenge.
1215 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1216
1217 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1218 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1219 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1220
1221 TestCompletionCallback callback2;
1222
1223 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1224 EXPECT_EQ(ERR_IO_PENDING, rv);
1225
1226 rv = callback2.WaitForResult();
1227 EXPECT_EQ(OK, rv);
1228
1229 response = trans->GetResponseInfo();
1230 ASSERT_FALSE(response == NULL);
1231 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1232 EXPECT_EQ(100, response->headers->GetContentLength());
1233}
1234
1235// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321236// proxy connection, when setting up an SSL tunnel.
1237TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1238 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591239 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1240 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321241
[email protected]5695b8c2009-09-30 21:36:431242 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321243
[email protected]1c773ea12009-04-28 19:58:421244 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321245 request.method = "GET";
1246 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461247 // Ensure that proxy authentication is attempted even
1248 // when the no authentication data flag is set.
1249 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321250
1251 // Since we have proxy, should try to establish tunnel.
1252 MockWrite data_writes1[] = {
1253 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451254 "Host: www.google.com\r\n"
1255 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321256
1257 // After calling trans->RestartWithAuth(), this is the request we should
1258 // be issuing -- the final header line contains the credentials.
1259 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1260 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451261 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321262 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1263 };
1264
1265 // The proxy responds to the connect with a 407, using a persistent
1266 // connection.
1267 MockRead data_reads1[] = {
1268 // No credentials.
1269 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1270 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1271 MockRead("Content-Length: 10\r\n\r\n"),
1272 MockRead("0123456789"),
1273
1274 // Wrong credentials (wrong password).
1275 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1276 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1277 MockRead("Content-Length: 10\r\n\r\n"),
1278 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421279 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321280 };
1281
[email protected]31a2bfe2010-02-09 08:03:391282 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1283 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591284 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321285
1286 TestCompletionCallback callback1;
1287
[email protected]dbb83db2010-05-11 18:13:391288 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1289 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421290 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321291
1292 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421293 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391294 size_t pos = ExpectLogContainsSomewhere(
1295 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1296 NetLog::PHASE_NONE);
1297 ExpectLogContainsSomewhere(
1298 log.entries(), pos,
1299 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1300 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321301
[email protected]1c773ea12009-04-28 19:58:421302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321303 EXPECT_FALSE(response == NULL);
1304
1305 EXPECT_TRUE(response->headers->IsKeepAlive());
1306 EXPECT_EQ(407, response->headers->response_code());
1307 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421308 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321309
1310 // The password prompt info should have been set in response->auth_challenge.
1311 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1312
[email protected]71e4573a2009-05-21 22:03:001313 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321314 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1315 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1316
1317 TestCompletionCallback callback2;
1318
1319 // Wrong password (should be "bar").
1320 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421321 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321322
1323 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421324 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321325
1326 response = trans->GetResponseInfo();
1327 EXPECT_FALSE(response == NULL);
1328
1329 EXPECT_TRUE(response->headers->IsKeepAlive());
1330 EXPECT_EQ(407, response->headers->response_code());
1331 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421332 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321333
1334 // The password prompt info should have been set in response->auth_challenge.
1335 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1336
[email protected]71e4573a2009-05-21 22:03:001337 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321338 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1339 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1340}
1341
[email protected]a8e9b162009-03-12 00:06:441342// Test that we don't read the response body when we fail to establish a tunnel,
1343// even if the user cancels the proxy's auth attempt.
1344TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1345 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591346 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441347
[email protected]e44de5d2009-06-05 20:12:451348 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441349
[email protected]5695b8c2009-09-30 21:36:431350 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441351
[email protected]1c773ea12009-04-28 19:58:421352 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441353 request.method = "GET";
1354 request.url = GURL("https://www.google.com/");
1355 request.load_flags = 0;
1356
1357 // Since we have proxy, should try to establish tunnel.
1358 MockWrite data_writes[] = {
1359 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451360 "Host: www.google.com\r\n"
1361 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441362 };
1363
1364 // The proxy responds to the connect with a 407.
1365 MockRead data_reads[] = {
1366 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1367 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1368 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421369 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441370 };
1371
[email protected]31a2bfe2010-02-09 08:03:391372 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1373 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591374 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441375
1376 TestCompletionCallback callback;
1377
[email protected]5a1d7ca2010-04-28 20:12:271378 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421379 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441380
1381 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421382 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441383
[email protected]1c773ea12009-04-28 19:58:421384 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441385 EXPECT_FALSE(response == NULL);
1386
1387 EXPECT_TRUE(response->headers->IsKeepAlive());
1388 EXPECT_EQ(407, response->headers->response_code());
1389 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421390 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441391
1392 std::string response_data;
1393 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421394 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441395}
1396
[email protected]8fdbcd22010-05-05 02:54:521397// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1398// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1399TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1400 // We are using a DIRECT connection (i.e. no proxy) for this session.
1401 SessionDependencies session_deps;
1402 scoped_ptr<HttpTransaction> trans(
1403 new HttpNetworkTransaction(CreateSession(&session_deps)));
1404
1405 HttpRequestInfo request;
1406 request.method = "GET";
1407 request.url = GURL("http://www.google.com/");
1408 request.load_flags = 0;
1409
1410 MockWrite data_writes1[] = {
1411 MockWrite("GET / HTTP/1.1\r\n"
1412 "Host: www.google.com\r\n"
1413 "Connection: keep-alive\r\n\r\n"),
1414 };
1415
1416 MockRead data_reads1[] = {
1417 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1418 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1419 // Large content-length -- won't matter, as connection will be reset.
1420 MockRead("Content-Length: 10000\r\n\r\n"),
1421 MockRead(false, ERR_FAILED),
1422 };
1423
1424 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1425 data_writes1, arraysize(data_writes1));
1426 session_deps.socket_factory.AddSocketDataProvider(&data1);
1427
1428 TestCompletionCallback callback;
1429
1430 int rv = trans->Start(&request, &callback, BoundNetLog());
1431 EXPECT_EQ(ERR_IO_PENDING, rv);
1432
1433 rv = callback.WaitForResult();
1434 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1435}
1436
[email protected]ff007e162009-05-23 09:13:151437void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081438 const MockRead& status, int expected_status) {
1439 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591440 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081441
[email protected]228ff742009-06-05 01:19:591442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081443
[email protected]5695b8c2009-09-30 21:36:431444 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081445
[email protected]1c773ea12009-04-28 19:58:421446 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081447 request.method = "GET";
1448 request.url = GURL("https://www.google.com/");
1449 request.load_flags = 0;
1450
1451 // Since we have proxy, should try to establish tunnel.
1452 MockWrite data_writes[] = {
1453 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451454 "Host: www.google.com\r\n"
1455 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081456 };
1457
1458 MockRead data_reads[] = {
1459 status,
1460 MockRead("Content-Length: 10\r\n\r\n"),
1461 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421462 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081463 };
1464
[email protected]31a2bfe2010-02-09 08:03:391465 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1466 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591467 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081468
1469 TestCompletionCallback callback;
1470
[email protected]5a1d7ca2010-04-28 20:12:271471 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421472 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081473
1474 rv = callback.WaitForResult();
1475 EXPECT_EQ(expected_status, rv);
1476}
1477
[email protected]ff007e162009-05-23 09:13:151478void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081479 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421480 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081481}
1482
1483TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1484 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1485}
1486
1487TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1488 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1489}
1490
1491TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1492 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1500 ConnectStatusHelper(
1501 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1502}
1503
1504TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1505 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1506}
1507
1508TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1509 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1510}
1511
1512TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1513 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1514}
1515
1516TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1517 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1518}
1519
1520TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1521 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1522}
1523
1524TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1525 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1526}
1527
1528TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1529 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1534}
1535
1536TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1537 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1538}
1539
1540TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1541 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1542}
1543
1544TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1545 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1546}
1547
1548TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1549 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1550}
1551
1552TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1553 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1554}
1555
1556TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1557 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1558}
1559
1560TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1561 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1562}
1563
1564TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1565 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1566}
1567
1568TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1569 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1570}
1571
1572TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1573 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1574}
1575
1576TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1577 ConnectStatusHelperWithExpectedStatus(
1578 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421579 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081580}
1581
1582TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1583 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1584}
1585
1586TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1587 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1588}
1589
1590TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1591 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1592}
1593
1594TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1595 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1596}
1597
1598TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1599 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1600}
1601
1602TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1603 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1604}
1605
1606TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1607 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1608}
1609
1610TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1611 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1612}
1613
1614TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1615 ConnectStatusHelper(
1616 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1617}
1618
1619TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1620 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1621}
1622
1623TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1624 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1625}
1626
1627TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1628 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1629}
1630
1631TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1632 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1633}
1634
1635TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1636 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1637}
1638
1639TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1640 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1641}
1642
1643TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1644 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1645}
1646
[email protected]038e9a32008-10-08 22:40:161647// Test the flow when both the proxy server AND origin server require
1648// authentication. Again, this uses basic auth for both since that is
1649// the simplest to mock.
1650TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591651 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011652
[email protected]038e9a32008-10-08 22:40:161653 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421654 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431655 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161656
[email protected]1c773ea12009-04-28 19:58:421657 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161658 request.method = "GET";
1659 request.url = GURL("http://www.google.com/");
1660 request.load_flags = 0;
1661
[email protected]f9ee6b52008-11-08 06:46:231662 MockWrite data_writes1[] = {
1663 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1664 "Host: www.google.com\r\n"
1665 "Proxy-Connection: keep-alive\r\n\r\n"),
1666 };
1667
[email protected]038e9a32008-10-08 22:40:161668 MockRead data_reads1[] = {
1669 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1670 // Give a couple authenticate options (only the middle one is actually
1671 // supported).
[email protected]22927ad2009-09-21 19:56:191672 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161673 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1674 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1676 // Large content-length -- won't matter, as connection will be reset.
1677 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421678 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161679 };
1680
1681 // After calling trans->RestartWithAuth() the first time, this is the
1682 // request we should be issuing -- the final header line contains the
1683 // proxy's credentials.
1684 MockWrite data_writes2[] = {
1685 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1686 "Host: www.google.com\r\n"
1687 "Proxy-Connection: keep-alive\r\n"
1688 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1689 };
1690
1691 // Now the proxy server lets the request pass through to origin server.
1692 // The origin server responds with a 401.
1693 MockRead data_reads2[] = {
1694 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1695 // Note: We are using the same realm-name as the proxy server. This is
1696 // completely valid, as realms are unique across hosts.
1697 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1698 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1699 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421700 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161701 };
1702
1703 // After calling trans->RestartWithAuth() the second time, we should send
1704 // the credentials for both the proxy and origin server.
1705 MockWrite data_writes3[] = {
1706 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1707 "Host: www.google.com\r\n"
1708 "Proxy-Connection: keep-alive\r\n"
1709 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1710 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1711 };
1712
1713 // Lastly we get the desired content.
1714 MockRead data_reads3[] = {
1715 MockRead("HTTP/1.0 200 OK\r\n"),
1716 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1717 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421718 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161719 };
1720
[email protected]31a2bfe2010-02-09 08:03:391721 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1722 data_writes1, arraysize(data_writes1));
1723 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1724 data_writes2, arraysize(data_writes2));
1725 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1726 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591727 session_deps.socket_factory.AddSocketDataProvider(&data1);
1728 session_deps.socket_factory.AddSocketDataProvider(&data2);
1729 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161730
1731 TestCompletionCallback callback1;
1732
[email protected]5a1d7ca2010-04-28 20:12:271733 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421734 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161735
1736 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421737 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161738
[email protected]1c773ea12009-04-28 19:58:421739 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161740 EXPECT_FALSE(response == NULL);
1741
1742 // The password prompt info should have been set in response->auth_challenge.
1743 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1744
[email protected]71e4573a2009-05-21 22:03:001745 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161746 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1747 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1748
1749 TestCompletionCallback callback2;
1750
1751 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421752 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161753
1754 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421755 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161756
1757 response = trans->GetResponseInfo();
1758 EXPECT_FALSE(response == NULL);
1759 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1760
[email protected]71e4573a2009-05-21 22:03:001761 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161762 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1763 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1764
1765 TestCompletionCallback callback3;
1766
1767 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421768 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161769
1770 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421771 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161772
1773 response = trans->GetResponseInfo();
1774 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1775 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161776}
[email protected]4ddaf2502008-10-23 18:26:191777
[email protected]ea9dc9a2009-09-05 00:43:321778// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1779// can't hook into its internals to cause it to generate predictable NTLM
1780// authorization headers.
1781#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291782// The NTLM authentication unit tests were generated by capturing the HTTP
1783// requests and responses using Fiddler 2 and inspecting the generated random
1784// bytes in the debugger.
1785
1786// Enter the correct password and authenticate successfully.
1787TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421788 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111789 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591790 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401791 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431792 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241793
[email protected]1c773ea12009-04-28 19:58:421794 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241795 request.method = "GET";
1796 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1797 request.load_flags = 0;
1798
1799 MockWrite data_writes1[] = {
1800 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1801 "Host: 172.22.68.17\r\n"
1802 "Connection: keep-alive\r\n\r\n"),
1803 };
1804
1805 MockRead data_reads1[] = {
1806 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1807 // Negotiate and NTLM are often requested together. We only support NTLM.
1808 MockRead("WWW-Authenticate: Negotiate\r\n"),
1809 MockRead("WWW-Authenticate: NTLM\r\n"),
1810 MockRead("Connection: close\r\n"),
1811 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361812 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241813 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421814 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241815 };
1816
1817 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221818 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241819 // request we should be issuing -- the final header line contains a Type
1820 // 1 message.
1821 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1822 "Host: 172.22.68.17\r\n"
1823 "Connection: keep-alive\r\n"
1824 "Authorization: NTLM "
1825 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1826
1827 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1828 // (the credentials for the origin server). The second request continues
1829 // on the same connection.
1830 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1831 "Host: 172.22.68.17\r\n"
1832 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291833 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1834 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1835 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1836 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1837 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241838 };
1839
1840 MockRead data_reads2[] = {
1841 // The origin server responds with a Type 2 message.
1842 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1843 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291844 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241845 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1846 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1847 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1848 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1849 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1850 "BtAAAAAAA=\r\n"),
1851 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361852 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241853 MockRead("You are not authorized to view this page\r\n"),
1854
1855 // Lastly we get the desired content.
1856 MockRead("HTTP/1.1 200 OK\r\n"),
1857 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1858 MockRead("Content-Length: 13\r\n\r\n"),
1859 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421860 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241861 };
1862
[email protected]31a2bfe2010-02-09 08:03:391863 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1864 data_writes1, arraysize(data_writes1));
1865 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1866 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591867 session_deps.socket_factory.AddSocketDataProvider(&data1);
1868 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241869
1870 TestCompletionCallback callback1;
1871
[email protected]5a1d7ca2010-04-28 20:12:271872 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421873 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241874
1875 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421876 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241877
[email protected]0757e7702009-03-27 04:00:221878 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1879 TestCompletionCallback callback2;
1880 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421881 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221882 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421883 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221884 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1885
[email protected]1c773ea12009-04-28 19:58:421886 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241887 EXPECT_FALSE(response == NULL);
1888
1889 // The password prompt info should have been set in response->auth_challenge.
1890 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1891
[email protected]71e4573a2009-05-21 22:03:001892 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241893 EXPECT_EQ(L"", response->auth_challenge->realm);
1894 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1895
[email protected]0757e7702009-03-27 04:00:221896 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241897
[email protected]0757e7702009-03-27 04:00:221898 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421899 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241900
[email protected]0757e7702009-03-27 04:00:221901 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421902 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241903
1904 response = trans->GetResponseInfo();
1905 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1906 EXPECT_EQ(13, response->headers->GetContentLength());
1907}
1908
[email protected]385a4672009-03-11 22:21:291909// Enter a wrong password, and then the correct one.
1910TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421911 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111912 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591913 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401914 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431915 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291916
[email protected]1c773ea12009-04-28 19:58:421917 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291918 request.method = "GET";
1919 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1920 request.load_flags = 0;
1921
1922 MockWrite data_writes1[] = {
1923 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1924 "Host: 172.22.68.17\r\n"
1925 "Connection: keep-alive\r\n\r\n"),
1926 };
1927
1928 MockRead data_reads1[] = {
1929 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1930 // Negotiate and NTLM are often requested together. We only support NTLM.
1931 MockRead("WWW-Authenticate: Negotiate\r\n"),
1932 MockRead("WWW-Authenticate: NTLM\r\n"),
1933 MockRead("Connection: close\r\n"),
1934 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361935 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291936 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421937 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291938 };
1939
1940 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221941 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291942 // request we should be issuing -- the final header line contains a Type
1943 // 1 message.
1944 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1945 "Host: 172.22.68.17\r\n"
1946 "Connection: keep-alive\r\n"
1947 "Authorization: NTLM "
1948 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1949
1950 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1951 // (the credentials for the origin server). The second request continues
1952 // on the same connection.
1953 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1954 "Host: 172.22.68.17\r\n"
1955 "Connection: keep-alive\r\n"
1956 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1957 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1958 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1959 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1960 "4Ww7b7E=\r\n\r\n"),
1961 };
1962
1963 MockRead data_reads2[] = {
1964 // The origin server responds with a Type 2 message.
1965 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1966 MockRead("WWW-Authenticate: NTLM "
1967 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1968 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1969 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1970 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1971 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1972 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1973 "BtAAAAAAA=\r\n"),
1974 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361975 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291976 MockRead("You are not authorized to view this page\r\n"),
1977
1978 // Wrong password.
1979 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1980 MockRead("WWW-Authenticate: Negotiate\r\n"),
1981 MockRead("WWW-Authenticate: NTLM\r\n"),
1982 MockRead("Connection: close\r\n"),
1983 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361984 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291985 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421986 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291987 };
1988
1989 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221990 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291991 // request we should be issuing -- the final header line contains a Type
1992 // 1 message.
1993 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1994 "Host: 172.22.68.17\r\n"
1995 "Connection: keep-alive\r\n"
1996 "Authorization: NTLM "
1997 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1998
1999 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2000 // (the credentials for the origin server). The second request continues
2001 // on the same connection.
2002 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2003 "Host: 172.22.68.17\r\n"
2004 "Connection: keep-alive\r\n"
2005 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2006 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2007 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2008 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2009 "+4MUm7c=\r\n\r\n"),
2010 };
2011
2012 MockRead data_reads3[] = {
2013 // The origin server responds with a Type 2 message.
2014 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2015 MockRead("WWW-Authenticate: NTLM "
2016 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2017 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2018 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2019 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2020 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2021 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2022 "BtAAAAAAA=\r\n"),
2023 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362024 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292025 MockRead("You are not authorized to view this page\r\n"),
2026
2027 // Lastly we get the desired content.
2028 MockRead("HTTP/1.1 200 OK\r\n"),
2029 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2030 MockRead("Content-Length: 13\r\n\r\n"),
2031 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422032 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292033 };
2034
[email protected]31a2bfe2010-02-09 08:03:392035 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2036 data_writes1, arraysize(data_writes1));
2037 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2038 data_writes2, arraysize(data_writes2));
2039 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2040 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592041 session_deps.socket_factory.AddSocketDataProvider(&data1);
2042 session_deps.socket_factory.AddSocketDataProvider(&data2);
2043 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292044
2045 TestCompletionCallback callback1;
2046
[email protected]5a1d7ca2010-04-28 20:12:272047 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422048 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292049
2050 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422051 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292052
[email protected]0757e7702009-03-27 04:00:222053 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292054 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222055 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422056 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292057 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422058 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222059 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292060
[email protected]1c773ea12009-04-28 19:58:422061 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292062 EXPECT_FALSE(response == NULL);
2063
2064 // The password prompt info should have been set in response->auth_challenge.
2065 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2066
[email protected]71e4573a2009-05-21 22:03:002067 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292068 EXPECT_EQ(L"", response->auth_challenge->realm);
2069 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2070
2071 TestCompletionCallback callback3;
2072
[email protected]0757e7702009-03-27 04:00:222073 // Enter the wrong password.
2074 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422075 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292076
2077 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422078 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292079
[email protected]0757e7702009-03-27 04:00:222080 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2081 TestCompletionCallback callback4;
2082 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422083 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222084 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422085 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222086 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2087
2088 response = trans->GetResponseInfo();
2089 EXPECT_FALSE(response == NULL);
2090
2091 // The password prompt info should have been set in response->auth_challenge.
2092 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2093
[email protected]71e4573a2009-05-21 22:03:002094 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222095 EXPECT_EQ(L"", response->auth_challenge->realm);
2096 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2097
2098 TestCompletionCallback callback5;
2099
2100 // Now enter the right password.
2101 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422102 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222103
2104 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422105 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222106
[email protected]385a4672009-03-11 22:21:292107 response = trans->GetResponseInfo();
2108 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2109 EXPECT_EQ(13, response->headers->GetContentLength());
2110}
[email protected]ea9dc9a2009-09-05 00:43:322111#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292112
[email protected]4ddaf2502008-10-23 18:26:192113// Test reading a server response which has only headers, and no body.
2114// After some maximum number of bytes is consumed, the transaction should
2115// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2116TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592117 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402118 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432119 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192120
[email protected]1c773ea12009-04-28 19:58:422121 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192122 request.method = "GET";
2123 request.url = GURL("http://www.google.com/");
2124 request.load_flags = 0;
2125
[email protected]b75b7b2f2009-10-06 00:54:532126 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432127 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532128 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192129
2130 MockRead data_reads[] = {
2131 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432132 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192133 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422134 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192135 };
[email protected]31a2bfe2010-02-09 08:03:392136 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592137 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192138
2139 TestCompletionCallback callback;
2140
[email protected]5a1d7ca2010-04-28 20:12:272141 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422142 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192143
2144 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422145 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192146
[email protected]1c773ea12009-04-28 19:58:422147 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192148 EXPECT_TRUE(response == NULL);
2149}
[email protected]f4e426b2008-11-05 00:24:492150
2151// Make sure that we don't try to reuse a TCPClientSocket when failing to
2152// establish tunnel.
2153// http://code.google.com/p/chromium/issues/detail?id=3772
2154TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2155 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592156 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012157
[email protected]228ff742009-06-05 01:19:592158 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492159
[email protected]5695b8c2009-09-30 21:36:432160 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492161
[email protected]1c773ea12009-04-28 19:58:422162 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492163 request.method = "GET";
2164 request.url = GURL("https://www.google.com/");
2165 request.load_flags = 0;
2166
2167 // Since we have proxy, should try to establish tunnel.
2168 MockWrite data_writes1[] = {
2169 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452170 "Host: www.google.com\r\n"
2171 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492172 };
2173
[email protected]77848d12008-11-14 00:00:222174 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492175 // connection. Usually a proxy would return 501 (not implemented),
2176 // or 200 (tunnel established).
2177 MockRead data_reads1[] = {
2178 MockRead("HTTP/1.1 404 Not Found\r\n"),
2179 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422180 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492181 };
2182
[email protected]31a2bfe2010-02-09 08:03:392183 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2184 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592185 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492186
2187 TestCompletionCallback callback1;
2188
[email protected]5a1d7ca2010-04-28 20:12:272189 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422190 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492191
2192 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422193 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492194
[email protected]1c773ea12009-04-28 19:58:422195 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082196 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492197
[email protected]b4404c02009-04-10 16:38:522198 // Empty the current queue. This is necessary because idle sockets are
2199 // added to the connection pool asynchronously with a PostTask.
2200 MessageLoop::current()->RunAllPending();
2201
[email protected]f4e426b2008-11-05 00:24:492202 // We now check to make sure the TCPClientSocket was not added back to
2203 // the pool.
[email protected]a937a06d2009-08-19 21:19:242204 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492205 trans.reset();
[email protected]b4404c02009-04-10 16:38:522206 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492207 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242208 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492209}
[email protected]372d34a2008-11-05 21:30:512210
[email protected]1b157c02009-04-21 01:55:402211// Make sure that we recycle a socket after reading all of the response body.
2212TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592213 SessionDependencies session_deps;
2214 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402215
[email protected]5695b8c2009-09-30 21:36:432216 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402217
[email protected]1c773ea12009-04-28 19:58:422218 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402219 request.method = "GET";
2220 request.url = GURL("http://www.google.com/");
2221 request.load_flags = 0;
2222
2223 MockRead data_reads[] = {
2224 // A part of the response body is received with the response headers.
2225 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2226 // The rest of the response body is received in two parts.
2227 MockRead("lo"),
2228 MockRead(" world"),
2229 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422230 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402231 };
2232
[email protected]31a2bfe2010-02-09 08:03:392233 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592234 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402235
2236 TestCompletionCallback callback;
2237
[email protected]5a1d7ca2010-04-28 20:12:272238 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422239 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402240
2241 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422242 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402243
[email protected]1c773ea12009-04-28 19:58:422244 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402245 EXPECT_TRUE(response != NULL);
2246
2247 EXPECT_TRUE(response->headers != NULL);
2248 std::string status_line = response->headers->GetStatusLine();
2249 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2250
[email protected]a937a06d2009-08-19 21:19:242251 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402252
2253 std::string response_data;
2254 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422255 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402256 EXPECT_EQ("hello world", response_data);
2257
2258 // Empty the current queue. This is necessary because idle sockets are
2259 // added to the connection pool asynchronously with a PostTask.
2260 MessageLoop::current()->RunAllPending();
2261
2262 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242263 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402264}
2265
[email protected]b4404c02009-04-10 16:38:522266// Make sure that we recycle a socket after a zero-length response.
2267// http://crbug.com/9880
2268TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592269 SessionDependencies session_deps;
2270 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522271
[email protected]5695b8c2009-09-30 21:36:432272 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522273
[email protected]1c773ea12009-04-28 19:58:422274 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522275 request.method = "GET";
2276 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2277 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2278 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2279 "rt=prt.2642,ol.2649,xjs.2951");
2280 request.load_flags = 0;
2281
2282 MockRead data_reads[] = {
2283 MockRead("HTTP/1.1 204 No Content\r\n"
2284 "Content-Length: 0\r\n"
2285 "Content-Type: text/html\r\n\r\n"),
2286 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422287 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522288 };
2289
[email protected]31a2bfe2010-02-09 08:03:392290 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592291 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522292
2293 TestCompletionCallback callback;
2294
[email protected]5a1d7ca2010-04-28 20:12:272295 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422296 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522297
2298 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422299 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522300
[email protected]1c773ea12009-04-28 19:58:422301 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522302 EXPECT_TRUE(response != NULL);
2303
2304 EXPECT_TRUE(response->headers != NULL);
2305 std::string status_line = response->headers->GetStatusLine();
2306 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2307
[email protected]a937a06d2009-08-19 21:19:242308 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522309
2310 std::string response_data;
2311 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422312 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522313 EXPECT_EQ("", response_data);
2314
2315 // Empty the current queue. This is necessary because idle sockets are
2316 // added to the connection pool asynchronously with a PostTask.
2317 MessageLoop::current()->RunAllPending();
2318
2319 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242320 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522321}
2322
[email protected]372d34a2008-11-05 21:30:512323TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422324 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512325 // Transaction 1: a GET request that succeeds. The socket is recycled
2326 // after use.
2327 request[0].method = "GET";
2328 request[0].url = GURL("http://www.google.com/");
2329 request[0].load_flags = 0;
2330 // Transaction 2: a POST request. Reuses the socket kept alive from
2331 // transaction 1. The first attempts fails when writing the POST data.
2332 // This causes the transaction to retry with a new socket. The second
2333 // attempt succeeds.
2334 request[1].method = "POST";
2335 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422336 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512337 request[1].upload_data->AppendBytes("foo", 3);
2338 request[1].load_flags = 0;
2339
[email protected]228ff742009-06-05 01:19:592340 SessionDependencies session_deps;
2341 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512342
2343 // The first socket is used for transaction 1 and the first attempt of
2344 // transaction 2.
2345
2346 // The response of transaction 1.
2347 MockRead data_reads1[] = {
2348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2349 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422350 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512351 };
2352 // The mock write results of transaction 1 and the first attempt of
2353 // transaction 2.
2354 MockWrite data_writes1[] = {
2355 MockWrite(false, 64), // GET
2356 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422357 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512358 };
[email protected]31a2bfe2010-02-09 08:03:392359 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2360 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512361
2362 // The second socket is used for the second attempt of transaction 2.
2363
2364 // The response of transaction 2.
2365 MockRead data_reads2[] = {
2366 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2367 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422368 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512369 };
2370 // The mock write results of the second attempt of transaction 2.
2371 MockWrite data_writes2[] = {
2372 MockWrite(false, 93), // POST
2373 MockWrite(false, 3), // POST data
2374 };
[email protected]31a2bfe2010-02-09 08:03:392375 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2376 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512377
[email protected]5ecc992a42009-11-11 01:41:592378 session_deps.socket_factory.AddSocketDataProvider(&data1);
2379 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512380
2381 const char* kExpectedResponseData[] = {
2382 "hello world", "welcome"
2383 };
2384
2385 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422386 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432387 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512388
2389 TestCompletionCallback callback;
2390
[email protected]5a1d7ca2010-04-28 20:12:272391 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422392 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512393
2394 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422395 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512396
[email protected]1c773ea12009-04-28 19:58:422397 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512398 EXPECT_TRUE(response != NULL);
2399
2400 EXPECT_TRUE(response->headers != NULL);
2401 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2402
2403 std::string response_data;
2404 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422405 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512406 EXPECT_EQ(kExpectedResponseData[i], response_data);
2407 }
2408}
[email protected]f9ee6b52008-11-08 06:46:232409
2410// Test the request-challenge-retry sequence for basic auth when there is
2411// an identity in the URL. The request should be sent as normal, but when
2412// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322413TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592414 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402415 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432416 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232417
[email protected]1c773ea12009-04-28 19:58:422418 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232419 request.method = "GET";
2420 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292421 request.url = GURL("http://foo:b@[email protected]/");
2422
2423 // The password contains an escaped character -- for this test to pass it
2424 // will need to be unescaped by HttpNetworkTransaction.
2425 EXPECT_EQ("b%40r", request.url.password());
2426
[email protected]ea9dc9a2009-09-05 00:43:322427 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232428
2429 MockWrite data_writes1[] = {
2430 MockWrite("GET / HTTP/1.1\r\n"
2431 "Host: www.google.com\r\n"
2432 "Connection: keep-alive\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads1[] = {
2436 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2437 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2438 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422439 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232440 };
2441
2442 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322443 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232444 MockWrite data_writes2[] = {
2445 MockWrite("GET / HTTP/1.1\r\n"
2446 "Host: www.google.com\r\n"
2447 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292448 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232449 };
2450
2451 MockRead data_reads2[] = {
2452 MockRead("HTTP/1.0 200 OK\r\n"),
2453 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422454 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232455 };
2456
[email protected]31a2bfe2010-02-09 08:03:392457 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2458 data_writes1, arraysize(data_writes1));
2459 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2460 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592461 session_deps.socket_factory.AddSocketDataProvider(&data1);
2462 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232463
2464 TestCompletionCallback callback1;
2465
[email protected]5a1d7ca2010-04-28 20:12:272466 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422467 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232468
2469 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422470 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232471
[email protected]0757e7702009-03-27 04:00:222472 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2473 TestCompletionCallback callback2;
2474 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422475 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222476 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422477 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222478 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2479
[email protected]1c773ea12009-04-28 19:58:422480 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232481 EXPECT_FALSE(response == NULL);
2482
2483 // There is no challenge info, since the identity in URL worked.
2484 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2485
2486 EXPECT_EQ(100, response->headers->GetContentLength());
2487
2488 // Empty the current queue.
2489 MessageLoop::current()->RunAllPending();
2490}
2491
[email protected]ea9dc9a2009-09-05 00:43:322492// Test the request-challenge-retry sequence for basic auth when there is
2493// an incorrect identity in the URL. The identity from the URL should be used
2494// only once.
2495TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2496 SessionDependencies session_deps;
2497 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432498 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322499
2500 HttpRequestInfo request;
2501 request.method = "GET";
2502 // Note: the URL has a username:password in it. The password "baz" is
2503 // wrong (should be "bar").
2504 request.url = GURL("http://foo:[email protected]/");
2505
2506 request.load_flags = LOAD_NORMAL;
2507
2508 MockWrite data_writes1[] = {
2509 MockWrite("GET / HTTP/1.1\r\n"
2510 "Host: www.google.com\r\n"
2511 "Connection: keep-alive\r\n\r\n"),
2512 };
2513
2514 MockRead data_reads1[] = {
2515 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2516 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2517 MockRead("Content-Length: 10\r\n\r\n"),
2518 MockRead(false, ERR_FAILED),
2519 };
2520
2521 // After the challenge above, the transaction will be restarted using the
2522 // identity from the url (foo, baz) to answer the challenge.
2523 MockWrite data_writes2[] = {
2524 MockWrite("GET / HTTP/1.1\r\n"
2525 "Host: www.google.com\r\n"
2526 "Connection: keep-alive\r\n"
2527 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2528 };
2529
2530 MockRead data_reads2[] = {
2531 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2532 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2533 MockRead("Content-Length: 10\r\n\r\n"),
2534 MockRead(false, ERR_FAILED),
2535 };
2536
2537 // After the challenge above, the transaction will be restarted using the
2538 // identity supplied by the user (foo, bar) to answer the challenge.
2539 MockWrite data_writes3[] = {
2540 MockWrite("GET / HTTP/1.1\r\n"
2541 "Host: www.google.com\r\n"
2542 "Connection: keep-alive\r\n"
2543 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2544 };
2545
2546 MockRead data_reads3[] = {
2547 MockRead("HTTP/1.0 200 OK\r\n"),
2548 MockRead("Content-Length: 100\r\n\r\n"),
2549 MockRead(false, OK),
2550 };
2551
[email protected]31a2bfe2010-02-09 08:03:392552 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2553 data_writes1, arraysize(data_writes1));
2554 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2555 data_writes2, arraysize(data_writes2));
2556 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2557 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592558 session_deps.socket_factory.AddSocketDataProvider(&data1);
2559 session_deps.socket_factory.AddSocketDataProvider(&data2);
2560 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322561
2562 TestCompletionCallback callback1;
2563
[email protected]5a1d7ca2010-04-28 20:12:272564 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322565 EXPECT_EQ(ERR_IO_PENDING, rv);
2566
2567 rv = callback1.WaitForResult();
2568 EXPECT_EQ(OK, rv);
2569
2570 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2571 TestCompletionCallback callback2;
2572 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2573 EXPECT_EQ(ERR_IO_PENDING, rv);
2574 rv = callback2.WaitForResult();
2575 EXPECT_EQ(OK, rv);
2576 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2577
2578 const HttpResponseInfo* response = trans->GetResponseInfo();
2579 EXPECT_FALSE(response == NULL);
2580 // The password prompt info should have been set in response->auth_challenge.
2581 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2582
2583 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2584 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2585 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2586
2587 TestCompletionCallback callback3;
2588 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2589 EXPECT_EQ(ERR_IO_PENDING, rv);
2590 rv = callback3.WaitForResult();
2591 EXPECT_EQ(OK, rv);
2592 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2593
2594 response = trans->GetResponseInfo();
2595 EXPECT_FALSE(response == NULL);
2596
2597 // There is no challenge info, since the identity worked.
2598 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2599
2600 EXPECT_EQ(100, response->headers->GetContentLength());
2601
2602 // Empty the current queue.
2603 MessageLoop::current()->RunAllPending();
2604}
2605
[email protected]f9ee6b52008-11-08 06:46:232606// Test that previously tried username/passwords for a realm get re-used.
2607TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592608 SessionDependencies session_deps;
2609 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232610
2611 // Transaction 1: authenticate (foo, bar) on MyRealm1
2612 {
[email protected]5695b8c2009-09-30 21:36:432613 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232614
[email protected]1c773ea12009-04-28 19:58:422615 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232616 request.method = "GET";
2617 request.url = GURL("http://www.google.com/x/y/z");
2618 request.load_flags = 0;
2619
2620 MockWrite data_writes1[] = {
2621 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2622 "Host: www.google.com\r\n"
2623 "Connection: keep-alive\r\n\r\n"),
2624 };
2625
2626 MockRead data_reads1[] = {
2627 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2628 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2629 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422630 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232631 };
2632
2633 // Resend with authorization (username=foo, password=bar)
2634 MockWrite data_writes2[] = {
2635 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2636 "Host: www.google.com\r\n"
2637 "Connection: keep-alive\r\n"
2638 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2639 };
2640
2641 // Sever accepts the authorization.
2642 MockRead data_reads2[] = {
2643 MockRead("HTTP/1.0 200 OK\r\n"),
2644 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422645 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232646 };
2647
[email protected]31a2bfe2010-02-09 08:03:392648 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2649 data_writes1, arraysize(data_writes1));
2650 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2651 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592652 session_deps.socket_factory.AddSocketDataProvider(&data1);
2653 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232654
2655 TestCompletionCallback callback1;
2656
[email protected]5a1d7ca2010-04-28 20:12:272657 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232659
2660 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422661 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232662
[email protected]1c773ea12009-04-28 19:58:422663 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232664 EXPECT_FALSE(response == NULL);
2665
2666 // The password prompt info should have been set in
2667 // response->auth_challenge.
2668 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2669
[email protected]71e4573a2009-05-21 22:03:002670 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232671 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2672 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2673
2674 TestCompletionCallback callback2;
2675
2676 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422677 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232678
2679 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422680 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232681
2682 response = trans->GetResponseInfo();
2683 EXPECT_FALSE(response == NULL);
2684 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2685 EXPECT_EQ(100, response->headers->GetContentLength());
2686 }
2687
2688 // ------------------------------------------------------------------------
2689
2690 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2691 {
[email protected]5695b8c2009-09-30 21:36:432692 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232693
[email protected]1c773ea12009-04-28 19:58:422694 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232695 request.method = "GET";
2696 // Note that Transaction 1 was at /x/y/z, so this is in the same
2697 // protection space as MyRealm1.
2698 request.url = GURL("http://www.google.com/x/y/a/b");
2699 request.load_flags = 0;
2700
2701 MockWrite data_writes1[] = {
2702 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2703 "Host: www.google.com\r\n"
2704 "Connection: keep-alive\r\n"
2705 // Send preemptive authorization for MyRealm1
2706 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2707 };
2708
2709 // The server didn't like the preemptive authorization, and
2710 // challenges us for a different realm (MyRealm2).
2711 MockRead data_reads1[] = {
2712 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2713 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2714 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422715 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232716 };
2717
2718 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2719 MockWrite data_writes2[] = {
2720 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2721 "Host: www.google.com\r\n"
2722 "Connection: keep-alive\r\n"
2723 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2724 };
2725
2726 // Sever accepts the authorization.
2727 MockRead data_reads2[] = {
2728 MockRead("HTTP/1.0 200 OK\r\n"),
2729 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422730 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232731 };
2732
[email protected]31a2bfe2010-02-09 08:03:392733 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2734 data_writes1, arraysize(data_writes1));
2735 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2736 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592737 session_deps.socket_factory.AddSocketDataProvider(&data1);
2738 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232739
2740 TestCompletionCallback callback1;
2741
[email protected]5a1d7ca2010-04-28 20:12:272742 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422743 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232744
2745 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422746 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232747
[email protected]1c773ea12009-04-28 19:58:422748 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232749 EXPECT_FALSE(response == NULL);
2750
2751 // The password prompt info should have been set in
2752 // response->auth_challenge.
2753 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2754
[email protected]71e4573a2009-05-21 22:03:002755 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232756 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2757 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2758
2759 TestCompletionCallback callback2;
2760
2761 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422762 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232763
2764 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422765 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232766
2767 response = trans->GetResponseInfo();
2768 EXPECT_FALSE(response == NULL);
2769 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2770 EXPECT_EQ(100, response->headers->GetContentLength());
2771 }
2772
2773 // ------------------------------------------------------------------------
2774
2775 // Transaction 3: Resend a request in MyRealm's protection space --
2776 // succeed with preemptive authorization.
2777 {
[email protected]5695b8c2009-09-30 21:36:432778 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232779
[email protected]1c773ea12009-04-28 19:58:422780 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232781 request.method = "GET";
2782 request.url = GURL("http://www.google.com/x/y/z2");
2783 request.load_flags = 0;
2784
2785 MockWrite data_writes1[] = {
2786 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2787 "Host: www.google.com\r\n"
2788 "Connection: keep-alive\r\n"
2789 // The authorization for MyRealm1 gets sent preemptively
2790 // (since the url is in the same protection space)
2791 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2792 };
2793
2794 // Sever accepts the preemptive authorization
2795 MockRead data_reads1[] = {
2796 MockRead("HTTP/1.0 200 OK\r\n"),
2797 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422798 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232799 };
2800
[email protected]31a2bfe2010-02-09 08:03:392801 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2802 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592803 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232804
2805 TestCompletionCallback callback1;
2806
[email protected]5a1d7ca2010-04-28 20:12:272807 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422808 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232809
2810 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422811 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232812
[email protected]1c773ea12009-04-28 19:58:422813 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232814 EXPECT_FALSE(response == NULL);
2815
2816 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2817 EXPECT_EQ(100, response->headers->GetContentLength());
2818 }
2819
2820 // ------------------------------------------------------------------------
2821
2822 // Transaction 4: request another URL in MyRealm (however the
2823 // url is not known to belong to the protection space, so no pre-auth).
2824 {
[email protected]5695b8c2009-09-30 21:36:432825 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232826
[email protected]1c773ea12009-04-28 19:58:422827 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232828 request.method = "GET";
2829 request.url = GURL("http://www.google.com/x/1");
2830 request.load_flags = 0;
2831
2832 MockWrite data_writes1[] = {
2833 MockWrite("GET /x/1 HTTP/1.1\r\n"
2834 "Host: www.google.com\r\n"
2835 "Connection: keep-alive\r\n\r\n"),
2836 };
2837
2838 MockRead data_reads1[] = {
2839 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2840 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2841 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422842 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232843 };
2844
2845 // Resend with authorization from MyRealm's cache.
2846 MockWrite data_writes2[] = {
2847 MockWrite("GET /x/1 HTTP/1.1\r\n"
2848 "Host: www.google.com\r\n"
2849 "Connection: keep-alive\r\n"
2850 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2851 };
2852
2853 // Sever accepts the authorization.
2854 MockRead data_reads2[] = {
2855 MockRead("HTTP/1.0 200 OK\r\n"),
2856 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422857 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232858 };
2859
[email protected]31a2bfe2010-02-09 08:03:392860 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2861 data_writes1, arraysize(data_writes1));
2862 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2863 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592864 session_deps.socket_factory.AddSocketDataProvider(&data1);
2865 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232866
2867 TestCompletionCallback callback1;
2868
[email protected]5a1d7ca2010-04-28 20:12:272869 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422870 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232871
2872 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422873 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232874
[email protected]0757e7702009-03-27 04:00:222875 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2876 TestCompletionCallback callback2;
2877 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422878 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222879 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422880 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222881 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2882
[email protected]1c773ea12009-04-28 19:58:422883 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232884 EXPECT_FALSE(response == NULL);
2885 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2886 EXPECT_EQ(100, response->headers->GetContentLength());
2887 }
2888
2889 // ------------------------------------------------------------------------
2890
2891 // Transaction 5: request a URL in MyRealm, but the server rejects the
2892 // cached identity. Should invalidate and re-prompt.
2893 {
[email protected]5695b8c2009-09-30 21:36:432894 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232895
[email protected]1c773ea12009-04-28 19:58:422896 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232897 request.method = "GET";
2898 request.url = GURL("http://www.google.com/p/q/t");
2899 request.load_flags = 0;
2900
2901 MockWrite data_writes1[] = {
2902 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2903 "Host: www.google.com\r\n"
2904 "Connection: keep-alive\r\n\r\n"),
2905 };
2906
2907 MockRead data_reads1[] = {
2908 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2909 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2910 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422911 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232912 };
2913
2914 // Resend with authorization from cache for MyRealm.
2915 MockWrite data_writes2[] = {
2916 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2917 "Host: www.google.com\r\n"
2918 "Connection: keep-alive\r\n"
2919 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2920 };
2921
2922 // Sever rejects the authorization.
2923 MockRead data_reads2[] = {
2924 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2925 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2926 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422927 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232928 };
2929
2930 // At this point we should prompt for new credentials for MyRealm.
2931 // Restart with username=foo3, password=foo4.
2932 MockWrite data_writes3[] = {
2933 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2934 "Host: www.google.com\r\n"
2935 "Connection: keep-alive\r\n"
2936 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2937 };
2938
2939 // Sever accepts the authorization.
2940 MockRead data_reads3[] = {
2941 MockRead("HTTP/1.0 200 OK\r\n"),
2942 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422943 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232944 };
2945
[email protected]31a2bfe2010-02-09 08:03:392946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2947 data_writes1, arraysize(data_writes1));
2948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2949 data_writes2, arraysize(data_writes2));
2950 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2951 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592952 session_deps.socket_factory.AddSocketDataProvider(&data1);
2953 session_deps.socket_factory.AddSocketDataProvider(&data2);
2954 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232955
2956 TestCompletionCallback callback1;
2957
[email protected]5a1d7ca2010-04-28 20:12:272958 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422959 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232960
2961 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422962 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232963
[email protected]0757e7702009-03-27 04:00:222964 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2965 TestCompletionCallback callback2;
2966 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422967 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222968 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422969 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222970 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2971
[email protected]1c773ea12009-04-28 19:58:422972 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232973 EXPECT_FALSE(response == NULL);
2974
2975 // The password prompt info should have been set in
2976 // response->auth_challenge.
2977 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2978
[email protected]71e4573a2009-05-21 22:03:002979 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232980 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2981 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2982
[email protected]0757e7702009-03-27 04:00:222983 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232984
[email protected]0757e7702009-03-27 04:00:222985 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422986 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232987
[email protected]0757e7702009-03-27 04:00:222988 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422989 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232990
2991 response = trans->GetResponseInfo();
2992 EXPECT_FALSE(response == NULL);
2993 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2994 EXPECT_EQ(100, response->headers->GetContentLength());
2995 }
2996}
[email protected]89ceba9a2009-03-21 03:46:062997
[email protected]3c32c5f2010-05-18 15:18:122998// Tests that nonce count increments when multiple auth attempts
2999// are started with the same nonce.
3000TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3001 SessionDependencies session_deps;
3002 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3003 HttpAuthHandlerDigest::SetFixedCnonce(true);
3004
3005 // Transaction 1: authenticate (foo, bar) on MyRealm1
3006 {
3007 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3008
3009 HttpRequestInfo request;
3010 request.method = "GET";
3011 request.url = GURL("http://www.google.com/x/y/z");
3012 request.load_flags = 0;
3013
3014 MockWrite data_writes1[] = {
3015 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3016 "Host: www.google.com\r\n"
3017 "Connection: keep-alive\r\n\r\n"),
3018 };
3019
3020 MockRead data_reads1[] = {
3021 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3022 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3023 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3024 MockRead(false, OK),
3025 };
3026
3027 // Resend with authorization (username=foo, password=bar)
3028 MockWrite data_writes2[] = {
3029 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3030 "Host: www.google.com\r\n"
3031 "Connection: keep-alive\r\n"
3032 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3033 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3034 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3035 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3036 };
3037
3038 // Sever accepts the authorization.
3039 MockRead data_reads2[] = {
3040 MockRead("HTTP/1.0 200 OK\r\n"),
3041 MockRead(false, OK),
3042 };
3043
3044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3045 data_writes1, arraysize(data_writes1));
3046 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3047 data_writes2, arraysize(data_writes2));
3048 session_deps.socket_factory.AddSocketDataProvider(&data1);
3049 session_deps.socket_factory.AddSocketDataProvider(&data2);
3050
3051 TestCompletionCallback callback1;
3052
3053 int rv = trans->Start(&request, &callback1, BoundNetLog());
3054 EXPECT_EQ(ERR_IO_PENDING, rv);
3055
3056 rv = callback1.WaitForResult();
3057 EXPECT_EQ(OK, rv);
3058
3059 const HttpResponseInfo* response = trans->GetResponseInfo();
3060 ASSERT_FALSE(response == NULL);
3061
3062 // The password prompt info should have been set in
3063 // response->auth_challenge.
3064 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3065
3066 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3067 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3068 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3069
3070 TestCompletionCallback callback2;
3071
3072 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3073 EXPECT_EQ(ERR_IO_PENDING, rv);
3074
3075 rv = callback2.WaitForResult();
3076 EXPECT_EQ(OK, rv);
3077
3078 response = trans->GetResponseInfo();
3079 ASSERT_FALSE(response == NULL);
3080 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3081 }
3082
3083 // ------------------------------------------------------------------------
3084
3085 // Transaction 2: Request another resource in digestive's protection space.
3086 // This will preemptively add an Authorization header which should have an
3087 // "nc" value of 2 (as compared to 1 in the first use.
3088 {
3089 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3090
3091 HttpRequestInfo request;
3092 request.method = "GET";
3093 // Note that Transaction 1 was at /x/y/z, so this is in the same
3094 // protection space as digest.
3095 request.url = GURL("http://www.google.com/x/y/a/b");
3096 request.load_flags = 0;
3097
3098 MockWrite data_writes1[] = {
3099 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3100 "Host: www.google.com\r\n"
3101 "Connection: keep-alive\r\n"
3102 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3103 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3104 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3105 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3106 };
3107
3108 // Sever accepts the authorization.
3109 MockRead data_reads1[] = {
3110 MockRead("HTTP/1.0 200 OK\r\n"),
3111 MockRead("Content-Length: 100\r\n\r\n"),
3112 MockRead(false, OK),
3113 };
3114
3115 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3116 data_writes1, arraysize(data_writes1));
3117 session_deps.socket_factory.AddSocketDataProvider(&data1);
3118
3119 TestCompletionCallback callback1;
3120
3121 int rv = trans->Start(&request, &callback1, BoundNetLog());
3122 EXPECT_EQ(ERR_IO_PENDING, rv);
3123
3124 rv = callback1.WaitForResult();
3125 EXPECT_EQ(OK, rv);
3126
3127 const HttpResponseInfo* response = trans->GetResponseInfo();
3128 ASSERT_FALSE(response == NULL);
3129 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3130 }
3131}
3132
[email protected]89ceba9a2009-03-21 03:46:063133// Test the ResetStateForRestart() private method.
3134TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3135 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593136 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403137 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433138 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063139
3140 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063141 trans->read_buf_ = new IOBuffer(15);
3142 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573143 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063144
3145 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143146 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573147 response->auth_challenge = new AuthChallengeInfo();
3148 response->ssl_info.cert_status = -15;
3149 response->response_time = base::Time::Now();
3150 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063151
3152 { // Setup state for response_.vary_data
3153 HttpRequestInfo request;
3154 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3155 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573156 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433157 request.extra_headers.SetHeader("Foo", "1");
3158 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573159 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063160 }
3161
3162 // Cause the above state to be reset.
3163 trans->ResetStateForRestart();
3164
3165 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073166 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063167 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573168 EXPECT_EQ(0U, trans->request_headers_.size());
3169 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3170 EXPECT_TRUE(response->headers.get() == NULL);
3171 EXPECT_EQ(false, response->was_cached);
3172 EXPECT_EQ(0, response->ssl_info.cert_status);
3173 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063174}
3175
[email protected]bacff652009-03-31 17:50:333176// Test HTTPS connections to a site with a bad certificate
3177TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593178 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403179 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433180 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333181
3182 HttpRequestInfo request;
3183 request.method = "GET";
3184 request.url = GURL("https://www.google.com/");
3185 request.load_flags = 0;
3186
3187 MockWrite data_writes[] = {
3188 MockWrite("GET / HTTP/1.1\r\n"
3189 "Host: www.google.com\r\n"
3190 "Connection: keep-alive\r\n\r\n"),
3191 };
3192
3193 MockRead data_reads[] = {
3194 MockRead("HTTP/1.0 200 OK\r\n"),
3195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3196 MockRead("Content-Length: 100\r\n\r\n"),
3197 MockRead(false, OK),
3198 };
3199
[email protected]5ecc992a42009-11-11 01:41:593200 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393201 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3202 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593203 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3204 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333205
[email protected]5ecc992a42009-11-11 01:41:593206 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3207 session_deps.socket_factory.AddSocketDataProvider(&data);
3208 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3209 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333210
3211 TestCompletionCallback callback;
3212
[email protected]5a1d7ca2010-04-28 20:12:273213 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333214 EXPECT_EQ(ERR_IO_PENDING, rv);
3215
3216 rv = callback.WaitForResult();
3217 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3218
3219 rv = trans->RestartIgnoringLastError(&callback);
3220 EXPECT_EQ(ERR_IO_PENDING, rv);
3221
3222 rv = callback.WaitForResult();
3223 EXPECT_EQ(OK, rv);
3224
3225 const HttpResponseInfo* response = trans->GetResponseInfo();
3226
3227 EXPECT_FALSE(response == NULL);
3228 EXPECT_EQ(100, response->headers->GetContentLength());
3229}
3230
3231// Test HTTPS connections to a site with a bad certificate, going through a
3232// proxy
3233TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593234 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333235
3236 HttpRequestInfo request;
3237 request.method = "GET";
3238 request.url = GURL("https://www.google.com/");
3239 request.load_flags = 0;
3240
3241 MockWrite proxy_writes[] = {
3242 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453243 "Host: www.google.com\r\n"
3244 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333245 };
3246
3247 MockRead proxy_reads[] = {
3248 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423249 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333250 };
3251
3252 MockWrite data_writes[] = {
3253 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453254 "Host: www.google.com\r\n"
3255 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333256 MockWrite("GET / HTTP/1.1\r\n"
3257 "Host: www.google.com\r\n"
3258 "Connection: keep-alive\r\n\r\n"),
3259 };
3260
3261 MockRead data_reads[] = {
3262 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3263 MockRead("HTTP/1.0 200 OK\r\n"),
3264 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3265 MockRead("Content-Length: 100\r\n\r\n"),
3266 MockRead(false, OK),
3267 };
3268
[email protected]31a2bfe2010-02-09 08:03:393269 StaticSocketDataProvider ssl_bad_certificate(
3270 proxy_reads, arraysize(proxy_reads),
3271 proxy_writes, arraysize(proxy_writes));
3272 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3273 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593274 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3275 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333276
[email protected]5ecc992a42009-11-11 01:41:593277 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3278 session_deps.socket_factory.AddSocketDataProvider(&data);
3279 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3280 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333281
3282 TestCompletionCallback callback;
3283
3284 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593285 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333286
[email protected]d207a5f2009-06-04 05:28:403287 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433288 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333289
[email protected]5a1d7ca2010-04-28 20:12:273290 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333291 EXPECT_EQ(ERR_IO_PENDING, rv);
3292
3293 rv = callback.WaitForResult();
3294 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3295
3296 rv = trans->RestartIgnoringLastError(&callback);
3297 EXPECT_EQ(ERR_IO_PENDING, rv);
3298
3299 rv = callback.WaitForResult();
3300 EXPECT_EQ(OK, rv);
3301
3302 const HttpResponseInfo* response = trans->GetResponseInfo();
3303
3304 EXPECT_FALSE(response == NULL);
3305 EXPECT_EQ(100, response->headers->GetContentLength());
3306 }
3307}
3308
[email protected]1c773ea12009-04-28 19:58:423309TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593310 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403311 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433312 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423313
3314 HttpRequestInfo request;
3315 request.method = "GET";
3316 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433317 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3318 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423319
3320 MockWrite data_writes[] = {
3321 MockWrite("GET / HTTP/1.1\r\n"
3322 "Host: www.google.com\r\n"
3323 "Connection: keep-alive\r\n"
3324 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3325 };
3326
3327 // Lastly, the server responds with the actual content.
3328 MockRead data_reads[] = {
3329 MockRead("HTTP/1.0 200 OK\r\n"),
3330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3331 MockRead("Content-Length: 100\r\n\r\n"),
3332 MockRead(false, OK),
3333 };
3334
[email protected]31a2bfe2010-02-09 08:03:393335 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3336 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593337 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423338
3339 TestCompletionCallback callback;
3340
[email protected]5a1d7ca2010-04-28 20:12:273341 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423342 EXPECT_EQ(ERR_IO_PENDING, rv);
3343
3344 rv = callback.WaitForResult();
3345 EXPECT_EQ(OK, rv);
3346}
3347
3348TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593349 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403350 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433351 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423352
3353 HttpRequestInfo request;
3354 request.method = "GET";
3355 request.url = GURL("http://www.google.com/");
3356 request.load_flags = 0;
3357 request.referrer = GURL("http://the.previous.site.com/");
3358
3359 MockWrite data_writes[] = {
3360 MockWrite("GET / HTTP/1.1\r\n"
3361 "Host: www.google.com\r\n"
3362 "Connection: keep-alive\r\n"
3363 "Referer: http://the.previous.site.com/\r\n\r\n"),
3364 };
3365
3366 // Lastly, the server responds with the actual content.
3367 MockRead data_reads[] = {
3368 MockRead("HTTP/1.0 200 OK\r\n"),
3369 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3370 MockRead("Content-Length: 100\r\n\r\n"),
3371 MockRead(false, OK),
3372 };
3373
[email protected]31a2bfe2010-02-09 08:03:393374 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3375 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593376 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423377
3378 TestCompletionCallback callback;
3379
[email protected]5a1d7ca2010-04-28 20:12:273380 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423381 EXPECT_EQ(ERR_IO_PENDING, rv);
3382
3383 rv = callback.WaitForResult();
3384 EXPECT_EQ(OK, rv);
3385}
3386
3387TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593388 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403389 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433390 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423391
3392 HttpRequestInfo request;
3393 request.method = "POST";
3394 request.url = GURL("http://www.google.com/");
3395
3396 MockWrite data_writes[] = {
3397 MockWrite("POST / HTTP/1.1\r\n"
3398 "Host: www.google.com\r\n"
3399 "Connection: keep-alive\r\n"
3400 "Content-Length: 0\r\n\r\n"),
3401 };
3402
3403 // Lastly, the server responds with the actual content.
3404 MockRead data_reads[] = {
3405 MockRead("HTTP/1.0 200 OK\r\n"),
3406 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3407 MockRead("Content-Length: 100\r\n\r\n"),
3408 MockRead(false, OK),
3409 };
3410
[email protected]31a2bfe2010-02-09 08:03:393411 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3412 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593413 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423414
3415 TestCompletionCallback callback;
3416
[email protected]5a1d7ca2010-04-28 20:12:273417 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423418 EXPECT_EQ(ERR_IO_PENDING, rv);
3419
3420 rv = callback.WaitForResult();
3421 EXPECT_EQ(OK, rv);
3422}
3423
3424TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593425 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403426 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433427 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423428
3429 HttpRequestInfo request;
3430 request.method = "PUT";
3431 request.url = GURL("http://www.google.com/");
3432
3433 MockWrite data_writes[] = {
3434 MockWrite("PUT / HTTP/1.1\r\n"
3435 "Host: www.google.com\r\n"
3436 "Connection: keep-alive\r\n"
3437 "Content-Length: 0\r\n\r\n"),
3438 };
3439
3440 // Lastly, the server responds with the actual content.
3441 MockRead data_reads[] = {
3442 MockRead("HTTP/1.0 200 OK\r\n"),
3443 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3444 MockRead("Content-Length: 100\r\n\r\n"),
3445 MockRead(false, OK),
3446 };
3447
[email protected]31a2bfe2010-02-09 08:03:393448 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3449 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593450 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423451
3452 TestCompletionCallback callback;
3453
[email protected]5a1d7ca2010-04-28 20:12:273454 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423455 EXPECT_EQ(ERR_IO_PENDING, rv);
3456
3457 rv = callback.WaitForResult();
3458 EXPECT_EQ(OK, rv);
3459}
3460
3461TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593462 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403463 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433464 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423465
3466 HttpRequestInfo request;
3467 request.method = "HEAD";
3468 request.url = GURL("http://www.google.com/");
3469
3470 MockWrite data_writes[] = {
3471 MockWrite("HEAD / HTTP/1.1\r\n"
3472 "Host: www.google.com\r\n"
3473 "Connection: keep-alive\r\n"
3474 "Content-Length: 0\r\n\r\n"),
3475 };
3476
3477 // Lastly, the server responds with the actual content.
3478 MockRead data_reads[] = {
3479 MockRead("HTTP/1.0 200 OK\r\n"),
3480 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3481 MockRead("Content-Length: 100\r\n\r\n"),
3482 MockRead(false, OK),
3483 };
3484
[email protected]31a2bfe2010-02-09 08:03:393485 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3486 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593487 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423488
3489 TestCompletionCallback callback;
3490
[email protected]5a1d7ca2010-04-28 20:12:273491 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423492 EXPECT_EQ(ERR_IO_PENDING, rv);
3493
3494 rv = callback.WaitForResult();
3495 EXPECT_EQ(OK, rv);
3496}
3497
3498TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593499 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403500 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433501 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423502
3503 HttpRequestInfo request;
3504 request.method = "GET";
3505 request.url = GURL("http://www.google.com/");
3506 request.load_flags = LOAD_BYPASS_CACHE;
3507
3508 MockWrite data_writes[] = {
3509 MockWrite("GET / HTTP/1.1\r\n"
3510 "Host: www.google.com\r\n"
3511 "Connection: keep-alive\r\n"
3512 "Pragma: no-cache\r\n"
3513 "Cache-Control: no-cache\r\n\r\n"),
3514 };
3515
3516 // Lastly, the server responds with the actual content.
3517 MockRead data_reads[] = {
3518 MockRead("HTTP/1.0 200 OK\r\n"),
3519 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3520 MockRead("Content-Length: 100\r\n\r\n"),
3521 MockRead(false, OK),
3522 };
3523
[email protected]31a2bfe2010-02-09 08:03:393524 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3525 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593526 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423527
3528 TestCompletionCallback callback;
3529
[email protected]5a1d7ca2010-04-28 20:12:273530 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423531 EXPECT_EQ(ERR_IO_PENDING, rv);
3532
3533 rv = callback.WaitForResult();
3534 EXPECT_EQ(OK, rv);
3535}
3536
3537TEST_F(HttpNetworkTransactionTest,
3538 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593539 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403540 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433541 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423542
3543 HttpRequestInfo request;
3544 request.method = "GET";
3545 request.url = GURL("http://www.google.com/");
3546 request.load_flags = LOAD_VALIDATE_CACHE;
3547
3548 MockWrite data_writes[] = {
3549 MockWrite("GET / HTTP/1.1\r\n"
3550 "Host: www.google.com\r\n"
3551 "Connection: keep-alive\r\n"
3552 "Cache-Control: max-age=0\r\n\r\n"),
3553 };
3554
3555 // Lastly, the server responds with the actual content.
3556 MockRead data_reads[] = {
3557 MockRead("HTTP/1.0 200 OK\r\n"),
3558 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3559 MockRead("Content-Length: 100\r\n\r\n"),
3560 MockRead(false, OK),
3561 };
3562
[email protected]31a2bfe2010-02-09 08:03:393563 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3564 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593565 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423566
3567 TestCompletionCallback callback;
3568
[email protected]5a1d7ca2010-04-28 20:12:273569 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423570 EXPECT_EQ(ERR_IO_PENDING, rv);
3571
3572 rv = callback.WaitForResult();
3573 EXPECT_EQ(OK, rv);
3574}
3575
3576TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593577 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403578 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433579 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423580
3581 HttpRequestInfo request;
3582 request.method = "GET";
3583 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433584 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423585
3586 MockWrite data_writes[] = {
3587 MockWrite("GET / HTTP/1.1\r\n"
3588 "Host: www.google.com\r\n"
3589 "Connection: keep-alive\r\n"
3590 "FooHeader: Bar\r\n\r\n"),
3591 };
3592
3593 // Lastly, the server responds with the actual content.
3594 MockRead data_reads[] = {
3595 MockRead("HTTP/1.0 200 OK\r\n"),
3596 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3597 MockRead("Content-Length: 100\r\n\r\n"),
3598 MockRead(false, OK),
3599 };
3600
[email protected]31a2bfe2010-02-09 08:03:393601 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3602 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593603 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423604
3605 TestCompletionCallback callback;
3606
[email protected]5a1d7ca2010-04-28 20:12:273607 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423608 EXPECT_EQ(ERR_IO_PENDING, rv);
3609
3610 rv = callback.WaitForResult();
3611 EXPECT_EQ(OK, rv);
3612}
3613
[email protected]270c6412010-03-29 22:02:473614TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3615 SessionDependencies session_deps;
3616 scoped_ptr<HttpTransaction> trans(
3617 new HttpNetworkTransaction(CreateSession(&session_deps)));
3618
3619 HttpRequestInfo request;
3620 request.method = "GET";
3621 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433622 request.extra_headers.SetHeader("referer", "www.foo.com");
3623 request.extra_headers.SetHeader("hEllo", "Kitty");
3624 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473625
3626 MockWrite data_writes[] = {
3627 MockWrite("GET / HTTP/1.1\r\n"
3628 "Host: www.google.com\r\n"
3629 "Connection: keep-alive\r\n"
3630 "hEllo: Kitty\r\n"
3631 "FoO: bar\r\n\r\n"),
3632 };
3633
3634 // Lastly, the server responds with the actual content.
3635 MockRead data_reads[] = {
3636 MockRead("HTTP/1.0 200 OK\r\n"),
3637 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3638 MockRead("Content-Length: 100\r\n\r\n"),
3639 MockRead(false, OK),
3640 };
3641
3642 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3643 data_writes, arraysize(data_writes));
3644 session_deps.socket_factory.AddSocketDataProvider(&data);
3645
3646 TestCompletionCallback callback;
3647
[email protected]5a1d7ca2010-04-28 20:12:273648 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473649 EXPECT_EQ(ERR_IO_PENDING, rv);
3650
3651 rv = callback.WaitForResult();
3652 EXPECT_EQ(OK, rv);
3653}
3654
[email protected]3cd17242009-06-23 02:59:023655TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093656 SessionDependencies session_deps(
3657 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023658
3659 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433660 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023661
3662 HttpRequestInfo request;
3663 request.method = "GET";
3664 request.url = GURL("http://www.google.com/");
3665 request.load_flags = 0;
3666
3667 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3668 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3669
3670 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353671 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023672 MockWrite("GET / HTTP/1.1\r\n"
3673 "Host: www.google.com\r\n"
3674 "Connection: keep-alive\r\n\r\n")
3675 };
3676
3677 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593678 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023679 MockRead("HTTP/1.0 200 OK\r\n"),
3680 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3681 MockRead("Payload"),
3682 MockRead(false, OK)
3683 };
3684
[email protected]31a2bfe2010-02-09 08:03:393685 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3686 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593687 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023688
3689 TestCompletionCallback callback;
3690
[email protected]5a1d7ca2010-04-28 20:12:273691 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023692 EXPECT_EQ(ERR_IO_PENDING, rv);
3693
3694 rv = callback.WaitForResult();
3695 EXPECT_EQ(OK, rv);
3696
3697 const HttpResponseInfo* response = trans->GetResponseInfo();
3698 EXPECT_FALSE(response == NULL);
3699
3700 std::string response_text;
3701 rv = ReadTransaction(trans.get(), &response_text);
3702 EXPECT_EQ(OK, rv);
3703 EXPECT_EQ("Payload", response_text);
3704}
3705
3706TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093707 SessionDependencies session_deps(
3708 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023709
3710 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433711 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023712
3713 HttpRequestInfo request;
3714 request.method = "GET";
3715 request.url = GURL("https://www.google.com/");
3716 request.load_flags = 0;
3717
3718 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3719 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3720
3721 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353722 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3723 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023724 MockWrite("GET / HTTP/1.1\r\n"
3725 "Host: www.google.com\r\n"
3726 "Connection: keep-alive\r\n\r\n")
3727 };
3728
3729 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353730 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3731 arraysize(read_buffer)),
3732 MockRead("HTTP/1.0 200 OK\r\n"),
3733 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3734 MockRead("Payload"),
3735 MockRead(false, OK)
3736 };
3737
[email protected]31a2bfe2010-02-09 08:03:393738 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3739 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593740 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353741
[email protected]5ecc992a42009-11-11 01:41:593742 SSLSocketDataProvider ssl(true, OK);
3743 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353744
3745 TestCompletionCallback callback;
3746
[email protected]5a1d7ca2010-04-28 20:12:273747 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353748 EXPECT_EQ(ERR_IO_PENDING, rv);
3749
3750 rv = callback.WaitForResult();
3751 EXPECT_EQ(OK, rv);
3752
3753 const HttpResponseInfo* response = trans->GetResponseInfo();
3754 EXPECT_FALSE(response == NULL);
3755
3756 std::string response_text;
3757 rv = ReadTransaction(trans.get(), &response_text);
3758 EXPECT_EQ(OK, rv);
3759 EXPECT_EQ("Payload", response_text);
3760}
3761
3762TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093763 SessionDependencies session_deps(
3764 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353765
3766 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433767 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353768
3769 HttpRequestInfo request;
3770 request.method = "GET";
3771 request.url = GURL("http://www.google.com/");
3772 request.load_flags = 0;
3773
3774 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3775 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373776 const char kSOCKS5OkRequest[] = {
3777 0x05, // Version
3778 0x01, // Command (CONNECT)
3779 0x00, // Reserved.
3780 0x03, // Address type (DOMAINNAME).
3781 0x0E, // Length of domain (14)
3782 // Domain string:
3783 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3784 0x00, 0x50, // 16-bit port (80)
3785 };
[email protected]e0c27be2009-07-15 13:09:353786 const char kSOCKS5OkResponse[] =
3787 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3788
3789 MockWrite data_writes[] = {
3790 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3791 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3792 MockWrite("GET / HTTP/1.1\r\n"
3793 "Host: www.google.com\r\n"
3794 "Connection: keep-alive\r\n\r\n")
3795 };
3796
3797 MockRead data_reads[] = {
3798 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3799 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3800 MockRead("HTTP/1.0 200 OK\r\n"),
3801 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3802 MockRead("Payload"),
3803 MockRead(false, OK)
3804 };
3805
[email protected]31a2bfe2010-02-09 08:03:393806 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3807 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593808 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353809
3810 TestCompletionCallback callback;
3811
[email protected]5a1d7ca2010-04-28 20:12:273812 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353813 EXPECT_EQ(ERR_IO_PENDING, rv);
3814
3815 rv = callback.WaitForResult();
3816 EXPECT_EQ(OK, rv);
3817
3818 const HttpResponseInfo* response = trans->GetResponseInfo();
3819 EXPECT_FALSE(response == NULL);
3820
3821 std::string response_text;
3822 rv = ReadTransaction(trans.get(), &response_text);
3823 EXPECT_EQ(OK, rv);
3824 EXPECT_EQ("Payload", response_text);
3825}
3826
3827TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093828 SessionDependencies session_deps(
3829 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353830
3831 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433832 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353833
3834 HttpRequestInfo request;
3835 request.method = "GET";
3836 request.url = GURL("https://www.google.com/");
3837 request.load_flags = 0;
3838
3839 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3840 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373841 const unsigned char kSOCKS5OkRequest[] = {
3842 0x05, // Version
3843 0x01, // Command (CONNECT)
3844 0x00, // Reserved.
3845 0x03, // Address type (DOMAINNAME).
3846 0x0E, // Length of domain (14)
3847 // Domain string:
3848 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3849 0x01, 0xBB, // 16-bit port (443)
3850 };
3851
[email protected]e0c27be2009-07-15 13:09:353852 const char kSOCKS5OkResponse[] =
3853 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3854
3855 MockWrite data_writes[] = {
3856 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3857 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3858 arraysize(kSOCKS5OkRequest)),
3859 MockWrite("GET / HTTP/1.1\r\n"
3860 "Host: www.google.com\r\n"
3861 "Connection: keep-alive\r\n\r\n")
3862 };
3863
3864 MockRead data_reads[] = {
3865 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3866 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023867 MockRead("HTTP/1.0 200 OK\r\n"),
3868 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3869 MockRead("Payload"),
3870 MockRead(false, OK)
3871 };
3872
[email protected]31a2bfe2010-02-09 08:03:393873 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3874 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593875 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023876
[email protected]5ecc992a42009-11-11 01:41:593877 SSLSocketDataProvider ssl(true, OK);
3878 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023879
3880 TestCompletionCallback callback;
3881
[email protected]5a1d7ca2010-04-28 20:12:273882 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023883 EXPECT_EQ(ERR_IO_PENDING, rv);
3884
3885 rv = callback.WaitForResult();
3886 EXPECT_EQ(OK, rv);
3887
3888 const HttpResponseInfo* response = trans->GetResponseInfo();
3889 EXPECT_FALSE(response == NULL);
3890
3891 std::string response_text;
3892 rv = ReadTransaction(trans.get(), &response_text);
3893 EXPECT_EQ(OK, rv);
3894 EXPECT_EQ("Payload", response_text);
3895}
3896
[email protected]04e5be32009-06-26 20:00:313897// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063898
3899struct GroupNameTest {
3900 std::string proxy_server;
3901 std::string url;
3902 std::string expected_group_name;
3903};
3904
3905scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3906 const std::string& proxy_server) {
3907 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3909
3910 HttpAlternateProtocols* alternate_protocols =
3911 session->mutable_alternate_protocols();
3912 alternate_protocols->SetAlternateProtocolFor(
3913 HostPortPair("host.with.alternate", 80), 443,
3914 HttpAlternateProtocols::NPN_SPDY_1);
3915
3916 return session;
3917}
3918
3919int GroupNameTransactionHelper(
3920 const std::string& url,
3921 const scoped_refptr<HttpNetworkSession>& session) {
3922 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3923
3924 HttpRequestInfo request;
3925 request.method = "GET";
3926 request.url = GURL(url);
3927 request.load_flags = 0;
3928
3929 TestCompletionCallback callback;
3930
3931 // We do not complete this request, the dtor will clean the transaction up.
3932 return trans->Start(&request, &callback, BoundNetLog());
3933}
3934
3935TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
3936 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:313937 {
[email protected]2d731a32010-04-29 01:04:063938 "", // unused
[email protected]04e5be32009-06-26 20:00:313939 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:543940 "www.google.com:80",
3941 },
3942 {
[email protected]2d731a32010-04-29 01:04:063943 "", // unused
[email protected]2ff8b312010-04-26 22:20:543944 "http://[2001:1418:13:1::25]/direct",
3945 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:313946 },
[email protected]04e5be32009-06-26 20:00:313947
3948 // SSL Tests
3949 {
[email protected]2d731a32010-04-29 01:04:063950 "", // unused
[email protected]04e5be32009-06-26 20:00:313951 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:023952 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313953 },
3954 {
[email protected]2d731a32010-04-29 01:04:063955 "", // unused
3956 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:023957 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:313958 },
3959 {
[email protected]2d731a32010-04-29 01:04:063960 "", // unused
[email protected]2ff8b312010-04-26 22:20:543961 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:023962 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:543963 },
[email protected]2d731a32010-04-29 01:04:063964 };
[email protected]2ff8b312010-04-26 22:20:543965
[email protected]2d731a32010-04-29 01:04:063966 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3967
3968 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3969 scoped_refptr<HttpNetworkSession> session(
3970 SetupSessionForGroupNameTests(tests[i].proxy_server));
3971
3972 HttpNetworkSessionPeer peer(session);
3973 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3974 new CaptureGroupNameTCPSocketPool(session.get()));
3975 peer.SetTCPSocketPool(tcp_conn_pool);
3976
3977 EXPECT_EQ(ERR_IO_PENDING,
3978 GroupNameTransactionHelper(tests[i].url, session));
3979 EXPECT_EQ(tests[i].expected_group_name,
3980 tcp_conn_pool->last_group_name_received());
3981 }
3982
3983 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3984}
3985
3986TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
3987 const GroupNameTest tests[] = {
3988 {
3989 "http_proxy",
3990 "http://www.google.com/http_proxy_normal",
3991 "www.google.com:80",
3992 },
3993
3994 // SSL Tests
3995 {
3996 "http_proxy",
3997 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:023998 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:063999 },
4000
[email protected]9faeded92010-04-29 20:03:054001 {
4002 "http_proxy",
4003 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024004 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054005 },
[email protected]2d731a32010-04-29 01:04:064006 };
4007
4008 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4009
4010 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4011 scoped_refptr<HttpNetworkSession> session(
4012 SetupSessionForGroupNameTests(tests[i].proxy_server));
4013
4014 HttpNetworkSessionPeer peer(session);
4015
4016 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
4017 new CaptureGroupNameTCPSocketPool(session.get()));
4018 peer.SetSocketPoolForHTTPProxy(
4019 HostPortPair("http_proxy", 80), http_proxy_pool);
4020
4021 EXPECT_EQ(ERR_IO_PENDING,
4022 GroupNameTransactionHelper(tests[i].url, session));
4023 EXPECT_EQ(tests[i].expected_group_name,
4024 http_proxy_pool->last_group_name_received());
4025 }
4026
4027 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4028}
4029
4030TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4031 const GroupNameTest tests[] = {
4032 {
4033 "socks4://socks_proxy:1080",
4034 "http://www.google.com/socks4_direct",
4035 "socks4/www.google.com:80",
4036 },
4037 {
4038 "socks5://socks_proxy:1080",
4039 "http://www.google.com/socks5_direct",
4040 "socks5/www.google.com:80",
4041 },
4042
4043 // SSL Tests
4044 {
4045 "socks4://socks_proxy:1080",
4046 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024047 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064048 },
4049 {
4050 "socks5://socks_proxy:1080",
4051 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024052 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064053 },
4054
[email protected]9faeded92010-04-29 20:03:054055 {
4056 "socks4://socks_proxy:1080",
4057 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024058 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054059 },
[email protected]04e5be32009-06-26 20:00:314060 };
4061
[email protected]2ff8b312010-04-26 22:20:544062 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4063
[email protected]04e5be32009-06-26 20:00:314064 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064065 scoped_refptr<HttpNetworkSession> session(
4066 SetupSessionForGroupNameTests(tests[i].proxy_server));
4067 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314068
[email protected]a796bcec2010-03-22 17:17:264069 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064070 new CaptureGroupNameSOCKSSocketPool(session.get()));
4071 peer.SetSocketPoolForSOCKSProxy(
4072 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:314073
[email protected]5695b8c2009-09-30 21:36:434074 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314075
[email protected]2d731a32010-04-29 01:04:064076 EXPECT_EQ(ERR_IO_PENDING,
4077 GroupNameTransactionHelper(tests[i].url, session));
4078 EXPECT_EQ(tests[i].expected_group_name,
4079 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314080 }
[email protected]2ff8b312010-04-26 22:20:544081
4082 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314083}
4084
[email protected]9172a982009-06-06 00:30:254085TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544086 SessionDependencies session_deps(
4087 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324088
[email protected]69719062010-01-05 20:09:214089 // This simulates failure resolving all hostnames; that means we will fail
4090 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324091 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4092
[email protected]9172a982009-06-06 00:30:254093 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434094 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254095
4096 HttpRequestInfo request;
4097 request.method = "GET";
4098 request.url = GURL("http://www.google.com/");
4099
4100 TestCompletionCallback callback;
4101
[email protected]5a1d7ca2010-04-28 20:12:274102 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254103 EXPECT_EQ(ERR_IO_PENDING, rv);
4104
[email protected]9172a982009-06-06 00:30:254105 rv = callback.WaitForResult();
4106 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4107}
4108
[email protected]f3e6c1e2009-06-15 20:52:124109// Host resolution observer used by
4110// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4111// resovle requests are issued with a referrer of |expected_referrer|.
4112class ResolutionReferrerObserver : public HostResolver::Observer {
4113 public:
4114 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4115 : expected_referrer_(expected_referrer),
4116 called_start_with_referrer_(false),
4117 called_finish_with_referrer_(false) {
4118 }
4119
4120 virtual void OnStartResolution(int id,
4121 const HostResolver::RequestInfo& info) {
4122 if (info.referrer() == expected_referrer_)
4123 called_start_with_referrer_ = true;
4124 }
4125
4126 virtual void OnFinishResolutionWithStatus(
4127 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4128 if (info.referrer() == expected_referrer_)
4129 called_finish_with_referrer_ = true;
4130 }
4131
[email protected]eb255d32009-06-17 02:11:034132 virtual void OnCancelResolution(int id,
4133 const HostResolver::RequestInfo& info ) {
4134 FAIL() << "Should not be cancelling any requests!";
4135 }
4136
[email protected]f3e6c1e2009-06-15 20:52:124137 bool did_complete_with_expected_referrer() const {
4138 return called_start_with_referrer_ && called_finish_with_referrer_;
4139 }
4140
4141 private:
4142 GURL expected_referrer_;
4143 bool called_start_with_referrer_;
4144 bool called_finish_with_referrer_;
4145
4146 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4147};
4148
4149// Make sure that when HostResolver::Resolve() is invoked, it passes through
4150// the "referrer". This is depended on by the DNS prefetch observer.
4151TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4152 GURL referrer = GURL("http://expected-referrer/");
4153 EXPECT_TRUE(referrer.is_valid());
4154 ResolutionReferrerObserver resolution_observer(referrer);
4155
4156 SessionDependencies session_deps;
4157 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434158 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124159
4160 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144161 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124162
4163 // Connect up a mock socket which will fail when reading.
4164 MockRead data_reads[] = {
4165 MockRead(false, ERR_FAILED),
4166 };
[email protected]31a2bfe2010-02-09 08:03:394167 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594168 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124169
4170 // Issue a request, containing an HTTP referrer.
4171 HttpRequestInfo request;
4172 request.method = "GET";
4173 request.referrer = referrer;
4174 request.url = GURL("http://www.google.com/");
4175
4176 // Run the request until it fails reading from the socket.
4177 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274178 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124179 EXPECT_EQ(ERR_IO_PENDING, rv);
4180 rv = callback.WaitForResult();
4181 EXPECT_EQ(ERR_FAILED, rv);
4182
4183 // Check that the host resolution observer saw |referrer|.
4184 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4185}
4186
[email protected]685af592010-05-11 19:31:244187// Base test to make sure that when the load flags for a request specify to
4188// bypass the cache, the DNS cache is not used.
4189void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284190 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324191
[email protected]a2c2fb92009-07-18 07:31:044192 // Select a host resolver that does caching.
4193 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324194
[email protected]3b9cca42009-06-16 01:08:284195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434196 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284197
4198 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4199 // a synchronous lookup.)
4200 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144201 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464202 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274203 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284204 EXPECT_EQ(OK, rv);
4205
4206 // Verify that it was added to host cache, by doing a subsequent async lookup
4207 // and confirming it completes synchronously.
4208 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464209 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284210 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274211 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324212 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284213
4214 // Inject a failure the next time that "www.google.com" is resolved. This way
4215 // we can tell if the next lookup hit the cache, or the "network".
4216 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324217 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284218
4219 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4220 // first read -- this won't be reached as the host resolution will fail first.
4221 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394222 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594223 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284224
4225 // Issue a request, asking to bypass the cache(s).
4226 HttpRequestInfo request;
4227 request.method = "GET";
[email protected]685af592010-05-11 19:31:244228 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284229 request.url = GURL("http://www.google.com/");
4230
4231 // Run the request.
4232 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274233 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284234 ASSERT_EQ(ERR_IO_PENDING, rv);
4235 rv = callback.WaitForResult();
4236
4237 // If we bypassed the cache, we would have gotten a failure while resolving
4238 // "www.google.com".
4239 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4240}
4241
[email protected]685af592010-05-11 19:31:244242// There are multiple load flags that should trigger the host cache bypass.
4243// Test each in isolation:
4244TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4245 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4246}
4247
4248TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4249 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4250}
4251
4252TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4253 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4254}
4255
[email protected]0877e3d2009-10-17 22:29:574256// Make sure we can handle an error when writing the request.
4257TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4258 SessionDependencies session_deps;
4259 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4260
4261 HttpRequestInfo request;
4262 request.method = "GET";
4263 request.url = GURL("http://www.foo.com/");
4264 request.load_flags = 0;
4265
4266 MockWrite write_failure[] = {
4267 MockWrite(true, ERR_CONNECTION_RESET),
4268 };
[email protected]31a2bfe2010-02-09 08:03:394269 StaticSocketDataProvider data(NULL, 0,
4270 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594271 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574272
4273 TestCompletionCallback callback;
4274
4275 scoped_ptr<HttpTransaction> trans(
4276 new HttpNetworkTransaction(CreateSession(&session_deps)));
4277
[email protected]5a1d7ca2010-04-28 20:12:274278 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574279 EXPECT_EQ(ERR_IO_PENDING, rv);
4280
4281 rv = callback.WaitForResult();
4282 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4283}
4284
4285// Check that a connection closed after the start of the headers finishes ok.
4286TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4287 SessionDependencies session_deps;
4288 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4289
4290 HttpRequestInfo request;
4291 request.method = "GET";
4292 request.url = GURL("http://www.foo.com/");
4293 request.load_flags = 0;
4294
4295 MockRead data_reads[] = {
4296 MockRead("HTTP/1."),
4297 MockRead(false, OK),
4298 };
4299
[email protected]31a2bfe2010-02-09 08:03:394300 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594301 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574302
4303 TestCompletionCallback callback;
4304
4305 scoped_ptr<HttpTransaction> trans(
4306 new HttpNetworkTransaction(CreateSession(&session_deps)));
4307
[email protected]5a1d7ca2010-04-28 20:12:274308 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574309 EXPECT_EQ(ERR_IO_PENDING, rv);
4310
4311 rv = callback.WaitForResult();
4312 EXPECT_EQ(OK, rv);
4313
4314 const HttpResponseInfo* response = trans->GetResponseInfo();
4315 EXPECT_TRUE(response != NULL);
4316
4317 EXPECT_TRUE(response->headers != NULL);
4318 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4319
4320 std::string response_data;
4321 rv = ReadTransaction(trans.get(), &response_data);
4322 EXPECT_EQ(OK, rv);
4323 EXPECT_EQ("", response_data);
4324}
4325
4326// Make sure that a dropped connection while draining the body for auth
4327// restart does the right thing.
4328TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4329 SessionDependencies session_deps;
4330 scoped_ptr<HttpTransaction> trans(
4331 new HttpNetworkTransaction(CreateSession(&session_deps)));
4332
4333 HttpRequestInfo request;
4334 request.method = "GET";
4335 request.url = GURL("http://www.google.com/");
4336 request.load_flags = 0;
4337
4338 MockWrite data_writes1[] = {
4339 MockWrite("GET / HTTP/1.1\r\n"
4340 "Host: www.google.com\r\n"
4341 "Connection: keep-alive\r\n\r\n"),
4342 };
4343
4344 MockRead data_reads1[] = {
4345 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4346 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4347 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4348 MockRead("Content-Length: 14\r\n\r\n"),
4349 MockRead("Unauth"),
4350 MockRead(true, ERR_CONNECTION_RESET),
4351 };
4352
[email protected]31a2bfe2010-02-09 08:03:394353 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4354 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594355 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574356
4357 // After calling trans->RestartWithAuth(), this is the request we should
4358 // be issuing -- the final header line contains the credentials.
4359 MockWrite data_writes2[] = {
4360 MockWrite("GET / HTTP/1.1\r\n"
4361 "Host: www.google.com\r\n"
4362 "Connection: keep-alive\r\n"
4363 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4364 };
4365
4366 // Lastly, the server responds with the actual content.
4367 MockRead data_reads2[] = {
4368 MockRead("HTTP/1.1 200 OK\r\n"),
4369 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4370 MockRead("Content-Length: 100\r\n\r\n"),
4371 MockRead(false, OK),
4372 };
4373
[email protected]31a2bfe2010-02-09 08:03:394374 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4375 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594376 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574377
4378 TestCompletionCallback callback1;
4379
[email protected]5a1d7ca2010-04-28 20:12:274380 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574381 EXPECT_EQ(ERR_IO_PENDING, rv);
4382
4383 rv = callback1.WaitForResult();
4384 EXPECT_EQ(OK, rv);
4385
4386 const HttpResponseInfo* response = trans->GetResponseInfo();
4387 EXPECT_FALSE(response == NULL);
4388
4389 // The password prompt info should have been set in response->auth_challenge.
4390 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4391
4392 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4393 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4394 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4395
4396 TestCompletionCallback callback2;
4397
4398 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4399 EXPECT_EQ(ERR_IO_PENDING, rv);
4400
4401 rv = callback2.WaitForResult();
4402 EXPECT_EQ(OK, rv);
4403
4404 response = trans->GetResponseInfo();
4405 EXPECT_FALSE(response == NULL);
4406 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4407 EXPECT_EQ(100, response->headers->GetContentLength());
4408}
4409
4410// Test HTTPS connections going through a proxy that sends extra data.
4411TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4412 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4413
4414 HttpRequestInfo request;
4415 request.method = "GET";
4416 request.url = GURL("https://www.google.com/");
4417 request.load_flags = 0;
4418
4419 MockRead proxy_reads[] = {
4420 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4421 MockRead(false, OK)
4422 };
4423
[email protected]31a2bfe2010-02-09 08:03:394424 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594425 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574426
[email protected]5ecc992a42009-11-11 01:41:594427 session_deps.socket_factory.AddSocketDataProvider(&data);
4428 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574429
4430 TestCompletionCallback callback;
4431
4432 session_deps.socket_factory.ResetNextMockIndexes();
4433
4434 scoped_ptr<HttpTransaction> trans(
4435 new HttpNetworkTransaction(CreateSession(&session_deps)));
4436
[email protected]5a1d7ca2010-04-28 20:12:274437 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574438 EXPECT_EQ(ERR_IO_PENDING, rv);
4439
4440 rv = callback.WaitForResult();
4441 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4442}
4443
[email protected]e22e1362009-11-23 21:31:124444TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464445 SessionDependencies session_deps;
4446 scoped_ptr<HttpTransaction> trans(
4447 new HttpNetworkTransaction(CreateSession(&session_deps)));
4448
4449 HttpRequestInfo request;
4450 request.method = "GET";
4451 request.url = GURL("http://www.google.com/");
4452 request.load_flags = 0;
4453
[email protected]e22e1362009-11-23 21:31:124454 MockRead data_reads[] = {
4455 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4456 MockRead(false, OK),
4457 };
[email protected]9492e4a2010-02-24 00:58:464458
4459 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4460 session_deps.socket_factory.AddSocketDataProvider(&data);
4461
4462 TestCompletionCallback callback;
4463
[email protected]5a1d7ca2010-04-28 20:12:274464 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464465 EXPECT_EQ(ERR_IO_PENDING, rv);
4466
4467 EXPECT_EQ(OK, callback.WaitForResult());
4468
4469 const HttpResponseInfo* response = trans->GetResponseInfo();
4470 EXPECT_TRUE(response != NULL);
4471
4472 EXPECT_TRUE(response->headers != NULL);
4473 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4474
4475 std::string response_data;
4476 rv = ReadTransaction(trans.get(), &response_data);
4477 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124478}
4479
[email protected]95d88ffe2010-02-04 21:25:334480TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4481 SessionDependencies session_deps;
4482 scoped_ptr<HttpTransaction> trans(
4483 new HttpNetworkTransaction(CreateSession(&session_deps)));
4484
4485 HttpRequestInfo request;
4486 request.method = "POST";
4487 request.url = GURL("http://www.google.com/upload");
4488 request.upload_data = new UploadData;
4489 request.load_flags = 0;
4490
4491 FilePath temp_file_path;
4492 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4493 const uint64 kFakeSize = 100000; // file is actually blank
4494
4495 std::vector<UploadData::Element> elements;
4496 UploadData::Element element;
4497 element.SetToFilePath(temp_file_path);
4498 element.SetContentLength(kFakeSize);
4499 elements.push_back(element);
4500 request.upload_data->set_elements(elements);
4501 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4502
4503 MockRead data_reads[] = {
4504 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4505 MockRead("hello world"),
4506 MockRead(false, OK),
4507 };
[email protected]31a2bfe2010-02-09 08:03:394508 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334509 session_deps.socket_factory.AddSocketDataProvider(&data);
4510
4511 TestCompletionCallback callback;
4512
[email protected]5a1d7ca2010-04-28 20:12:274513 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334514 EXPECT_EQ(ERR_IO_PENDING, rv);
4515
4516 rv = callback.WaitForResult();
4517 EXPECT_EQ(OK, rv);
4518
4519 const HttpResponseInfo* response = trans->GetResponseInfo();
4520 EXPECT_TRUE(response != NULL);
4521
4522 EXPECT_TRUE(response->headers != NULL);
4523 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4524
4525 std::string response_data;
4526 rv = ReadTransaction(trans.get(), &response_data);
4527 EXPECT_EQ(OK, rv);
4528 EXPECT_EQ("hello world", response_data);
4529
4530 file_util::Delete(temp_file_path, false);
4531}
4532
[email protected]6624b4622010-03-29 19:58:364533TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4534 // If we try to upload an unreadable file, the network stack should report
4535 // the file size as zero and upload zero bytes for that file.
4536 SessionDependencies session_deps;
4537 scoped_ptr<HttpTransaction> trans(
4538 new HttpNetworkTransaction(CreateSession(&session_deps)));
4539
4540 FilePath temp_file;
4541 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4542 std::string temp_file_content("Unreadable file.");
4543 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4544 temp_file_content.length()));
4545 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4546
4547 HttpRequestInfo request;
4548 request.method = "POST";
4549 request.url = GURL("http://www.google.com/upload");
4550 request.upload_data = new UploadData;
4551 request.load_flags = 0;
4552
4553 std::vector<UploadData::Element> elements;
4554 UploadData::Element element;
4555 element.SetToFilePath(temp_file);
4556 elements.push_back(element);
4557 request.upload_data->set_elements(elements);
4558
4559 MockRead data_reads[] = {
4560 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4561 MockRead(false, OK),
4562 };
4563 MockWrite data_writes[] = {
4564 MockWrite("POST /upload HTTP/1.1\r\n"
4565 "Host: www.google.com\r\n"
4566 "Connection: keep-alive\r\n"
4567 "Content-Length: 0\r\n\r\n"),
4568 MockWrite(false, OK),
4569 };
4570 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4571 arraysize(data_writes));
4572 session_deps.socket_factory.AddSocketDataProvider(&data);
4573
4574 TestCompletionCallback callback;
4575
[email protected]5a1d7ca2010-04-28 20:12:274576 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364577 EXPECT_EQ(ERR_IO_PENDING, rv);
4578
4579 rv = callback.WaitForResult();
4580 EXPECT_EQ(OK, rv);
4581
4582 const HttpResponseInfo* response = trans->GetResponseInfo();
4583 EXPECT_TRUE(response != NULL);
4584 EXPECT_TRUE(response->headers != NULL);
4585 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4586
4587 file_util::Delete(temp_file, false);
4588}
4589
4590TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4591 SessionDependencies session_deps;
4592 scoped_ptr<HttpTransaction> trans(
4593 new HttpNetworkTransaction(CreateSession(&session_deps)));
4594
4595 FilePath temp_file;
4596 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4597 std::string temp_file_contents("Unreadable file.");
4598 std::string unreadable_contents(temp_file_contents.length(), '\0');
4599 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4600 temp_file_contents.length()));
4601
4602 HttpRequestInfo request;
4603 request.method = "POST";
4604 request.url = GURL("http://www.google.com/upload");
4605 request.upload_data = new UploadData;
4606 request.load_flags = 0;
4607
4608 std::vector<UploadData::Element> elements;
4609 UploadData::Element element;
4610 element.SetToFilePath(temp_file);
4611 elements.push_back(element);
4612 request.upload_data->set_elements(elements);
4613
4614 MockRead data_reads[] = {
4615 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4616 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4617 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4618
4619 MockRead("HTTP/1.1 200 OK\r\n"),
4620 MockRead("Content-Length: 0\r\n\r\n"),
4621 MockRead(false, OK),
4622 };
4623 MockWrite data_writes[] = {
4624 MockWrite("POST /upload HTTP/1.1\r\n"
4625 "Host: www.google.com\r\n"
4626 "Connection: keep-alive\r\n"
4627 "Content-Length: 16\r\n\r\n"),
4628 MockWrite(false, temp_file_contents.c_str()),
4629
4630 MockWrite("POST /upload HTTP/1.1\r\n"
4631 "Host: www.google.com\r\n"
4632 "Connection: keep-alive\r\n"
4633 "Content-Length: 16\r\n"
4634 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4635 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4636 MockWrite(false, OK),
4637 };
4638 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4639 arraysize(data_writes));
4640 session_deps.socket_factory.AddSocketDataProvider(&data);
4641
4642 TestCompletionCallback callback1;
4643
[email protected]5a1d7ca2010-04-28 20:12:274644 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364645 EXPECT_EQ(ERR_IO_PENDING, rv);
4646
4647 rv = callback1.WaitForResult();
4648 EXPECT_EQ(OK, rv);
4649
4650 const HttpResponseInfo* response = trans->GetResponseInfo();
4651 EXPECT_TRUE(response != NULL);
4652 EXPECT_TRUE(response->headers != NULL);
4653 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4654
4655 // The password prompt info should have been set in response->auth_challenge.
4656 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4657 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4658 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4659 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4660
4661 // Now make the file unreadable and try again.
4662 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4663
4664 TestCompletionCallback callback2;
4665
4666 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4667 EXPECT_EQ(ERR_IO_PENDING, rv);
4668
4669 rv = callback2.WaitForResult();
4670 EXPECT_EQ(OK, rv);
4671
4672 response = trans->GetResponseInfo();
4673 EXPECT_TRUE(response != NULL);
4674 EXPECT_TRUE(response->headers != NULL);
4675 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4676 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4677
4678 file_util::Delete(temp_file, false);
4679}
4680
[email protected]aeefc9e82010-02-19 16:18:274681// Tests that changes to Auth realms are treated like auth rejections.
4682TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4683 SessionDependencies session_deps;
4684 scoped_ptr<HttpTransaction> trans(
4685 new HttpNetworkTransaction(CreateSession(&session_deps)));
4686
4687 HttpRequestInfo request;
4688 request.method = "GET";
4689 request.url = GURL("http://www.google.com/");
4690 request.load_flags = 0;
4691
4692 // First transaction will request a resource and receive a Basic challenge
4693 // with realm="first_realm".
4694 MockWrite data_writes1[] = {
4695 MockWrite("GET / HTTP/1.1\r\n"
4696 "Host: www.google.com\r\n"
4697 "Connection: keep-alive\r\n"
4698 "\r\n"),
4699 };
4700 MockRead data_reads1[] = {
4701 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4702 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4703 "\r\n"),
4704 };
4705
4706 // After calling trans->RestartWithAuth(), provide an Authentication header
4707 // for first_realm. The server will reject and provide a challenge with
4708 // second_realm.
4709 MockWrite data_writes2[] = {
4710 MockWrite("GET / HTTP/1.1\r\n"
4711 "Host: www.google.com\r\n"
4712 "Connection: keep-alive\r\n"
4713 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4714 "\r\n"),
4715 };
4716 MockRead data_reads2[] = {
4717 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4718 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4719 "\r\n"),
4720 };
4721
4722 // This again fails, and goes back to first_realm. Make sure that the
4723 // entry is removed from cache.
4724 MockWrite data_writes3[] = {
4725 MockWrite("GET / HTTP/1.1\r\n"
4726 "Host: www.google.com\r\n"
4727 "Connection: keep-alive\r\n"
4728 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4729 "\r\n"),
4730 };
4731 MockRead data_reads3[] = {
4732 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4733 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4734 "\r\n"),
4735 };
4736
4737 // Try one last time (with the correct password) and get the resource.
4738 MockWrite data_writes4[] = {
4739 MockWrite("GET / HTTP/1.1\r\n"
4740 "Host: www.google.com\r\n"
4741 "Connection: keep-alive\r\n"
4742 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4743 "\r\n"),
4744 };
4745 MockRead data_reads4[] = {
4746 MockRead("HTTP/1.1 200 OK\r\n"
4747 "Content-Type: text/html; charset=iso-8859-1\r\n"
4748 "Content-Length: 100\r\n"
4749 "\r\n"),
4750 };
4751
4752 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4753 data_writes1, arraysize(data_writes1));
4754 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4755 data_writes2, arraysize(data_writes2));
4756 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4757 data_writes3, arraysize(data_writes3));
4758 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4759 data_writes4, arraysize(data_writes4));
4760 session_deps.socket_factory.AddSocketDataProvider(&data1);
4761 session_deps.socket_factory.AddSocketDataProvider(&data2);
4762 session_deps.socket_factory.AddSocketDataProvider(&data3);
4763 session_deps.socket_factory.AddSocketDataProvider(&data4);
4764
4765 TestCompletionCallback callback1;
4766
4767 // Issue the first request with Authorize headers. There should be a
4768 // password prompt for first_realm waiting to be filled in after the
4769 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274770 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274771 EXPECT_EQ(ERR_IO_PENDING, rv);
4772 rv = callback1.WaitForResult();
4773 EXPECT_EQ(OK, rv);
4774 const HttpResponseInfo* response = trans->GetResponseInfo();
4775 ASSERT_FALSE(response == NULL);
4776 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4777 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4778 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4779 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4780
4781 // Issue the second request with an incorrect password. There should be a
4782 // password prompt for second_realm waiting to be filled in after the
4783 // transaction completes.
4784 TestCompletionCallback callback2;
4785 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4786 EXPECT_EQ(ERR_IO_PENDING, rv);
4787 rv = callback2.WaitForResult();
4788 EXPECT_EQ(OK, rv);
4789 response = trans->GetResponseInfo();
4790 ASSERT_FALSE(response == NULL);
4791 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4792 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4793 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4794 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4795
4796 // Issue the third request with another incorrect password. There should be
4797 // a password prompt for first_realm waiting to be filled in. If the password
4798 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4799 // first_realm was not correctly removed.
4800 TestCompletionCallback callback3;
4801 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4802 EXPECT_EQ(ERR_IO_PENDING, rv);
4803 rv = callback3.WaitForResult();
4804 EXPECT_EQ(OK, rv);
4805 response = trans->GetResponseInfo();
4806 ASSERT_FALSE(response == NULL);
4807 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4808 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4809 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4810 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4811
4812 // Issue the fourth request with the correct password and username.
4813 TestCompletionCallback callback4;
4814 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4815 EXPECT_EQ(ERR_IO_PENDING, rv);
4816 rv = callback4.WaitForResult();
4817 EXPECT_EQ(OK, rv);
4818 response = trans->GetResponseInfo();
4819 ASSERT_FALSE(response == NULL);
4820 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4821}
4822
[email protected]564b4912010-03-09 16:30:424823TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424824 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064825 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424826
[email protected]564b4912010-03-09 16:30:424827 SessionDependencies session_deps;
4828
4829 MockRead data_reads[] = {
4830 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064831 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424832 MockRead("hello world"),
4833 MockRead(false, OK),
4834 };
4835
4836 HttpRequestInfo request;
4837 request.method = "GET";
4838 request.url = GURL("http://www.google.com/");
4839 request.load_flags = 0;
4840
4841 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4842
4843 session_deps.socket_factory.AddSocketDataProvider(&data);
4844
4845 TestCompletionCallback callback;
4846
4847 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4848 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4849
[email protected]5a1d7ca2010-04-28 20:12:274850 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534852
[email protected]564b4912010-03-09 16:30:424853 HostPortPair http_host_port_pair;
4854 http_host_port_pair.host = "www.google.com";
4855 http_host_port_pair.port = 80;
4856 const HttpAlternateProtocols& alternate_protocols =
4857 session->alternate_protocols();
4858 EXPECT_FALSE(
4859 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4860
4861 EXPECT_EQ(OK, callback.WaitForResult());
4862
4863 const HttpResponseInfo* response = trans->GetResponseInfo();
4864 ASSERT_TRUE(response != NULL);
4865 ASSERT_TRUE(response->headers != NULL);
4866 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4867
4868 std::string response_data;
4869 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4870 EXPECT_EQ("hello world", response_data);
4871
4872 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4873 const HttpAlternateProtocols::PortProtocolPair alternate =
4874 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4875 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4876 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064877 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424878 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424879
[email protected]31e2c69e2010-04-15 18:06:064880 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424881 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424882}
4883
4884TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064885 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424886 SessionDependencies session_deps;
4887
4888 HttpRequestInfo request;
4889 request.method = "GET";
4890 request.url = GURL("http://www.google.com/");
4891 request.load_flags = 0;
4892
4893 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4894 StaticSocketDataProvider first_data;
4895 first_data.set_connect_data(mock_connect);
4896 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4897
4898 MockRead data_reads[] = {
4899 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4900 MockRead("hello world"),
4901 MockRead(true, OK),
4902 };
4903 StaticSocketDataProvider second_data(
4904 data_reads, arraysize(data_reads), NULL, 0);
4905 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4906
4907 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4908 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4909 // http://crbug.com/37454.
4910 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4911
4912 TestCompletionCallback callback;
4913
4914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4915
4916 HostPortPair http_host_port_pair;
4917 http_host_port_pair.host = "www.google.com";
4918 http_host_port_pair.port = 80;
4919 HttpAlternateProtocols* alternate_protocols =
4920 session->mutable_alternate_protocols();
4921 alternate_protocols->SetAlternateProtocolFor(
4922 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064923 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424924
4925 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4926
[email protected]5a1d7ca2010-04-28 20:12:274927 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424928 EXPECT_EQ(ERR_IO_PENDING, rv);
4929 EXPECT_EQ(OK, callback.WaitForResult());
4930
4931 const HttpResponseInfo* response = trans->GetResponseInfo();
4932 ASSERT_TRUE(response != NULL);
4933 ASSERT_TRUE(response->headers != NULL);
4934 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4935
4936 std::string response_data;
4937 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4938 EXPECT_EQ("hello world", response_data);
4939
4940 ASSERT_TRUE(
4941 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4942 const HttpAlternateProtocols::PortProtocolPair alternate =
4943 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4944 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064945 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424946}
4947
4948// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4949// says that it does SPDY, but it just does the TLS handshake, but the NPN
4950// response does not indicate SPDY, so we just do standard HTTPS over the port.
4951// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4952// on the original port.
[email protected]a2cb8122010-03-10 17:22:424953// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4954// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534955//
[email protected]a2cb8122010-03-10 17:22:424956// HttpRequestInfo request;
4957// request.method = "GET";
4958// request.url = GURL("http://www.google.com/");
4959// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534960//
[email protected]a2cb8122010-03-10 17:22:424961// MockRead data_reads[] = {
4962// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4963// MockRead("hello world"),
4964// MockRead(true, OK),
4965// };
4966// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4967// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534968//
[email protected]a2cb8122010-03-10 17:22:424969// SSLSocketDataProvider ssl(true, OK);
4970// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534971//
[email protected]a2cb8122010-03-10 17:22:424972// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534973//
[email protected]a2cb8122010-03-10 17:22:424974// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534975//
[email protected]a2cb8122010-03-10 17:22:424976// HostPortPair http_host_port_pair;
4977// http_host_port_pair.host = "www.google.com";
4978// http_host_port_pair.port = 80;
4979// HttpAlternateProtocols* alternate_protocols =
4980// session->mutable_alternate_protocols();
4981// alternate_protocols->SetAlternateProtocolFor(
4982// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064983// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534984//
[email protected]a2cb8122010-03-10 17:22:424985// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534986//
[email protected]5a1d7ca2010-04-28 20:12:274987// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:424988// EXPECT_EQ(ERR_IO_PENDING, rv);
4989// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534990//
[email protected]a2cb8122010-03-10 17:22:424991// const HttpResponseInfo* response = trans->GetResponseInfo();
4992// ASSERT_TRUE(response != NULL);
4993// ASSERT_TRUE(response->headers != NULL);
4994// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534995//
[email protected]a2cb8122010-03-10 17:22:424996// std::string response_data;
4997// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4998// EXPECT_EQ("hello world", response_data);
4999// }
5000
5001TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065002 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545003 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115004 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425005 SessionDependencies session_deps;
5006
5007 HttpRequestInfo request;
5008 request.method = "GET";
5009 request.url = GURL("http://www.google.com/");
5010 request.load_flags = 0;
5011
[email protected]a2cb8122010-03-10 17:22:425012 StaticSocketDataProvider first_tcp_connect;
5013 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5014
5015 SSLSocketDataProvider ssl(true, OK);
5016 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5017
[email protected]564b4912010-03-09 16:30:425018 MockRead data_reads[] = {
5019 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5020 MockRead("hello world"),
5021 MockRead(true, OK),
5022 };
[email protected]a2cb8122010-03-10 17:22:425023 StaticSocketDataProvider fallback_data(
5024 data_reads, arraysize(data_reads), NULL, 0);
5025 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425026
5027 TestCompletionCallback callback;
5028
5029 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5030
5031 HostPortPair http_host_port_pair;
5032 http_host_port_pair.host = "www.google.com";
5033 http_host_port_pair.port = 80;
5034 HttpAlternateProtocols* alternate_protocols =
5035 session->mutable_alternate_protocols();
5036 alternate_protocols->SetAlternateProtocolFor(
5037 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065038 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425039
5040 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5041
[email protected]5a1d7ca2010-04-28 20:12:275042 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425043 EXPECT_EQ(ERR_IO_PENDING, rv);
5044 EXPECT_EQ(OK, callback.WaitForResult());
5045
5046 const HttpResponseInfo* response = trans->GetResponseInfo();
5047 ASSERT_TRUE(response != NULL);
5048 ASSERT_TRUE(response->headers != NULL);
5049 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5050
5051 std::string response_data;
5052 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5053 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545054 HttpNetworkTransaction::SetNextProtos("");
5055 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5056}
5057
5058TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5059 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5060 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115061 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545062 SessionDependencies session_deps;
5063
5064 HttpRequestInfo request;
5065 request.method = "GET";
5066 request.url = GURL("http://www.google.com/");
5067 request.load_flags = 0;
5068
5069 MockRead data_reads[] = {
5070 MockRead("HTTP/1.1 200 OK\r\n"),
5071 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5072 MockRead("hello world"),
5073 MockRead(true, OK),
5074 };
5075
5076 StaticSocketDataProvider first_transaction(
5077 data_reads, arraysize(data_reads), NULL, 0);
5078 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5079
5080 SSLSocketDataProvider ssl(true, OK);
5081 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5082 ssl.next_proto = "spdy/1";
5083 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5084
5085 MockWrite spdy_writes[] = {
5086 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5087 arraysize(kGetSyn)),
5088 };
5089
5090 MockRead spdy_reads[] = {
5091 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5092 arraysize(kGetSynReply)),
5093 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5094 arraysize(kGetBodyFrame)),
5095 MockRead(true, 0, 0),
5096 };
5097
5098 scoped_refptr<DelayedSocketData> spdy_data(
5099 new DelayedSocketData(
5100 1, // wait for one write to finish before reading.
5101 spdy_reads, arraysize(spdy_reads),
5102 spdy_writes, arraysize(spdy_writes)));
5103 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5104
5105 TestCompletionCallback callback;
5106
5107 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5108 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5109
[email protected]5a1d7ca2010-04-28 20:12:275110 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545111 EXPECT_EQ(ERR_IO_PENDING, rv);
5112 EXPECT_EQ(OK, callback.WaitForResult());
5113
5114 const HttpResponseInfo* response = trans->GetResponseInfo();
5115 ASSERT_TRUE(response != NULL);
5116 ASSERT_TRUE(response->headers != NULL);
5117 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5118
5119 std::string response_data;
5120 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5121 EXPECT_EQ("hello world", response_data);
5122
5123 trans.reset(new HttpNetworkTransaction(session));
5124
[email protected]5a1d7ca2010-04-28 20:12:275125 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545126 EXPECT_EQ(ERR_IO_PENDING, rv);
5127 EXPECT_EQ(OK, callback.WaitForResult());
5128
5129 response = trans->GetResponseInfo();
5130 ASSERT_TRUE(response != NULL);
5131 ASSERT_TRUE(response->headers != NULL);
5132 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5133
5134 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5135 EXPECT_EQ("hello!", response_data);
5136
5137 HttpNetworkTransaction::SetNextProtos("");
5138 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5139}
5140
[email protected]631f1322010-04-30 17:59:115141class CapturingProxyResolver : public ProxyResolver {
5142 public:
5143 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5144 virtual ~CapturingProxyResolver() {}
5145
5146 virtual int GetProxyForURL(const GURL& url,
5147 ProxyInfo* results,
5148 CompletionCallback* callback,
5149 RequestHandle* request,
5150 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425151 ProxyServer proxy_server(
5152 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5153 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115154 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425155 return OK;
[email protected]631f1322010-04-30 17:59:115156 }
5157
5158 virtual void CancelRequest(RequestHandle request) {
5159 NOTREACHED();
5160 }
5161
5162 const std::vector<GURL>& resolved() const { return resolved_; }
5163
5164 private:
5165 virtual int SetPacScript(const GURL& /*pac_url*/,
5166 const std::string& /*pac_bytes*/,
5167 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425168 return OK;
[email protected]631f1322010-04-30 17:59:115169 }
5170
5171 std::vector<GURL> resolved_;
5172
5173 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5174};
5175
[email protected]631f1322010-04-30 17:59:115176TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5177 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5178 HttpNetworkTransaction::SetNextProtos(
5179 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5180
5181 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425182 proxy_config.set_auto_detect(true);
5183 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115184
[email protected]631f1322010-04-30 17:59:115185 CapturingProxyResolver* capturing_proxy_resolver =
5186 new CapturingProxyResolver();
5187 SessionDependencies session_deps(
5188 new ProxyService(new ProxyConfigServiceFixed(proxy_config),
5189 capturing_proxy_resolver,
5190 NULL,
5191 NULL));
5192
5193 HttpRequestInfo request;
5194 request.method = "GET";
5195 request.url = GURL("http://www.google.com/");
5196 request.load_flags = 0;
5197
5198 MockRead data_reads[] = {
5199 MockRead("HTTP/1.1 200 OK\r\n"),
5200 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5201 MockRead("hello world"),
5202 MockRead(true, OK),
5203 };
5204
5205 StaticSocketDataProvider first_transaction(
5206 data_reads, arraysize(data_reads), NULL, 0);
5207 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5208
5209 SSLSocketDataProvider ssl(true, OK);
5210 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5211 ssl.next_proto = "spdy/1";
5212 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5213
5214 MockWrite spdy_writes[] = {
5215 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5216 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425217 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]631f1322010-04-30 17:59:115218 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
[email protected]d911f1b2010-05-05 22:39:425219 arraysize(kGetSyn)), // 3
[email protected]631f1322010-04-30 17:59:115220 };
5221
[email protected]d911f1b2010-05-05 22:39:425222 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5223
[email protected]631f1322010-04-30 17:59:115224 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425225 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
5226 MockRead(true, reinterpret_cast<const char*>(kGetSynReply), // 2, 4
5227 arraysize(kGetSynReply), 4),
5228 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame), // 5
5229 arraysize(kGetBodyFrame), 4),
5230 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115231 };
5232
[email protected]d911f1b2010-05-05 22:39:425233 scoped_refptr<OrderedSocketData> spdy_data(
5234 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115235 spdy_reads, arraysize(spdy_reads),
5236 spdy_writes, arraysize(spdy_writes)));
5237 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5238
5239 TestCompletionCallback callback;
5240
5241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5242 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5243
5244 int rv = trans->Start(&request, &callback, BoundNetLog());
5245 EXPECT_EQ(ERR_IO_PENDING, rv);
5246 EXPECT_EQ(OK, callback.WaitForResult());
5247
5248 const HttpResponseInfo* response = trans->GetResponseInfo();
5249 ASSERT_TRUE(response != NULL);
5250 ASSERT_TRUE(response->headers != NULL);
5251 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5252
5253 std::string response_data;
5254 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5255 EXPECT_EQ("hello world", response_data);
5256
5257 trans.reset(new HttpNetworkTransaction(session));
5258
5259 rv = trans->Start(&request, &callback, BoundNetLog());
5260 EXPECT_EQ(ERR_IO_PENDING, rv);
5261 EXPECT_EQ(OK, callback.WaitForResult());
5262
5263 response = trans->GetResponseInfo();
5264 ASSERT_TRUE(response != NULL);
5265 ASSERT_TRUE(response->headers != NULL);
5266 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5267
5268 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5269 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425270 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5271 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115272 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425273 EXPECT_EQ("https://www.google.com/",
5274 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115275
5276 HttpNetworkTransaction::SetNextProtos("");
5277 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5278}
[email protected]631f1322010-04-30 17:59:115279
[email protected]2ff8b312010-04-26 22:20:545280TEST_F(HttpNetworkTransactionTest,
5281 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5282 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5283 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115284 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545285 SessionDependencies session_deps;
5286
5287 HttpRequestInfo request;
5288 request.method = "GET";
5289 request.url = GURL("http://www.google.com/");
5290 request.load_flags = 0;
5291
5292 MockRead data_reads[] = {
5293 MockRead("HTTP/1.1 200 OK\r\n"),
5294 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5295 MockRead("hello world"),
5296 MockRead(true, OK),
5297 };
5298
5299 StaticSocketDataProvider first_transaction(
5300 data_reads, arraysize(data_reads), NULL, 0);
5301 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5302
5303 SSLSocketDataProvider ssl(true, OK);
5304 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5305 ssl.next_proto = "spdy/1";
5306 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5307
5308 MockWrite spdy_writes[] = {
5309 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5310 arraysize(kGetSyn)),
5311 };
5312
5313 MockRead spdy_reads[] = {
5314 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5315 arraysize(kGetSynReply)),
5316 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5317 arraysize(kGetBodyFrame)),
5318 MockRead(true, 0, 0),
5319 };
5320
5321 scoped_refptr<DelayedSocketData> spdy_data(
5322 new DelayedSocketData(
5323 1, // wait for one write to finish before reading.
5324 spdy_reads, arraysize(spdy_reads),
5325 spdy_writes, arraysize(spdy_writes)));
5326 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5327
5328 TestCompletionCallback callback;
5329
5330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5331
5332 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5333
[email protected]5a1d7ca2010-04-28 20:12:275334 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545335 EXPECT_EQ(ERR_IO_PENDING, rv);
5336 EXPECT_EQ(OK, callback.WaitForResult());
5337
5338 const HttpResponseInfo* response = trans->GetResponseInfo();
5339 ASSERT_TRUE(response != NULL);
5340 ASSERT_TRUE(response->headers != NULL);
5341 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5342
5343 std::string response_data;
5344 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5345 EXPECT_EQ("hello world", response_data);
5346
5347 // Set up an initial SpdySession in the pool to reuse.
5348 scoped_refptr<SpdySession> spdy_session =
5349 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365350 session, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545351 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365352 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545353
5354 trans.reset(new HttpNetworkTransaction(session));
5355
[email protected]5a1d7ca2010-04-28 20:12:275356 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545357 EXPECT_EQ(ERR_IO_PENDING, rv);
5358 EXPECT_EQ(OK, callback.WaitForResult());
5359
5360 response = trans->GetResponseInfo();
5361 ASSERT_TRUE(response != NULL);
5362 ASSERT_TRUE(response->headers != NULL);
5363 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5364
5365 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5366 EXPECT_EQ("hello!", response_data);
5367
5368 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065369 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425370}
5371
[email protected]e5ae96a2010-04-14 20:12:455372// MockAuthHandlerCanonical is used by the ResolveCanonicalName
5373// HttpNetworkTransaction unit test below. Callers set up expectations for
5374// whether the canonical name needs to be resolved.
5375class MockAuthHandlerCanonical : public HttpAuthHandler {
5376 public:
5377 enum Resolve {
5378 RESOLVE_INIT,
5379 RESOLVE_SKIP,
5380 RESOLVE_SYNC,
5381 RESOLVE_ASYNC,
5382 RESOLVE_TESTED,
5383 };
5384
5385 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
5386 virtual ~MockAuthHandlerCanonical() {}
5387
5388 void SetResolveExpectation(Resolve resolve) {
5389 EXPECT_EQ(RESOLVE_INIT, resolve_);
5390 resolve_ = resolve;
5391 }
5392
5393 void ResetResolveExpectation() {
5394 EXPECT_EQ(RESOLVE_TESTED, resolve_);
5395 resolve_ = RESOLVE_INIT;
5396 }
5397
5398 virtual bool NeedsCanonicalName() {
5399 switch (resolve_) {
5400 case RESOLVE_SYNC:
5401 case RESOLVE_ASYNC:
5402 return true;
5403 case RESOLVE_SKIP:
5404 resolve_ = RESOLVE_TESTED;
5405 return false;
5406 default:
5407 NOTREACHED();
5408 return false;
5409 }
5410 }
5411
5412 virtual int ResolveCanonicalName(HostResolver* host_resolver,
5413 CompletionCallback* callback,
5414 const BoundNetLog& net_log) {
5415 EXPECT_NE(RESOLVE_TESTED, resolve_);
5416 int rv = OK;
5417 switch (resolve_) {
5418 case RESOLVE_SYNC:
5419 resolve_ = RESOLVE_TESTED;
5420 break;
5421 case RESOLVE_ASYNC:
5422 EXPECT_TRUE(user_callback_ == NULL);
5423 rv = ERR_IO_PENDING;
5424 user_callback_ = callback;
5425 MessageLoop::current()->PostTask(
5426 FROM_HERE,
5427 NewRunnableMethod(
5428 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
5429 break;
5430 default:
5431 NOTREACHED();
5432 break;
5433 }
5434 return rv;
5435 }
5436
5437 void OnResolveCanonicalName() {
5438 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
5439 EXPECT_TRUE(user_callback_ != NULL);
5440 resolve_ = RESOLVE_TESTED;
5441 CompletionCallback* callback = user_callback_;
5442 user_callback_ = NULL;
5443 callback->Run(OK);
5444 }
5445
5446 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
5447 scheme_ = "mock";
5448 score_ = 1;
5449 properties_ = 0;
5450 return true;
5451 }
5452
5453 virtual int GenerateAuthToken(const std::wstring& username,
5454 const std::wstring& password,
5455 const HttpRequestInfo* request,
5456 const ProxyInfo* proxy,
5457 std::string* auth_token) {
5458 auth_token->assign("Mock AUTH myserver.example.com");
5459 return OK;
5460 }
5461
5462 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
5463 const ProxyInfo* proxy,
5464 std::string* auth_token) {
5465 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
5466 return OK;
5467 }
5468
5469 // The Factory class simply returns the same handler each time
5470 // CreateAuthHandler is called.
5471 class Factory : public HttpAuthHandlerFactory {
5472 public:
5473 Factory() {}
5474 virtual ~Factory() {}
5475
5476 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
5477 mock_handler_ = mock_handler;
5478 }
5479 MockAuthHandlerCanonical* mock_handler() const {
5480 return mock_handler_.get();
5481 }
5482
5483 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
5484 HttpAuth::Target target,
5485 const GURL& origin,
5486 scoped_refptr<HttpAuthHandler>* handler) {
5487 *handler = mock_handler_;
5488 return OK;
5489 }
5490
5491 private:
5492 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
5493 };
5494
5495 private:
5496 Resolve resolve_;
5497 CompletionCallback* user_callback_;
5498};
5499
5500// Tests that ResolveCanonicalName is handled correctly by the
5501// HttpNetworkTransaction.
5502TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5503 SessionDependencies session_deps;
5504 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
5505 new MockAuthHandlerCanonical());
5506 auth_handler->Init(NULL);
5507 MockAuthHandlerCanonical::Factory* auth_factory(
5508 new MockAuthHandlerCanonical::Factory());
5509 auth_factory->set_mock_handler(auth_handler);
5510 session_deps.http_auth_handler_factory.reset(auth_factory);
5511
5512 for (int i = 0; i < 2; ++i) {
5513 scoped_ptr<HttpTransaction> trans(
5514 new HttpNetworkTransaction(CreateSession(&session_deps)));
5515
5516 // Set up expectations for this pass of the test. Many of the EXPECT calls
5517 // are contained inside the MockAuthHandlerCanonical codebase in response to
5518 // the expectations.
[email protected]2227c692010-05-04 15:36:115519 MockAuthHandlerCanonical::Resolve resolve =
5520 (i == 0) ?
[email protected]e5ae96a2010-04-14 20:12:455521 MockAuthHandlerCanonical::RESOLVE_SYNC :
5522 MockAuthHandlerCanonical::RESOLVE_ASYNC;
5523 auth_handler->SetResolveExpectation(resolve);
5524 HttpRequestInfo request;
5525 request.method = "GET";
5526 request.url = GURL("http://myserver/");
5527 request.load_flags = 0;
5528
5529 MockWrite data_writes1[] = {
5530 MockWrite("GET / HTTP/1.1\r\n"
5531 "Host: myserver\r\n"
5532 "Connection: keep-alive\r\n\r\n"),
5533 };
5534
5535 MockRead data_reads1[] = {
5536 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5537 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5538 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5539 MockRead("Content-Length: 14\r\n\r\n"),
5540 MockRead("Unauthorized\r\n"),
5541 };
5542
5543 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5544 data_writes1, arraysize(data_writes1));
5545 session_deps.socket_factory.AddSocketDataProvider(&data1);
5546
5547 TestCompletionCallback callback1;
5548
[email protected]5a1d7ca2010-04-28 20:12:275549 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455550 EXPECT_EQ(ERR_IO_PENDING, rv);
5551
5552 rv = callback1.WaitForResult();
5553 EXPECT_EQ(OK, rv);
5554
5555 const HttpResponseInfo* response = trans->GetResponseInfo();
5556 EXPECT_FALSE(response == NULL);
5557
5558 // The password prompt is set after the canonical name is resolved.
5559 // If it isn't present or is incorrect, it indicates that the scheme
5560 // did not complete correctly.
5561 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5562
5563 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5564 EXPECT_EQ(L"", response->auth_challenge->realm);
5565 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
5566 auth_handler->ResetResolveExpectation();
5567 }
5568}
5569
[email protected]aeaca1f2010-04-20 22:05:215570class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5571 public:
5572 TLSDecompressionFailureSocketDataProvider(bool fail_all)
5573 : fail_all_(fail_all) {
5574 }
5575
5576 virtual MockRead GetNextRead() {
5577 if (fail_all_)
5578 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5579
5580 return MockRead(false /* async */,
5581 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5582 }
5583
5584 virtual MockWriteResult OnWrite(const std::string& data) {
5585 return MockWriteResult(false /* async */, data.size());
5586 }
5587
5588 void Reset() {
5589 }
5590
5591 private:
5592 const bool fail_all_;
5593};
5594
5595// Test that we restart a connection when we see a decompression failure from
5596// the peer during the handshake. (In the real world we'll restart with SSLv3
5597// and we won't offer DEFLATE in that case.)
5598TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5599 HttpRequestInfo request;
5600 request.method = "GET";
5601 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5602 request.load_flags = 0;
5603
5604 SessionDependencies session_deps;
5605 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5606 false /* fail all reads */);
5607 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5608 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115609 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215610 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5611 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5612 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5613 session_deps.socket_factory.AddSSLSocketDataProvider(
5614 &ssl_socket_data_provider1);
5615 session_deps.socket_factory.AddSSLSocketDataProvider(
5616 &ssl_socket_data_provider2);
5617
5618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5619 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5620 TestCompletionCallback callback;
5621
[email protected]5a1d7ca2010-04-28 20:12:275622 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215623 EXPECT_EQ(ERR_IO_PENDING, rv);
5624 EXPECT_EQ(OK, callback.WaitForResult());
5625
5626 const HttpResponseInfo* response = trans->GetResponseInfo();
5627 ASSERT_TRUE(response != NULL);
5628 ASSERT_TRUE(response->headers != NULL);
5629 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5630
5631 std::string response_data;
5632 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5633 EXPECT_EQ("ok.", response_data);
5634}
5635
5636// Test that we restart a connection if we get a decompression failure from the
5637// peer while reading the first bytes from the connection. This occurs when the
5638// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5639// in the handshake.
5640TEST_F(HttpNetworkTransactionTest,
5641 RestartAfterTLSDecompressionFailureWithFalseStart) {
5642 HttpRequestInfo request;
5643 request.method = "GET";
5644 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
5645 request.load_flags = 0;
5646
5647 SessionDependencies session_deps;
5648 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5649 true /* fail all reads */);
5650 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5651 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
5652 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5653 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5654 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5655 session_deps.socket_factory.AddSSLSocketDataProvider(
5656 &ssl_socket_data_provider1);
5657 session_deps.socket_factory.AddSSLSocketDataProvider(
5658 &ssl_socket_data_provider2);
5659
5660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5661 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5662 TestCompletionCallback callback;
5663
[email protected]5a1d7ca2010-04-28 20:12:275664 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215665 EXPECT_EQ(ERR_IO_PENDING, rv);
5666 EXPECT_EQ(OK, callback.WaitForResult());
5667
5668 const HttpResponseInfo* response = trans->GetResponseInfo();
5669 ASSERT_TRUE(response != NULL);
5670 ASSERT_TRUE(response->headers != NULL);
5671 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5672
5673 std::string response_data;
5674 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5675 EXPECT_EQ("ok.", response_data);
5676}
5677
[email protected]89ceba9a2009-03-21 03:46:065678} // namespace net