blob: 37d6f60273bd986b6bc92ad9f30e11c4707cc926 [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]3fd9dae2010-06-21 11:39:0026#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2927#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5728#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5332#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1133#include "net/proxy/proxy_resolver.h"
34#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4435#include "net/socket/client_socket_factory.h"
36#include "net/socket/socket_test_util.h"
37#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5438#include "net/spdy/spdy_framer.h"
39#include "net/spdy/spdy_session.h"
40#include "net/spdy/spdy_session_pool.h"
41#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5242#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1543#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5244
45//-----------------------------------------------------------------------------
46
[email protected]89ceba9a2009-03-21 03:46:0647namespace net {
48
[email protected]2d731a32010-04-29 01:04:0649class HttpNetworkSessionPeer {
50 public:
51 explicit HttpNetworkSessionPeer(
52 const scoped_refptr<HttpNetworkSession>& session)
53 : session_(session) {}
54
55 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
56 session_->tcp_socket_pool_ = pool;
57 }
58
59 void SetSocketPoolForSOCKSProxy(
60 const HostPortPair& socks_proxy,
61 const scoped_refptr<SOCKSClientSocketPool>& pool) {
62 session_->socks_socket_pool_[socks_proxy] = pool;
63 }
64
65 void SetSocketPoolForHTTPProxy(
66 const HostPortPair& http_proxy,
67 const scoped_refptr<TCPClientSocketPool>& pool) {
68 session_->http_proxy_socket_pool_[http_proxy] = pool;
69 }
70
71 private:
72 const scoped_refptr<HttpNetworkSession> session_;
73
74 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
75};
76
[email protected]e44de5d2009-06-05 20:12:4577// Helper to manage the lifetimes of the dependencies for a
78// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4479struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5980 // 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]a554a8262010-05-20 00:13:5285 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]66761b952010-06-25 21:30:3886 spdy_session_pool(new SpdySessionPool()) {}
[email protected]228ff742009-06-05 01:19:5987
88 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4589 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4290 : host_resolver(new MockHostResolver),
91 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1092 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5293 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]66761b952010-06-25 21:30:3894 spdy_session_pool(new SpdySessionPool()) {}
[email protected]228ff742009-06-05 01:19:5995
[email protected]a2c2fb92009-07-18 07:31:0496 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0997 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4298 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5999 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50100 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52101 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:59102};
103
[email protected]1c773ea12009-04-28 19:58:42104ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50105 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48106 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39107 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53108}
109
[email protected]228ff742009-06-05 01:19:59110HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38111 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09112 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42113 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10114 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52115 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17116 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44117 NULL,
[email protected]06650c52010-06-03 00:49:17118 NULL);
[email protected]e8d536192008-10-17 22:21:14119}
120
[email protected]89836e22008-09-25 20:33:42121class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52122 public:
[email protected]2ff8b312010-04-26 22:20:54123 virtual void SetUp() {
124 spdy::SpdyFramer::set_enable_compression_default(false);
125 }
126
[email protected]0e75a732008-10-16 20:36:09127 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54128 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09129 // Empty the current queue.
130 MessageLoop::current()->RunAllPending();
131 PlatformTest::TearDown();
132 }
133
[email protected]3d2a59b2008-09-26 19:44:25134 protected:
135 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52136
[email protected]ff007e162009-05-23 09:13:15137 struct SimpleGetHelperResult {
138 int rv;
139 std::string status_line;
140 std::string response_data;
141 };
initial.commit586acc5fe2008-07-26 22:42:52142
[email protected]31a2bfe2010-02-09 08:03:39143 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
144 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15145 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52146
[email protected]228ff742009-06-05 01:19:59147 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40148 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43149 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]ff007e162009-05-23 09:13:15151 HttpRequestInfo request;
152 request.method = "GET";
153 request.url = GURL("http://www.google.com/");
154 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]31a2bfe2010-02-09 08:03:39156 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59157 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]ff007e162009-05-23 09:13:15159 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52160
[email protected]169d0012010-05-10 23:20:12161 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
162 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15163 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52164
[email protected]ff007e162009-05-23 09:13:15165 out.rv = callback.WaitForResult();
166 if (out.rv != OK)
167 return out;
168
169 const HttpResponseInfo* response = trans->GetResponseInfo();
170 EXPECT_TRUE(response != NULL);
171
172 EXPECT_TRUE(response->headers != NULL);
173 out.status_line = response->headers->GetStatusLine();
174
175 rv = ReadTransaction(trans.get(), &out.response_data);
176 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39177 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12178 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
179 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39180 ExpectLogContainsSomewhere(
181 log.entries(), pos,
182 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
183 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15184
[email protected]aecfbf22008-10-16 02:02:47185 return out;
[email protected]ff007e162009-05-23 09:13:15186 }
initial.commit586acc5fe2008-07-26 22:42:52187
[email protected]ff007e162009-05-23 09:13:15188 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
189 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52190
[email protected]ff007e162009-05-23 09:13:15191 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15192};
[email protected]231d5a32008-09-13 00:45:27193
[email protected]15a5ccf82008-10-23 19:57:43194// Fill |str| with a long header list that consumes >= |size| bytes.
195void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19196 const char* row =
197 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
198 const int sizeof_row = strlen(row);
199 const int num_rows = static_cast<int>(
200 ceil(static_cast<float>(size) / sizeof_row));
201 const int sizeof_data = num_rows * sizeof_row;
202 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43203 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51204
[email protected]4ddaf2502008-10-23 18:26:19205 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43206 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19207}
208
[email protected]385a4672009-03-11 22:21:29209// Alternative functions that eliminate randomness and dependency on the local
210// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20211void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29212 static const uint8 bytes[] = {
213 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
214 };
215 static size_t current_byte = 0;
216 for (size_t i = 0; i < n; ++i) {
217 output[i] = bytes[current_byte++];
218 current_byte %= arraysize(bytes);
219 }
220}
221
[email protected]fe2bc6a2009-03-23 16:52:20222void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29223 static const uint8 bytes[] = {
224 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
225 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
226 };
227 static size_t current_byte = 0;
228 for (size_t i = 0; i < n; ++i) {
229 output[i] = bytes[current_byte++];
230 current_byte %= arraysize(bytes);
231 }
232}
233
[email protected]fe2bc6a2009-03-23 16:52:20234std::string MockGetHostName() {
235 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29236}
237
[email protected]2d731a32010-04-29 01:04:06238template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26239class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31240 public:
[email protected]06650c52010-06-03 00:49:17241 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]b89f7e42010-05-20 20:37:00242 : EmulatedClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
[email protected]66761b952010-06-25 21:30:38243 NULL) {
244 }
[email protected]d80a4322009-08-14 07:07:49245 const std::string last_group_name_received() const {
246 return last_group_name_;
247 }
248
[email protected]684970b2009-08-14 04:54:46249 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49250 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31251 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31252 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46253 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53254 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31255 last_group_name_ = group_name;
256 return ERR_IO_PENDING;
257 }
[email protected]04e5be32009-06-26 20:00:31258 virtual void CancelRequest(const std::string& group_name,
259 const ClientSocketHandle* handle) { }
260 virtual void ReleaseSocket(const std::string& group_name,
261 ClientSocket* socket) {}
262 virtual void CloseIdleSockets() {}
263 virtual HostResolver* GetHostResolver() const {
264 return NULL;
265 }
266 virtual int IdleSocketCount() const {
267 return 0;
268 }
269 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
270 return 0;
271 }
272 virtual LoadState GetLoadState(const std::string& group_name,
273 const ClientSocketHandle* handle) const {
274 return LOAD_STATE_IDLE;
275 }
[email protected]a796bcec2010-03-22 17:17:26276 virtual base::TimeDelta ConnectionTimeout() const {
277 return base::TimeDelta();
278 }
[email protected]d80a4322009-08-14 07:07:49279
280 private:
[email protected]04e5be32009-06-26 20:00:31281 std::string last_group_name_;
282};
283
[email protected]2d731a32010-04-29 01:04:06284typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11285CaptureGroupNameTCPSocketPool;
[email protected]2d731a32010-04-29 01:04:06286typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11287CaptureGroupNameSOCKSSocketPool;
288
[email protected]231d5a32008-09-13 00:45:27289//-----------------------------------------------------------------------------
290
291TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59292 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40293 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43294 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27295}
296
297TEST_F(HttpNetworkTransactionTest, SimpleGET) {
298 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35299 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
300 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42301 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27302 };
[email protected]31a2bfe2010-02-09 08:03:39303 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
304 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42305 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27306 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
307 EXPECT_EQ("hello world", out.response_data);
308}
309
310// Response with no status line.
311TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
312 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35313 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42314 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27315 };
[email protected]31a2bfe2010-02-09 08:03:39316 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
317 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42318 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27319 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
320 EXPECT_EQ("hello world", out.response_data);
321}
322
323// Allow up to 4 bytes of junk to precede status line.
324TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
325 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35326 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42327 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27328 };
[email protected]31a2bfe2010-02-09 08:03:39329 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
330 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42331 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27332 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
333 EXPECT_EQ("DATA", out.response_data);
334}
335
336// Allow up to 4 bytes of junk to precede status line.
337TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
338 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35339 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42340 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27341 };
[email protected]31a2bfe2010-02-09 08:03:39342 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
343 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42344 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27345 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
346 EXPECT_EQ("DATA", out.response_data);
347}
348
349// Beyond 4 bytes of slop and it should fail to find a status line.
350TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35352 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42353 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27354 };
[email protected]31a2bfe2010-02-09 08:03:39355 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
356 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42357 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25358 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
359 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27360}
361
362// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
363TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
364 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35365 MockRead("\n"),
366 MockRead("\n"),
367 MockRead("Q"),
368 MockRead("J"),
369 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42370 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27371 };
[email protected]31a2bfe2010-02-09 08:03:39372 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
373 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42374 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27375 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
376 EXPECT_EQ("DATA", out.response_data);
377}
378
379// Close the connection before enough bytes to have a status line.
380TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
381 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35382 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42383 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27384 };
[email protected]31a2bfe2010-02-09 08:03:39385 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
386 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42387 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27388 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
389 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52390}
391
[email protected]f9d44aa2008-09-23 23:57:17392// Simulate a 204 response, lacking a Content-Length header, sent over a
393// persistent connection. The response should still terminate since a 204
394// cannot have a response body.
395TEST_F(HttpNetworkTransactionTest, StopsReading204) {
396 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35397 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
398 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42399 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17400 };
[email protected]31a2bfe2010-02-09 08:03:39401 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
402 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42403 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17404 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
405 EXPECT_EQ("", out.response_data);
406}
407
[email protected]0877e3d2009-10-17 22:29:57408// A simple request using chunked encoding with some extra data after.
409// (Like might be seen in a pipelined response.)
410TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
411 MockRead data_reads[] = {
412 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
413 MockRead("5\r\nHello\r\n"),
414 MockRead("1\r\n"),
415 MockRead(" \r\n"),
416 MockRead("5\r\nworld\r\n"),
417 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
418 MockRead(false, OK),
419 };
[email protected]31a2bfe2010-02-09 08:03:39420 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
421 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57422 EXPECT_EQ(OK, out.rv);
423 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
424 EXPECT_EQ("Hello world", out.response_data);
425}
426
[email protected]ef0faf2e72009-03-05 23:27:23427// Do a request using the HEAD method. Verify that we don't try to read the
428// message body (since HEAD has none).
429TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59430 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40431 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43432 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23433
[email protected]1c773ea12009-04-28 19:58:42434 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23435 request.method = "HEAD";
436 request.url = GURL("http://www.google.com/");
437 request.load_flags = 0;
438
439 MockWrite data_writes1[] = {
440 MockWrite("HEAD / HTTP/1.1\r\n"
441 "Host: www.google.com\r\n"
442 "Connection: keep-alive\r\n"
443 "Content-Length: 0\r\n\r\n"),
444 };
445 MockRead data_reads1[] = {
446 MockRead("HTTP/1.1 404 Not Found\r\n"),
447 MockRead("Server: Blah\r\n"),
448 MockRead("Content-Length: 1234\r\n\r\n"),
449
450 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42451 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23452 };
453
[email protected]31a2bfe2010-02-09 08:03:39454 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
455 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59456 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23457
458 TestCompletionCallback callback1;
459
[email protected]5a1d7ca2010-04-28 20:12:27460 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42461 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23462
463 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42464 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23465
[email protected]1c773ea12009-04-28 19:58:42466 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23467 EXPECT_FALSE(response == NULL);
468
469 // Check that the headers got parsed.
470 EXPECT_TRUE(response->headers != NULL);
471 EXPECT_EQ(1234, response->headers->GetContentLength());
472 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
473
474 std::string server_header;
475 void* iter = NULL;
476 bool has_server_header = response->headers->EnumerateHeader(
477 &iter, "Server", &server_header);
478 EXPECT_TRUE(has_server_header);
479 EXPECT_EQ("Blah", server_header);
480
481 // Reading should give EOF right away, since there is no message body
482 // (despite non-zero content-length).
483 std::string response_data;
484 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42485 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23486 EXPECT_EQ("", response_data);
487}
488
initial.commit586acc5fe2008-07-26 22:42:52489TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59490 SessionDependencies session_deps;
491 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52492
493 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35494 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
495 MockRead("hello"),
496 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
497 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42498 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52499 };
[email protected]31a2bfe2010-02-09 08:03:39500 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59501 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52502
503 const char* kExpectedResponseData[] = {
504 "hello", "world"
505 };
506
507 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43508 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52509
[email protected]1c773ea12009-04-28 19:58:42510 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52511 request.method = "GET";
512 request.url = GURL("http://www.google.com/");
513 request.load_flags = 0;
514
515 TestCompletionCallback callback;
516
[email protected]5a1d7ca2010-04-28 20:12:27517 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42518 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52519
520 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42521 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52522
[email protected]1c773ea12009-04-28 19:58:42523 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52524 EXPECT_TRUE(response != NULL);
525
526 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25527 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52528
529 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57530 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42531 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25532 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52533 }
534}
535
536TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59537 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40538 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43539 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52540
[email protected]1c773ea12009-04-28 19:58:42541 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52542 request.method = "POST";
543 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42544 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52545 request.upload_data->AppendBytes("foo", 3);
546 request.load_flags = 0;
547
548 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35549 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
550 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
551 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42552 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52553 };
[email protected]31a2bfe2010-02-09 08:03:39554 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59555 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52556
557 TestCompletionCallback callback;
558
[email protected]5a1d7ca2010-04-28 20:12:27559 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42560 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52561
562 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42563 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52564
[email protected]1c773ea12009-04-28 19:58:42565 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52566 EXPECT_TRUE(response != NULL);
567
568 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25569 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52570
571 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57572 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42573 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25574 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52575}
576
[email protected]3a2d3662009-03-27 03:49:14577// This test is almost the same as Ignores100 above, but the response contains
578// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57579// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14580TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59581 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40582 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43583 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14584
[email protected]1c773ea12009-04-28 19:58:42585 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14586 request.method = "GET";
587 request.url = GURL("http://www.foo.com/");
588 request.load_flags = 0;
589
590 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57591 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
592 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14593 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42594 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14595 };
[email protected]31a2bfe2010-02-09 08:03:39596 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59597 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14598
599 TestCompletionCallback callback;
600
[email protected]5a1d7ca2010-04-28 20:12:27601 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42602 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14603
604 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42605 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14606
[email protected]1c773ea12009-04-28 19:58:42607 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14608 EXPECT_TRUE(response != NULL);
609
610 EXPECT_TRUE(response->headers != NULL);
611 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
612
613 std::string response_data;
614 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42615 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14616 EXPECT_EQ("hello world", response_data);
617}
618
[email protected]ee9410e72010-01-07 01:42:38619TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
620 SessionDependencies session_deps;
621 scoped_ptr<HttpTransaction> trans(
622 new HttpNetworkTransaction(CreateSession(&session_deps)));
623
624 HttpRequestInfo request;
625 request.method = "POST";
626 request.url = GURL("http://www.foo.com/");
627 request.load_flags = 0;
628
629 MockRead data_reads[] = {
630 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
631 MockRead(true, 0),
632 };
[email protected]31a2bfe2010-02-09 08:03:39633 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38634 session_deps.socket_factory.AddSocketDataProvider(&data);
635
636 TestCompletionCallback callback;
637
[email protected]5a1d7ca2010-04-28 20:12:27638 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38639 EXPECT_EQ(ERR_IO_PENDING, rv);
640
641 rv = callback.WaitForResult();
642 EXPECT_EQ(OK, rv);
643
644 std::string response_data;
645 rv = ReadTransaction(trans.get(), &response_data);
646 EXPECT_EQ(OK, rv);
647 EXPECT_EQ("", response_data);
648}
649
650TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
651 SessionDependencies session_deps;
652 scoped_ptr<HttpTransaction> trans(
653 new HttpNetworkTransaction(CreateSession(&session_deps)));
654
655 HttpRequestInfo request;
656 request.method = "POST";
657 request.url = GURL("http://www.foo.com/");
658 request.load_flags = 0;
659
660 MockRead data_reads[] = {
661 MockRead(true, 0),
662 };
[email protected]31a2bfe2010-02-09 08:03:39663 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38664 session_deps.socket_factory.AddSocketDataProvider(&data);
665
666 TestCompletionCallback callback;
667
[email protected]5a1d7ca2010-04-28 20:12:27668 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38669 EXPECT_EQ(ERR_IO_PENDING, rv);
670
671 rv = callback.WaitForResult();
672 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
673}
674
[email protected]3d2a59b2008-09-26 19:44:25675// read_failure specifies a read failure that should cause the network
676// transaction to resend the request.
677void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
678 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59679 SessionDependencies session_deps;
680 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52681
[email protected]1c773ea12009-04-28 19:58:42682 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52683 request.method = "GET";
684 request.url = GURL("http://www.foo.com/");
685 request.load_flags = 0;
686
687 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35688 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
689 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25690 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52691 };
[email protected]31a2bfe2010-02-09 08:03:39692 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59693 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52694
695 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35696 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
697 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42698 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52699 };
[email protected]31a2bfe2010-02-09 08:03:39700 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59701 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52702
703 const char* kExpectedResponseData[] = {
704 "hello", "world"
705 };
706
707 for (int i = 0; i < 2; ++i) {
708 TestCompletionCallback callback;
709
[email protected]5695b8c2009-09-30 21:36:43710 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52711
[email protected]5a1d7ca2010-04-28 20:12:27712 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52714
715 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42716 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52717
[email protected]1c773ea12009-04-28 19:58:42718 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52719 EXPECT_TRUE(response != NULL);
720
721 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25722 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52723
724 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57725 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42726 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25727 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52728 }
729}
[email protected]3d2a59b2008-09-26 19:44:25730
731TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42732 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25733 KeepAliveConnectionResendRequestTest(read_failure);
734}
735
736TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42737 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25738 KeepAliveConnectionResendRequestTest(read_failure);
739}
740
741TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59742 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40743 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43744 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25745
[email protected]1c773ea12009-04-28 19:58:42746 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25747 request.method = "GET";
748 request.url = GURL("http://www.google.com/");
749 request.load_flags = 0;
750
751 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42752 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35753 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
754 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42755 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25756 };
[email protected]31a2bfe2010-02-09 08:03:39757 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59758 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25759
760 TestCompletionCallback callback;
761
[email protected]5a1d7ca2010-04-28 20:12:27762 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42763 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25764
765 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42766 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25767
[email protected]1c773ea12009-04-28 19:58:42768 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25769 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25770}
771
772// What do various browsers do when the server closes a non-keepalive
773// connection without sending any response header or body?
774//
775// IE7: error page
776// Safari 3.1.2 (Windows): error page
777// Firefox 3.0.1: blank page
778// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42779// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
780// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25781TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
782 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42783 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35784 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
785 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42786 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25787 };
[email protected]31a2bfe2010-02-09 08:03:39788 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
789 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42790 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25791}
[email protected]038e9a32008-10-08 22:40:16792
[email protected]fc31d6a42010-06-24 18:05:13793// Test that we correctly reuse a keep-alive connection after receiving a 304.
794TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
795 SessionDependencies session_deps;
796 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
797
798 HttpRequestInfo request;
799 request.method = "GET";
800 request.url = GURL("http://www.foo.com/");
801 request.load_flags = 0;
802
803 MockRead data1_reads[] = {
804 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
805 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
806 MockRead("hello"),
807 };
808 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
809 session_deps.socket_factory.AddSocketDataProvider(&data1);
810
811 MockRead data2_reads[] = {
812 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
813 };
814 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
815 session_deps.socket_factory.AddSocketDataProvider(&data2);
816
817 for (int i = 0; i < 2; ++i) {
818 TestCompletionCallback callback;
819
820 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
821
822 int rv = trans->Start(&request, &callback, BoundNetLog());
823 EXPECT_EQ(ERR_IO_PENDING, rv);
824
825 rv = callback.WaitForResult();
826 EXPECT_EQ(OK, rv);
827
828 const HttpResponseInfo* response = trans->GetResponseInfo();
829 EXPECT_TRUE(response != NULL);
830
831 EXPECT_TRUE(response->headers != NULL);
832 if (i == 0) {
833 EXPECT_EQ("HTTP/1.1 304 Not Modified",
834 response->headers->GetStatusLine());
835 // We intentionally don't read the response in this case, to reflect how
836 // HttpCache::Transaction uses HttpNetworkTransaction.
837 } else {
838 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
839 std::string response_data;
840 rv = ReadTransaction(trans.get(), &response_data);
841 EXPECT_EQ(OK, rv);
842 EXPECT_EQ("hello", response_data);
843 }
844 }
845}
846
[email protected]038e9a32008-10-08 22:40:16847// Test the request-challenge-retry sequence for basic auth.
848// (basic auth is the easiest to mock, because it has no randomness).
849TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59850 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40851 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43852 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16853
[email protected]1c773ea12009-04-28 19:58:42854 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16855 request.method = "GET";
856 request.url = GURL("http://www.google.com/");
857 request.load_flags = 0;
858
[email protected]f9ee6b52008-11-08 06:46:23859 MockWrite data_writes1[] = {
860 MockWrite("GET / HTTP/1.1\r\n"
861 "Host: www.google.com\r\n"
862 "Connection: keep-alive\r\n\r\n"),
863 };
864
[email protected]038e9a32008-10-08 22:40:16865 MockRead data_reads1[] = {
866 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
867 // Give a couple authenticate options (only the middle one is actually
868 // supported).
[email protected]22927ad2009-09-21 19:56:19869 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16870 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
871 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
872 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
873 // Large content-length -- won't matter, as connection will be reset.
874 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42875 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16876 };
877
878 // After calling trans->RestartWithAuth(), this is the request we should
879 // be issuing -- the final header line contains the credentials.
880 MockWrite data_writes2[] = {
881 MockWrite("GET / HTTP/1.1\r\n"
882 "Host: www.google.com\r\n"
883 "Connection: keep-alive\r\n"
884 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
885 };
886
887 // Lastly, the server responds with the actual content.
888 MockRead data_reads2[] = {
889 MockRead("HTTP/1.0 200 OK\r\n"),
890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
891 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42892 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16893 };
894
[email protected]31a2bfe2010-02-09 08:03:39895 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
896 data_writes1, arraysize(data_writes1));
897 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
898 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59899 session_deps.socket_factory.AddSocketDataProvider(&data1);
900 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16901
902 TestCompletionCallback callback1;
903
[email protected]5a1d7ca2010-04-28 20:12:27904 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16906
907 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42908 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16909
[email protected]1c773ea12009-04-28 19:58:42910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16911 EXPECT_FALSE(response == NULL);
912
913 // The password prompt info should have been set in response->auth_challenge.
914 EXPECT_FALSE(response->auth_challenge.get() == NULL);
915
[email protected]71e4573a2009-05-21 22:03:00916 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16917 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
918 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
919
920 TestCompletionCallback callback2;
921
922 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42923 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16924
925 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42926 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16927
928 response = trans->GetResponseInfo();
929 EXPECT_FALSE(response == NULL);
930 EXPECT_TRUE(response->auth_challenge.get() == NULL);
931 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16932}
933
[email protected]861fcd52009-08-26 02:33:46934TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
935 SessionDependencies session_deps;
936 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43937 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46938
939 HttpRequestInfo request;
940 request.method = "GET";
941 request.url = GURL("http://www.google.com/");
942 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
943
944 MockWrite data_writes[] = {
945 MockWrite("GET / HTTP/1.1\r\n"
946 "Host: www.google.com\r\n"
947 "Connection: keep-alive\r\n\r\n"),
948 };
949
950 MockRead data_reads[] = {
951 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
952 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
954 // Large content-length -- won't matter, as connection will be reset.
955 MockRead("Content-Length: 10000\r\n\r\n"),
956 MockRead(false, ERR_FAILED),
957 };
958
[email protected]31a2bfe2010-02-09 08:03:39959 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
960 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59961 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46962 TestCompletionCallback callback;
963
[email protected]5a1d7ca2010-04-28 20:12:27964 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46965 EXPECT_EQ(ERR_IO_PENDING, rv);
966
967 rv = callback.WaitForResult();
968 EXPECT_EQ(0, rv);
969
970 const HttpResponseInfo* response = trans->GetResponseInfo();
971 ASSERT_FALSE(response == NULL);
972 EXPECT_TRUE(response->auth_challenge.get() == NULL);
973}
974
[email protected]2d2697f92009-02-18 21:00:32975// Test the request-challenge-retry sequence for basic auth, over a keep-alive
976// connection.
977TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59978 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40979 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43980 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32981
[email protected]1c773ea12009-04-28 19:58:42982 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32983 request.method = "GET";
984 request.url = GURL("http://www.google.com/");
985 request.load_flags = 0;
986
987 MockWrite data_writes1[] = {
988 MockWrite("GET / HTTP/1.1\r\n"
989 "Host: www.google.com\r\n"
990 "Connection: keep-alive\r\n\r\n"),
991
992 // After calling trans->RestartWithAuth(), this is the request we should
993 // be issuing -- the final header line contains the credentials.
994 MockWrite("GET / HTTP/1.1\r\n"
995 "Host: www.google.com\r\n"
996 "Connection: keep-alive\r\n"
997 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
998 };
999
1000 MockRead data_reads1[] = {
1001 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1002 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1004 MockRead("Content-Length: 14\r\n\r\n"),
1005 MockRead("Unauthorized\r\n"),
1006
1007 // Lastly, the server responds with the actual content.
1008 MockRead("HTTP/1.1 200 OK\r\n"),
1009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1010 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421011 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321012 };
1013
[email protected]31a2bfe2010-02-09 08:03:391014 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1015 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591016 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321017
1018 TestCompletionCallback callback1;
1019
[email protected]5a1d7ca2010-04-28 20:12:271020 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421021 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321022
1023 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421024 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321025
[email protected]1c773ea12009-04-28 19:58:421026 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321027 EXPECT_FALSE(response == NULL);
1028
1029 // The password prompt info should have been set in response->auth_challenge.
1030 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1031
[email protected]71e4573a2009-05-21 22:03:001032 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321033 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1034 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1035
1036 TestCompletionCallback callback2;
1037
1038 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421039 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321040
1041 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421042 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321043
1044 response = trans->GetResponseInfo();
1045 EXPECT_FALSE(response == NULL);
1046 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1047 EXPECT_EQ(100, response->headers->GetContentLength());
1048}
1049
1050// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1051// connection and with no response body to drain.
1052TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591053 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401054 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431055 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321056
[email protected]1c773ea12009-04-28 19:58:421057 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321058 request.method = "GET";
1059 request.url = GURL("http://www.google.com/");
1060 request.load_flags = 0;
1061
1062 MockWrite data_writes1[] = {
1063 MockWrite("GET / HTTP/1.1\r\n"
1064 "Host: www.google.com\r\n"
1065 "Connection: keep-alive\r\n\r\n"),
1066
1067 // After calling trans->RestartWithAuth(), this is the request we should
1068 // be issuing -- the final header line contains the credentials.
1069 MockWrite("GET / HTTP/1.1\r\n"
1070 "Host: www.google.com\r\n"
1071 "Connection: keep-alive\r\n"
1072 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1073 };
1074
[email protected]2d2697f92009-02-18 21:00:321075 MockRead data_reads1[] = {
1076 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1077 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311078 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321079
1080 // Lastly, the server responds with the actual content.
1081 MockRead("HTTP/1.1 200 OK\r\n"),
1082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1083 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421084 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321085 };
1086
[email protected]31a2bfe2010-02-09 08:03:391087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1088 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591089 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321090
1091 TestCompletionCallback callback1;
1092
[email protected]5a1d7ca2010-04-28 20:12:271093 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421094 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321095
1096 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421097 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321098
[email protected]1c773ea12009-04-28 19:58:421099 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321100 EXPECT_FALSE(response == NULL);
1101
1102 // The password prompt info should have been set in response->auth_challenge.
1103 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1104
[email protected]71e4573a2009-05-21 22:03:001105 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321106 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1107 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1108
1109 TestCompletionCallback callback2;
1110
1111 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421112 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321113
1114 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421115 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321116
1117 response = trans->GetResponseInfo();
1118 EXPECT_FALSE(response == NULL);
1119 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1120 EXPECT_EQ(100, response->headers->GetContentLength());
1121}
1122
1123// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1124// connection and with a large response body to drain.
1125TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591126 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401127 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431128 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321129
[email protected]1c773ea12009-04-28 19:58:421130 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321131 request.method = "GET";
1132 request.url = GURL("http://www.google.com/");
1133 request.load_flags = 0;
1134
1135 MockWrite data_writes1[] = {
1136 MockWrite("GET / HTTP/1.1\r\n"
1137 "Host: www.google.com\r\n"
1138 "Connection: keep-alive\r\n\r\n"),
1139
1140 // After calling trans->RestartWithAuth(), this is the request we should
1141 // be issuing -- the final header line contains the credentials.
1142 MockWrite("GET / HTTP/1.1\r\n"
1143 "Host: www.google.com\r\n"
1144 "Connection: keep-alive\r\n"
1145 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1146 };
1147
1148 // Respond with 5 kb of response body.
1149 std::string large_body_string("Unauthorized");
1150 large_body_string.append(5 * 1024, ' ');
1151 large_body_string.append("\r\n");
1152
1153 MockRead data_reads1[] = {
1154 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1155 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1157 // 5134 = 12 + 5 * 1024 + 2
1158 MockRead("Content-Length: 5134\r\n\r\n"),
1159 MockRead(true, large_body_string.data(), large_body_string.size()),
1160
1161 // Lastly, the server responds with the actual content.
1162 MockRead("HTTP/1.1 200 OK\r\n"),
1163 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1164 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421165 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321166 };
1167
[email protected]31a2bfe2010-02-09 08:03:391168 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1169 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591170 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321171
1172 TestCompletionCallback callback1;
1173
[email protected]5a1d7ca2010-04-28 20:12:271174 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421175 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321176
1177 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421178 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321179
[email protected]1c773ea12009-04-28 19:58:421180 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321181 EXPECT_FALSE(response == NULL);
1182
1183 // The password prompt info should have been set in response->auth_challenge.
1184 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1185
[email protected]71e4573a2009-05-21 22:03:001186 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321187 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1188 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1189
1190 TestCompletionCallback callback2;
1191
1192 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421193 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321194
1195 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421196 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321197
1198 response = trans->GetResponseInfo();
1199 EXPECT_FALSE(response == NULL);
1200 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1201 EXPECT_EQ(100, response->headers->GetContentLength());
1202}
1203
1204// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311205// connection, but the server gets impatient and closes the connection.
1206TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1207 SessionDependencies session_deps;
1208 scoped_ptr<HttpTransaction> trans(
1209 new HttpNetworkTransaction(CreateSession(&session_deps)));
1210
1211 HttpRequestInfo request;
1212 request.method = "GET";
1213 request.url = GURL("http://www.google.com/");
1214 request.load_flags = 0;
1215
1216 MockWrite data_writes1[] = {
1217 MockWrite("GET / HTTP/1.1\r\n"
1218 "Host: www.google.com\r\n"
1219 "Connection: keep-alive\r\n\r\n"),
1220 // This simulates the seemingly successful write to a closed connection
1221 // if the bug is not fixed.
1222 MockWrite("GET / HTTP/1.1\r\n"
1223 "Host: www.google.com\r\n"
1224 "Connection: keep-alive\r\n"
1225 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1226 };
1227
1228 MockRead data_reads1[] = {
1229 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1230 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1231 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1232 MockRead("Content-Length: 14\r\n\r\n"),
1233 // Tell MockTCPClientSocket to simulate the server closing the connection.
1234 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1235 MockRead("Unauthorized\r\n"),
1236 MockRead(false, OK), // The server closes the connection.
1237 };
1238
1239 // After calling trans->RestartWithAuth(), this is the request we should
1240 // be issuing -- the final header line contains the credentials.
1241 MockWrite data_writes2[] = {
1242 MockWrite("GET / HTTP/1.1\r\n"
1243 "Host: www.google.com\r\n"
1244 "Connection: keep-alive\r\n"
1245 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1246 };
1247
1248 // Lastly, the server responds with the actual content.
1249 MockRead data_reads2[] = {
1250 MockRead("HTTP/1.1 200 OK\r\n"),
1251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1252 MockRead("Content-Length: 100\r\n\r\n"),
1253 MockRead(false, OK),
1254 };
1255
[email protected]31a2bfe2010-02-09 08:03:391256 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1257 data_writes1, arraysize(data_writes1));
1258 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1259 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311260 session_deps.socket_factory.AddSocketDataProvider(&data1);
1261 session_deps.socket_factory.AddSocketDataProvider(&data2);
1262
1263 TestCompletionCallback callback1;
1264
[email protected]5a1d7ca2010-04-28 20:12:271265 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311266 EXPECT_EQ(ERR_IO_PENDING, rv);
1267
1268 rv = callback1.WaitForResult();
1269 EXPECT_EQ(OK, rv);
1270
1271 const HttpResponseInfo* response = trans->GetResponseInfo();
1272 EXPECT_FALSE(response == NULL);
1273
1274 // The password prompt info should have been set in response->auth_challenge.
1275 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1276
1277 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1278 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1279 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1280
1281 TestCompletionCallback callback2;
1282
1283 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1284 EXPECT_EQ(ERR_IO_PENDING, rv);
1285
1286 rv = callback2.WaitForResult();
1287 EXPECT_EQ(OK, rv);
1288
1289 response = trans->GetResponseInfo();
1290 ASSERT_FALSE(response == NULL);
1291 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1292 EXPECT_EQ(100, response->headers->GetContentLength());
1293}
1294
1295// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321296// proxy connection, when setting up an SSL tunnel.
1297TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1298 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591299 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321301
[email protected]5695b8c2009-09-30 21:36:431302 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321303
[email protected]1c773ea12009-04-28 19:58:421304 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321305 request.method = "GET";
1306 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461307 // Ensure that proxy authentication is attempted even
1308 // when the no authentication data flag is set.
1309 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321310
1311 // Since we have proxy, should try to establish tunnel.
1312 MockWrite data_writes1[] = {
1313 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451314 "Host: www.google.com\r\n"
1315 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321316
1317 // After calling trans->RestartWithAuth(), this is the request we should
1318 // be issuing -- the final header line contains the credentials.
1319 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1320 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451321 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321322 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1323 };
1324
1325 // The proxy responds to the connect with a 407, using a persistent
1326 // connection.
1327 MockRead data_reads1[] = {
1328 // No credentials.
1329 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1330 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1331 MockRead("Content-Length: 10\r\n\r\n"),
1332 MockRead("0123456789"),
1333
1334 // Wrong credentials (wrong password).
1335 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1336 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1337 MockRead("Content-Length: 10\r\n\r\n"),
1338 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421339 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321340 };
1341
[email protected]31a2bfe2010-02-09 08:03:391342 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1343 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591344 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321345
1346 TestCompletionCallback callback1;
1347
[email protected]dbb83db2010-05-11 18:13:391348 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1349 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421350 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321351
1352 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421353 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391354 size_t pos = ExpectLogContainsSomewhere(
1355 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1356 NetLog::PHASE_NONE);
1357 ExpectLogContainsSomewhere(
1358 log.entries(), pos,
1359 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1360 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321361
[email protected]1c773ea12009-04-28 19:58:421362 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321363 EXPECT_FALSE(response == NULL);
1364
1365 EXPECT_TRUE(response->headers->IsKeepAlive());
1366 EXPECT_EQ(407, response->headers->response_code());
1367 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421368 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321369
1370 // The password prompt info should have been set in response->auth_challenge.
1371 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1372
[email protected]71e4573a2009-05-21 22:03:001373 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321374 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1375 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1376
1377 TestCompletionCallback callback2;
1378
1379 // Wrong password (should be "bar").
1380 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321382
1383 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421384 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321385
1386 response = trans->GetResponseInfo();
1387 EXPECT_FALSE(response == NULL);
1388
1389 EXPECT_TRUE(response->headers->IsKeepAlive());
1390 EXPECT_EQ(407, response->headers->response_code());
1391 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421392 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321393
1394 // The password prompt info should have been set in response->auth_challenge.
1395 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1396
[email protected]71e4573a2009-05-21 22:03:001397 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321398 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1399 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1400}
1401
[email protected]a8e9b162009-03-12 00:06:441402// Test that we don't read the response body when we fail to establish a tunnel,
1403// even if the user cancels the proxy's auth attempt.
1404TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1405 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591406 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441407
[email protected]e44de5d2009-06-05 20:12:451408 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441409
[email protected]5695b8c2009-09-30 21:36:431410 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441411
[email protected]1c773ea12009-04-28 19:58:421412 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441413 request.method = "GET";
1414 request.url = GURL("https://www.google.com/");
1415 request.load_flags = 0;
1416
1417 // Since we have proxy, should try to establish tunnel.
1418 MockWrite data_writes[] = {
1419 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451420 "Host: www.google.com\r\n"
1421 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441422 };
1423
1424 // The proxy responds to the connect with a 407.
1425 MockRead data_reads[] = {
1426 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1427 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1428 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421429 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441430 };
1431
[email protected]31a2bfe2010-02-09 08:03:391432 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1433 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591434 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441435
1436 TestCompletionCallback callback;
1437
[email protected]5a1d7ca2010-04-28 20:12:271438 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421439 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441440
1441 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421442 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441443
[email protected]1c773ea12009-04-28 19:58:421444 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441445 EXPECT_FALSE(response == NULL);
1446
1447 EXPECT_TRUE(response->headers->IsKeepAlive());
1448 EXPECT_EQ(407, response->headers->response_code());
1449 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421450 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441451
1452 std::string response_data;
1453 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421454 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441455}
1456
[email protected]8fdbcd22010-05-05 02:54:521457// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1458// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1459TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1460 // We are using a DIRECT connection (i.e. no proxy) for this session.
1461 SessionDependencies session_deps;
1462 scoped_ptr<HttpTransaction> trans(
1463 new HttpNetworkTransaction(CreateSession(&session_deps)));
1464
1465 HttpRequestInfo request;
1466 request.method = "GET";
1467 request.url = GURL("http://www.google.com/");
1468 request.load_flags = 0;
1469
1470 MockWrite data_writes1[] = {
1471 MockWrite("GET / HTTP/1.1\r\n"
1472 "Host: www.google.com\r\n"
1473 "Connection: keep-alive\r\n\r\n"),
1474 };
1475
1476 MockRead data_reads1[] = {
1477 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1478 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1479 // Large content-length -- won't matter, as connection will be reset.
1480 MockRead("Content-Length: 10000\r\n\r\n"),
1481 MockRead(false, ERR_FAILED),
1482 };
1483
1484 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1485 data_writes1, arraysize(data_writes1));
1486 session_deps.socket_factory.AddSocketDataProvider(&data1);
1487
1488 TestCompletionCallback callback;
1489
1490 int rv = trans->Start(&request, &callback, BoundNetLog());
1491 EXPECT_EQ(ERR_IO_PENDING, rv);
1492
1493 rv = callback.WaitForResult();
1494 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1495}
1496
[email protected]ff007e162009-05-23 09:13:151497void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081498 const MockRead& status, int expected_status) {
1499 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591500 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081501
[email protected]228ff742009-06-05 01:19:591502 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081503
[email protected]5695b8c2009-09-30 21:36:431504 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081505
[email protected]1c773ea12009-04-28 19:58:421506 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081507 request.method = "GET";
1508 request.url = GURL("https://www.google.com/");
1509 request.load_flags = 0;
1510
1511 // Since we have proxy, should try to establish tunnel.
1512 MockWrite data_writes[] = {
1513 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451514 "Host: www.google.com\r\n"
1515 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081516 };
1517
1518 MockRead data_reads[] = {
1519 status,
1520 MockRead("Content-Length: 10\r\n\r\n"),
1521 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421522 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081523 };
1524
[email protected]31a2bfe2010-02-09 08:03:391525 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1526 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591527 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081528
1529 TestCompletionCallback callback;
1530
[email protected]5a1d7ca2010-04-28 20:12:271531 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421532 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081533
1534 rv = callback.WaitForResult();
1535 EXPECT_EQ(expected_status, rv);
1536}
1537
[email protected]ff007e162009-05-23 09:13:151538void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081539 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421540 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081541}
1542
1543TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1544 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1545}
1546
1547TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1548 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1549}
1550
1551TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1552 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1553}
1554
1555TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1556 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1557}
1558
1559TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1560 ConnectStatusHelper(
1561 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1562}
1563
1564TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1565 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1566}
1567
1568TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1569 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1570}
1571
1572TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1573 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1574}
1575
1576TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1577 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1578}
1579
1580TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1581 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1582}
1583
1584TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1585 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1586}
1587
1588TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1589 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1590}
1591
1592TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1593 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1594}
1595
1596TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1597 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1598}
1599
1600TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1601 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1602}
1603
1604TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1605 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1606}
1607
1608TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1609 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1610}
1611
1612TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1613 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1614}
1615
1616TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1617 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1618}
1619
1620TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1621 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1622}
1623
1624TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1625 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1626}
1627
1628TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1629 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1630}
1631
1632TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1633 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1634}
1635
1636TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1637 ConnectStatusHelperWithExpectedStatus(
1638 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421639 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081640}
1641
1642TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1643 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1644}
1645
1646TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1647 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1648}
1649
1650TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1651 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1652}
1653
1654TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1655 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1656}
1657
1658TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1659 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1660}
1661
1662TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1663 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1664}
1665
1666TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1667 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1668}
1669
1670TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1671 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1672}
1673
1674TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1675 ConnectStatusHelper(
1676 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1677}
1678
1679TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1680 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1681}
1682
1683TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1684 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1685}
1686
1687TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1688 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1689}
1690
1691TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1692 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1693}
1694
1695TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1696 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1697}
1698
1699TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1700 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1701}
1702
1703TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1704 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1705}
1706
[email protected]038e9a32008-10-08 22:40:161707// Test the flow when both the proxy server AND origin server require
1708// authentication. Again, this uses basic auth for both since that is
1709// the simplest to mock.
1710TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591711 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011712
[email protected]038e9a32008-10-08 22:40:161713 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431715 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161716
[email protected]1c773ea12009-04-28 19:58:421717 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161718 request.method = "GET";
1719 request.url = GURL("http://www.google.com/");
1720 request.load_flags = 0;
1721
[email protected]f9ee6b52008-11-08 06:46:231722 MockWrite data_writes1[] = {
1723 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1724 "Host: www.google.com\r\n"
1725 "Proxy-Connection: keep-alive\r\n\r\n"),
1726 };
1727
[email protected]038e9a32008-10-08 22:40:161728 MockRead data_reads1[] = {
1729 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1730 // Give a couple authenticate options (only the middle one is actually
1731 // supported).
[email protected]22927ad2009-09-21 19:56:191732 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161733 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1734 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1735 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1736 // Large content-length -- won't matter, as connection will be reset.
1737 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421738 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161739 };
1740
1741 // After calling trans->RestartWithAuth() the first time, this is the
1742 // request we should be issuing -- the final header line contains the
1743 // proxy's credentials.
1744 MockWrite data_writes2[] = {
1745 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1746 "Host: www.google.com\r\n"
1747 "Proxy-Connection: keep-alive\r\n"
1748 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1749 };
1750
1751 // Now the proxy server lets the request pass through to origin server.
1752 // The origin server responds with a 401.
1753 MockRead data_reads2[] = {
1754 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1755 // Note: We are using the same realm-name as the proxy server. This is
1756 // completely valid, as realms are unique across hosts.
1757 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1758 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1759 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421760 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161761 };
1762
1763 // After calling trans->RestartWithAuth() the second time, we should send
1764 // the credentials for both the proxy and origin server.
1765 MockWrite data_writes3[] = {
1766 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1767 "Host: www.google.com\r\n"
1768 "Proxy-Connection: keep-alive\r\n"
1769 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1770 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1771 };
1772
1773 // Lastly we get the desired content.
1774 MockRead data_reads3[] = {
1775 MockRead("HTTP/1.0 200 OK\r\n"),
1776 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1777 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421778 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161779 };
1780
[email protected]31a2bfe2010-02-09 08:03:391781 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1782 data_writes1, arraysize(data_writes1));
1783 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1784 data_writes2, arraysize(data_writes2));
1785 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1786 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591787 session_deps.socket_factory.AddSocketDataProvider(&data1);
1788 session_deps.socket_factory.AddSocketDataProvider(&data2);
1789 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161790
1791 TestCompletionCallback callback1;
1792
[email protected]5a1d7ca2010-04-28 20:12:271793 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421794 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161795
1796 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421797 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161798
[email protected]1c773ea12009-04-28 19:58:421799 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161800 EXPECT_FALSE(response == NULL);
1801
1802 // The password prompt info should have been set in response->auth_challenge.
1803 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1804
[email protected]71e4573a2009-05-21 22:03:001805 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161806 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1807 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1808
1809 TestCompletionCallback callback2;
1810
1811 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421812 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161813
1814 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421815 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161816
1817 response = trans->GetResponseInfo();
1818 EXPECT_FALSE(response == NULL);
1819 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1820
[email protected]71e4573a2009-05-21 22:03:001821 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161822 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1823 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1824
1825 TestCompletionCallback callback3;
1826
1827 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421828 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161829
1830 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421831 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161832
1833 response = trans->GetResponseInfo();
1834 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1835 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161836}
[email protected]4ddaf2502008-10-23 18:26:191837
[email protected]ea9dc9a2009-09-05 00:43:321838// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1839// can't hook into its internals to cause it to generate predictable NTLM
1840// authorization headers.
1841#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291842// The NTLM authentication unit tests were generated by capturing the HTTP
1843// requests and responses using Fiddler 2 and inspecting the generated random
1844// bytes in the debugger.
1845
1846// Enter the correct password and authenticate successfully.
1847TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421848 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111849 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591850 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401851 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431852 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241853
[email protected]1c773ea12009-04-28 19:58:421854 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241855 request.method = "GET";
1856 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1857 request.load_flags = 0;
1858
1859 MockWrite data_writes1[] = {
1860 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1861 "Host: 172.22.68.17\r\n"
1862 "Connection: keep-alive\r\n\r\n"),
1863 };
1864
1865 MockRead data_reads1[] = {
1866 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:041867 // Negotiate and NTLM are often requested together. However, we only want
1868 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
1869 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:241870 MockRead("WWW-Authenticate: NTLM\r\n"),
1871 MockRead("Connection: close\r\n"),
1872 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361873 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241874 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421875 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241876 };
1877
1878 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221879 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241880 // request we should be issuing -- the final header line contains a Type
1881 // 1 message.
1882 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1883 "Host: 172.22.68.17\r\n"
1884 "Connection: keep-alive\r\n"
1885 "Authorization: NTLM "
1886 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1887
1888 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1889 // (the credentials for the origin server). The second request continues
1890 // on the same connection.
1891 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1892 "Host: 172.22.68.17\r\n"
1893 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291894 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1895 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1896 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1897 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1898 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241899 };
1900
1901 MockRead data_reads2[] = {
1902 // The origin server responds with a Type 2 message.
1903 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1904 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291905 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241906 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1907 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1908 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1909 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1910 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1911 "BtAAAAAAA=\r\n"),
1912 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361913 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241914 MockRead("You are not authorized to view this page\r\n"),
1915
1916 // Lastly we get the desired content.
1917 MockRead("HTTP/1.1 200 OK\r\n"),
1918 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1919 MockRead("Content-Length: 13\r\n\r\n"),
1920 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421921 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241922 };
1923
[email protected]31a2bfe2010-02-09 08:03:391924 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1925 data_writes1, arraysize(data_writes1));
1926 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1927 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591928 session_deps.socket_factory.AddSocketDataProvider(&data1);
1929 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241930
1931 TestCompletionCallback callback1;
1932
[email protected]5a1d7ca2010-04-28 20:12:271933 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421934 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241935
1936 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421937 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241938
[email protected]0757e7702009-03-27 04:00:221939 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1940 TestCompletionCallback callback2;
1941 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421942 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221943 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421944 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221945 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1946
[email protected]1c773ea12009-04-28 19:58:421947 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:041948 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:241949
[email protected]aef04272010-06-28 18:03:041950 // The password prompt info should have been set in
1951 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:241952 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1953
[email protected]71e4573a2009-05-21 22:03:001954 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241955 EXPECT_EQ(L"", response->auth_challenge->realm);
1956 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1957
[email protected]0757e7702009-03-27 04:00:221958 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241959
[email protected]0757e7702009-03-27 04:00:221960 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421961 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241962
[email protected]0757e7702009-03-27 04:00:221963 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421964 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241965
1966 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:041967 ASSERT_FALSE(response == NULL);
1968
[email protected]3f918782009-02-28 01:29:241969 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1970 EXPECT_EQ(13, response->headers->GetContentLength());
1971}
1972
[email protected]385a4672009-03-11 22:21:291973// Enter a wrong password, and then the correct one.
1974TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421975 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111976 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591977 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401978 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431979 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291980
[email protected]1c773ea12009-04-28 19:58:421981 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291982 request.method = "GET";
1983 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1984 request.load_flags = 0;
1985
1986 MockWrite data_writes1[] = {
1987 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1988 "Host: 172.22.68.17\r\n"
1989 "Connection: keep-alive\r\n\r\n"),
1990 };
1991
1992 MockRead data_reads1[] = {
1993 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:041994 // Negotiate and NTLM are often requested together. However, we only want
1995 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
1996 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:291997 MockRead("WWW-Authenticate: NTLM\r\n"),
1998 MockRead("Connection: close\r\n"),
1999 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362000 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292001 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422002 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292003 };
2004
2005 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222006 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292007 // request we should be issuing -- the final header line contains a Type
2008 // 1 message.
2009 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2010 "Host: 172.22.68.17\r\n"
2011 "Connection: keep-alive\r\n"
2012 "Authorization: NTLM "
2013 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2014
2015 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2016 // (the credentials for the origin server). The second request continues
2017 // on the same connection.
2018 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2019 "Host: 172.22.68.17\r\n"
2020 "Connection: keep-alive\r\n"
2021 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2022 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2023 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2024 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2025 "4Ww7b7E=\r\n\r\n"),
2026 };
2027
2028 MockRead data_reads2[] = {
2029 // The origin server responds with a Type 2 message.
2030 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2031 MockRead("WWW-Authenticate: NTLM "
2032 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2033 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2034 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2035 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2036 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2037 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2038 "BtAAAAAAA=\r\n"),
2039 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362040 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292041 MockRead("You are not authorized to view this page\r\n"),
2042
2043 // Wrong password.
2044 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292045 MockRead("WWW-Authenticate: NTLM\r\n"),
2046 MockRead("Connection: close\r\n"),
2047 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362048 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292049 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422050 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292051 };
2052
2053 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222054 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292055 // request we should be issuing -- the final header line contains a Type
2056 // 1 message.
2057 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2058 "Host: 172.22.68.17\r\n"
2059 "Connection: keep-alive\r\n"
2060 "Authorization: NTLM "
2061 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2062
2063 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2064 // (the credentials for the origin server). The second request continues
2065 // on the same connection.
2066 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2067 "Host: 172.22.68.17\r\n"
2068 "Connection: keep-alive\r\n"
2069 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2070 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2071 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2072 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2073 "+4MUm7c=\r\n\r\n"),
2074 };
2075
2076 MockRead data_reads3[] = {
2077 // The origin server responds with a Type 2 message.
2078 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2079 MockRead("WWW-Authenticate: NTLM "
2080 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2081 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2082 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2083 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2084 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2085 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2086 "BtAAAAAAA=\r\n"),
2087 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362088 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292089 MockRead("You are not authorized to view this page\r\n"),
2090
2091 // Lastly we get the desired content.
2092 MockRead("HTTP/1.1 200 OK\r\n"),
2093 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2094 MockRead("Content-Length: 13\r\n\r\n"),
2095 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422096 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292097 };
2098
[email protected]31a2bfe2010-02-09 08:03:392099 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2100 data_writes1, arraysize(data_writes1));
2101 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2102 data_writes2, arraysize(data_writes2));
2103 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2104 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592105 session_deps.socket_factory.AddSocketDataProvider(&data1);
2106 session_deps.socket_factory.AddSocketDataProvider(&data2);
2107 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292108
2109 TestCompletionCallback callback1;
2110
[email protected]5a1d7ca2010-04-28 20:12:272111 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422112 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292113
2114 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422115 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292116
[email protected]0757e7702009-03-27 04:00:222117 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292118 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222119 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422120 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292121 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422122 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222123 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292124
[email protected]1c773ea12009-04-28 19:58:422125 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292126 EXPECT_FALSE(response == NULL);
2127
2128 // The password prompt info should have been set in response->auth_challenge.
2129 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2130
[email protected]71e4573a2009-05-21 22:03:002131 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292132 EXPECT_EQ(L"", response->auth_challenge->realm);
2133 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2134
2135 TestCompletionCallback callback3;
2136
[email protected]0757e7702009-03-27 04:00:222137 // Enter the wrong password.
2138 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422139 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292140
2141 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422142 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292143
[email protected]0757e7702009-03-27 04:00:222144 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2145 TestCompletionCallback callback4;
2146 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222148 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422149 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222150 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2151
2152 response = trans->GetResponseInfo();
2153 EXPECT_FALSE(response == NULL);
2154
2155 // The password prompt info should have been set in response->auth_challenge.
2156 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2157
[email protected]71e4573a2009-05-21 22:03:002158 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222159 EXPECT_EQ(L"", response->auth_challenge->realm);
2160 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2161
2162 TestCompletionCallback callback5;
2163
2164 // Now enter the right password.
2165 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422166 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222167
2168 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422169 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222170
[email protected]385a4672009-03-11 22:21:292171 response = trans->GetResponseInfo();
2172 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2173 EXPECT_EQ(13, response->headers->GetContentLength());
2174}
[email protected]ea9dc9a2009-09-05 00:43:322175#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292176
[email protected]4ddaf2502008-10-23 18:26:192177// Test reading a server response which has only headers, and no body.
2178// After some maximum number of bytes is consumed, the transaction should
2179// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2180TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592181 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402182 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432183 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192184
[email protected]1c773ea12009-04-28 19:58:422185 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192186 request.method = "GET";
2187 request.url = GURL("http://www.google.com/");
2188 request.load_flags = 0;
2189
[email protected]b75b7b2f2009-10-06 00:54:532190 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432191 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532192 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192193
2194 MockRead data_reads[] = {
2195 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432196 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192197 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422198 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192199 };
[email protected]31a2bfe2010-02-09 08:03:392200 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592201 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192202
2203 TestCompletionCallback callback;
2204
[email protected]5a1d7ca2010-04-28 20:12:272205 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422206 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192207
2208 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422209 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192210
[email protected]1c773ea12009-04-28 19:58:422211 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192212 EXPECT_TRUE(response == NULL);
2213}
[email protected]f4e426b2008-11-05 00:24:492214
2215// Make sure that we don't try to reuse a TCPClientSocket when failing to
2216// establish tunnel.
2217// http://code.google.com/p/chromium/issues/detail?id=3772
2218TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2219 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592220 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012221
[email protected]228ff742009-06-05 01:19:592222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492223
[email protected]5695b8c2009-09-30 21:36:432224 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492225
[email protected]1c773ea12009-04-28 19:58:422226 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492227 request.method = "GET";
2228 request.url = GURL("https://www.google.com/");
2229 request.load_flags = 0;
2230
2231 // Since we have proxy, should try to establish tunnel.
2232 MockWrite data_writes1[] = {
2233 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452234 "Host: www.google.com\r\n"
2235 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492236 };
2237
[email protected]77848d12008-11-14 00:00:222238 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492239 // connection. Usually a proxy would return 501 (not implemented),
2240 // or 200 (tunnel established).
2241 MockRead data_reads1[] = {
2242 MockRead("HTTP/1.1 404 Not Found\r\n"),
2243 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422244 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492245 };
2246
[email protected]31a2bfe2010-02-09 08:03:392247 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2248 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592249 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492250
2251 TestCompletionCallback callback1;
2252
[email protected]5a1d7ca2010-04-28 20:12:272253 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422254 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492255
2256 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422257 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492258
[email protected]1c773ea12009-04-28 19:58:422259 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082260 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492261
[email protected]b4404c02009-04-10 16:38:522262 // Empty the current queue. This is necessary because idle sockets are
2263 // added to the connection pool asynchronously with a PostTask.
2264 MessageLoop::current()->RunAllPending();
2265
[email protected]f4e426b2008-11-05 00:24:492266 // We now check to make sure the TCPClientSocket was not added back to
2267 // the pool.
[email protected]a937a06d2009-08-19 21:19:242268 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492269 trans.reset();
[email protected]b4404c02009-04-10 16:38:522270 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492271 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242272 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492273}
[email protected]372d34a2008-11-05 21:30:512274
[email protected]1b157c02009-04-21 01:55:402275// Make sure that we recycle a socket after reading all of the response body.
2276TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592277 SessionDependencies session_deps;
2278 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402279
[email protected]5695b8c2009-09-30 21:36:432280 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402281
[email protected]1c773ea12009-04-28 19:58:422282 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402283 request.method = "GET";
2284 request.url = GURL("http://www.google.com/");
2285 request.load_flags = 0;
2286
2287 MockRead data_reads[] = {
2288 // A part of the response body is received with the response headers.
2289 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2290 // The rest of the response body is received in two parts.
2291 MockRead("lo"),
2292 MockRead(" world"),
2293 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422294 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402295 };
2296
[email protected]31a2bfe2010-02-09 08:03:392297 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592298 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402299
2300 TestCompletionCallback callback;
2301
[email protected]5a1d7ca2010-04-28 20:12:272302 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422303 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402304
2305 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422306 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402307
[email protected]1c773ea12009-04-28 19:58:422308 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402309 EXPECT_TRUE(response != NULL);
2310
2311 EXPECT_TRUE(response->headers != NULL);
2312 std::string status_line = response->headers->GetStatusLine();
2313 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2314
[email protected]a937a06d2009-08-19 21:19:242315 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402316
2317 std::string response_data;
2318 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422319 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402320 EXPECT_EQ("hello world", response_data);
2321
2322 // Empty the current queue. This is necessary because idle sockets are
2323 // added to the connection pool asynchronously with a PostTask.
2324 MessageLoop::current()->RunAllPending();
2325
2326 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242327 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402328}
2329
[email protected]b4404c02009-04-10 16:38:522330// Make sure that we recycle a socket after a zero-length response.
2331// http://crbug.com/9880
2332TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592333 SessionDependencies session_deps;
2334 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522335
[email protected]5695b8c2009-09-30 21:36:432336 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522337
[email protected]1c773ea12009-04-28 19:58:422338 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522339 request.method = "GET";
2340 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2341 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2342 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2343 "rt=prt.2642,ol.2649,xjs.2951");
2344 request.load_flags = 0;
2345
2346 MockRead data_reads[] = {
2347 MockRead("HTTP/1.1 204 No Content\r\n"
2348 "Content-Length: 0\r\n"
2349 "Content-Type: text/html\r\n\r\n"),
2350 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422351 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522352 };
2353
[email protected]31a2bfe2010-02-09 08:03:392354 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592355 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522356
2357 TestCompletionCallback callback;
2358
[email protected]5a1d7ca2010-04-28 20:12:272359 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422360 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522361
2362 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422363 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522364
[email protected]1c773ea12009-04-28 19:58:422365 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522366 EXPECT_TRUE(response != NULL);
2367
2368 EXPECT_TRUE(response->headers != NULL);
2369 std::string status_line = response->headers->GetStatusLine();
2370 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2371
[email protected]a937a06d2009-08-19 21:19:242372 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522373
2374 std::string response_data;
2375 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422376 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522377 EXPECT_EQ("", response_data);
2378
2379 // Empty the current queue. This is necessary because idle sockets are
2380 // added to the connection pool asynchronously with a PostTask.
2381 MessageLoop::current()->RunAllPending();
2382
2383 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242384 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522385}
2386
[email protected]372d34a2008-11-05 21:30:512387TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422388 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512389 // Transaction 1: a GET request that succeeds. The socket is recycled
2390 // after use.
2391 request[0].method = "GET";
2392 request[0].url = GURL("http://www.google.com/");
2393 request[0].load_flags = 0;
2394 // Transaction 2: a POST request. Reuses the socket kept alive from
2395 // transaction 1. The first attempts fails when writing the POST data.
2396 // This causes the transaction to retry with a new socket. The second
2397 // attempt succeeds.
2398 request[1].method = "POST";
2399 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422400 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512401 request[1].upload_data->AppendBytes("foo", 3);
2402 request[1].load_flags = 0;
2403
[email protected]228ff742009-06-05 01:19:592404 SessionDependencies session_deps;
2405 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512406
2407 // The first socket is used for transaction 1 and the first attempt of
2408 // transaction 2.
2409
2410 // The response of transaction 1.
2411 MockRead data_reads1[] = {
2412 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2413 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422414 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512415 };
2416 // The mock write results of transaction 1 and the first attempt of
2417 // transaction 2.
2418 MockWrite data_writes1[] = {
2419 MockWrite(false, 64), // GET
2420 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422421 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512422 };
[email protected]31a2bfe2010-02-09 08:03:392423 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2424 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512425
2426 // The second socket is used for the second attempt of transaction 2.
2427
2428 // The response of transaction 2.
2429 MockRead data_reads2[] = {
2430 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2431 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422432 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512433 };
2434 // The mock write results of the second attempt of transaction 2.
2435 MockWrite data_writes2[] = {
2436 MockWrite(false, 93), // POST
2437 MockWrite(false, 3), // POST data
2438 };
[email protected]31a2bfe2010-02-09 08:03:392439 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2440 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512441
[email protected]5ecc992a42009-11-11 01:41:592442 session_deps.socket_factory.AddSocketDataProvider(&data1);
2443 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512444
2445 const char* kExpectedResponseData[] = {
2446 "hello world", "welcome"
2447 };
2448
2449 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422450 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432451 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512452
2453 TestCompletionCallback callback;
2454
[email protected]5a1d7ca2010-04-28 20:12:272455 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422456 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512457
2458 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422459 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512460
[email protected]1c773ea12009-04-28 19:58:422461 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512462 EXPECT_TRUE(response != NULL);
2463
2464 EXPECT_TRUE(response->headers != NULL);
2465 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2466
2467 std::string response_data;
2468 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422469 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512470 EXPECT_EQ(kExpectedResponseData[i], response_data);
2471 }
2472}
[email protected]f9ee6b52008-11-08 06:46:232473
2474// Test the request-challenge-retry sequence for basic auth when there is
2475// an identity in the URL. The request should be sent as normal, but when
2476// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322477TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592478 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402479 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432480 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232481
[email protected]1c773ea12009-04-28 19:58:422482 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232483 request.method = "GET";
2484 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292485 request.url = GURL("http://foo:b@[email protected]/");
2486
2487 // The password contains an escaped character -- for this test to pass it
2488 // will need to be unescaped by HttpNetworkTransaction.
2489 EXPECT_EQ("b%40r", request.url.password());
2490
[email protected]ea9dc9a2009-09-05 00:43:322491 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232492
2493 MockWrite data_writes1[] = {
2494 MockWrite("GET / HTTP/1.1\r\n"
2495 "Host: www.google.com\r\n"
2496 "Connection: keep-alive\r\n\r\n"),
2497 };
2498
2499 MockRead data_reads1[] = {
2500 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2501 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2502 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422503 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232504 };
2505
2506 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322507 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232508 MockWrite data_writes2[] = {
2509 MockWrite("GET / HTTP/1.1\r\n"
2510 "Host: www.google.com\r\n"
2511 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292512 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232513 };
2514
2515 MockRead data_reads2[] = {
2516 MockRead("HTTP/1.0 200 OK\r\n"),
2517 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422518 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232519 };
2520
[email protected]31a2bfe2010-02-09 08:03:392521 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2522 data_writes1, arraysize(data_writes1));
2523 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2524 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592525 session_deps.socket_factory.AddSocketDataProvider(&data1);
2526 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232527
2528 TestCompletionCallback callback1;
2529
[email protected]5a1d7ca2010-04-28 20:12:272530 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422531 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232532
2533 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422534 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232535
[email protected]0757e7702009-03-27 04:00:222536 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2537 TestCompletionCallback callback2;
2538 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422539 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222540 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422541 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222542 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2543
[email protected]1c773ea12009-04-28 19:58:422544 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232545 EXPECT_FALSE(response == NULL);
2546
2547 // There is no challenge info, since the identity in URL worked.
2548 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2549
2550 EXPECT_EQ(100, response->headers->GetContentLength());
2551
2552 // Empty the current queue.
2553 MessageLoop::current()->RunAllPending();
2554}
2555
[email protected]ea9dc9a2009-09-05 00:43:322556// Test the request-challenge-retry sequence for basic auth when there is
2557// an incorrect identity in the URL. The identity from the URL should be used
2558// only once.
2559TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2560 SessionDependencies session_deps;
2561 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432562 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322563
2564 HttpRequestInfo request;
2565 request.method = "GET";
2566 // Note: the URL has a username:password in it. The password "baz" is
2567 // wrong (should be "bar").
2568 request.url = GURL("http://foo:[email protected]/");
2569
2570 request.load_flags = LOAD_NORMAL;
2571
2572 MockWrite data_writes1[] = {
2573 MockWrite("GET / HTTP/1.1\r\n"
2574 "Host: www.google.com\r\n"
2575 "Connection: keep-alive\r\n\r\n"),
2576 };
2577
2578 MockRead data_reads1[] = {
2579 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2580 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2581 MockRead("Content-Length: 10\r\n\r\n"),
2582 MockRead(false, ERR_FAILED),
2583 };
2584
2585 // After the challenge above, the transaction will be restarted using the
2586 // identity from the url (foo, baz) to answer the challenge.
2587 MockWrite data_writes2[] = {
2588 MockWrite("GET / HTTP/1.1\r\n"
2589 "Host: www.google.com\r\n"
2590 "Connection: keep-alive\r\n"
2591 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2592 };
2593
2594 MockRead data_reads2[] = {
2595 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2596 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2597 MockRead("Content-Length: 10\r\n\r\n"),
2598 MockRead(false, ERR_FAILED),
2599 };
2600
2601 // After the challenge above, the transaction will be restarted using the
2602 // identity supplied by the user (foo, bar) to answer the challenge.
2603 MockWrite data_writes3[] = {
2604 MockWrite("GET / HTTP/1.1\r\n"
2605 "Host: www.google.com\r\n"
2606 "Connection: keep-alive\r\n"
2607 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2608 };
2609
2610 MockRead data_reads3[] = {
2611 MockRead("HTTP/1.0 200 OK\r\n"),
2612 MockRead("Content-Length: 100\r\n\r\n"),
2613 MockRead(false, OK),
2614 };
2615
[email protected]31a2bfe2010-02-09 08:03:392616 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2617 data_writes1, arraysize(data_writes1));
2618 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2619 data_writes2, arraysize(data_writes2));
2620 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2621 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592622 session_deps.socket_factory.AddSocketDataProvider(&data1);
2623 session_deps.socket_factory.AddSocketDataProvider(&data2);
2624 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322625
2626 TestCompletionCallback callback1;
2627
[email protected]5a1d7ca2010-04-28 20:12:272628 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322629 EXPECT_EQ(ERR_IO_PENDING, rv);
2630
2631 rv = callback1.WaitForResult();
2632 EXPECT_EQ(OK, rv);
2633
2634 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2635 TestCompletionCallback callback2;
2636 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2637 EXPECT_EQ(ERR_IO_PENDING, rv);
2638 rv = callback2.WaitForResult();
2639 EXPECT_EQ(OK, rv);
2640 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2641
2642 const HttpResponseInfo* response = trans->GetResponseInfo();
2643 EXPECT_FALSE(response == NULL);
2644 // The password prompt info should have been set in response->auth_challenge.
2645 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2646
2647 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2648 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2649 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2650
2651 TestCompletionCallback callback3;
2652 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2653 EXPECT_EQ(ERR_IO_PENDING, rv);
2654 rv = callback3.WaitForResult();
2655 EXPECT_EQ(OK, rv);
2656 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2657
2658 response = trans->GetResponseInfo();
2659 EXPECT_FALSE(response == NULL);
2660
2661 // There is no challenge info, since the identity worked.
2662 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2663
2664 EXPECT_EQ(100, response->headers->GetContentLength());
2665
2666 // Empty the current queue.
2667 MessageLoop::current()->RunAllPending();
2668}
2669
[email protected]f9ee6b52008-11-08 06:46:232670// Test that previously tried username/passwords for a realm get re-used.
2671TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592672 SessionDependencies session_deps;
2673 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232674
2675 // Transaction 1: authenticate (foo, bar) on MyRealm1
2676 {
[email protected]5695b8c2009-09-30 21:36:432677 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232678
[email protected]1c773ea12009-04-28 19:58:422679 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232680 request.method = "GET";
2681 request.url = GURL("http://www.google.com/x/y/z");
2682 request.load_flags = 0;
2683
2684 MockWrite data_writes1[] = {
2685 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2686 "Host: www.google.com\r\n"
2687 "Connection: keep-alive\r\n\r\n"),
2688 };
2689
2690 MockRead data_reads1[] = {
2691 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2692 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2693 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422694 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232695 };
2696
2697 // Resend with authorization (username=foo, password=bar)
2698 MockWrite data_writes2[] = {
2699 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2700 "Host: www.google.com\r\n"
2701 "Connection: keep-alive\r\n"
2702 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2703 };
2704
2705 // Sever accepts the authorization.
2706 MockRead data_reads2[] = {
2707 MockRead("HTTP/1.0 200 OK\r\n"),
2708 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422709 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232710 };
2711
[email protected]31a2bfe2010-02-09 08:03:392712 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2713 data_writes1, arraysize(data_writes1));
2714 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2715 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592716 session_deps.socket_factory.AddSocketDataProvider(&data1);
2717 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232718
2719 TestCompletionCallback callback1;
2720
[email protected]5a1d7ca2010-04-28 20:12:272721 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422722 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232723
2724 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422725 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232726
[email protected]1c773ea12009-04-28 19:58:422727 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232728 EXPECT_FALSE(response == NULL);
2729
2730 // The password prompt info should have been set in
2731 // response->auth_challenge.
2732 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2733
[email protected]71e4573a2009-05-21 22:03:002734 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232735 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2736 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2737
2738 TestCompletionCallback callback2;
2739
2740 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422741 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232742
2743 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422744 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232745
2746 response = trans->GetResponseInfo();
2747 EXPECT_FALSE(response == NULL);
2748 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2749 EXPECT_EQ(100, response->headers->GetContentLength());
2750 }
2751
2752 // ------------------------------------------------------------------------
2753
2754 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2755 {
[email protected]5695b8c2009-09-30 21:36:432756 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232757
[email protected]1c773ea12009-04-28 19:58:422758 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232759 request.method = "GET";
2760 // Note that Transaction 1 was at /x/y/z, so this is in the same
2761 // protection space as MyRealm1.
2762 request.url = GURL("http://www.google.com/x/y/a/b");
2763 request.load_flags = 0;
2764
2765 MockWrite data_writes1[] = {
2766 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2767 "Host: www.google.com\r\n"
2768 "Connection: keep-alive\r\n"
2769 // Send preemptive authorization for MyRealm1
2770 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2771 };
2772
2773 // The server didn't like the preemptive authorization, and
2774 // challenges us for a different realm (MyRealm2).
2775 MockRead data_reads1[] = {
2776 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2777 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2778 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422779 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232780 };
2781
2782 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2783 MockWrite data_writes2[] = {
2784 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2785 "Host: www.google.com\r\n"
2786 "Connection: keep-alive\r\n"
2787 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2788 };
2789
2790 // Sever accepts the authorization.
2791 MockRead data_reads2[] = {
2792 MockRead("HTTP/1.0 200 OK\r\n"),
2793 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422794 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232795 };
2796
[email protected]31a2bfe2010-02-09 08:03:392797 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2798 data_writes1, arraysize(data_writes1));
2799 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2800 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592801 session_deps.socket_factory.AddSocketDataProvider(&data1);
2802 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232803
2804 TestCompletionCallback callback1;
2805
[email protected]5a1d7ca2010-04-28 20:12:272806 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422807 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232808
2809 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422810 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232811
[email protected]1c773ea12009-04-28 19:58:422812 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232813 EXPECT_FALSE(response == NULL);
2814
2815 // The password prompt info should have been set in
2816 // response->auth_challenge.
2817 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2818
[email protected]71e4573a2009-05-21 22:03:002819 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232820 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2821 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2822
2823 TestCompletionCallback callback2;
2824
2825 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232827
2828 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422829 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232830
2831 response = trans->GetResponseInfo();
2832 EXPECT_FALSE(response == NULL);
2833 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2834 EXPECT_EQ(100, response->headers->GetContentLength());
2835 }
2836
2837 // ------------------------------------------------------------------------
2838
2839 // Transaction 3: Resend a request in MyRealm's protection space --
2840 // succeed with preemptive authorization.
2841 {
[email protected]5695b8c2009-09-30 21:36:432842 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232843
[email protected]1c773ea12009-04-28 19:58:422844 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232845 request.method = "GET";
2846 request.url = GURL("http://www.google.com/x/y/z2");
2847 request.load_flags = 0;
2848
2849 MockWrite data_writes1[] = {
2850 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2851 "Host: www.google.com\r\n"
2852 "Connection: keep-alive\r\n"
2853 // The authorization for MyRealm1 gets sent preemptively
2854 // (since the url is in the same protection space)
2855 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2856 };
2857
2858 // Sever accepts the preemptive authorization
2859 MockRead data_reads1[] = {
2860 MockRead("HTTP/1.0 200 OK\r\n"),
2861 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422862 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232863 };
2864
[email protected]31a2bfe2010-02-09 08:03:392865 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2866 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592867 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232868
2869 TestCompletionCallback callback1;
2870
[email protected]5a1d7ca2010-04-28 20:12:272871 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422872 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232873
2874 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422875 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232876
[email protected]1c773ea12009-04-28 19:58:422877 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232878 EXPECT_FALSE(response == NULL);
2879
2880 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2881 EXPECT_EQ(100, response->headers->GetContentLength());
2882 }
2883
2884 // ------------------------------------------------------------------------
2885
2886 // Transaction 4: request another URL in MyRealm (however the
2887 // url is not known to belong to the protection space, so no pre-auth).
2888 {
[email protected]5695b8c2009-09-30 21:36:432889 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232890
[email protected]1c773ea12009-04-28 19:58:422891 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232892 request.method = "GET";
2893 request.url = GURL("http://www.google.com/x/1");
2894 request.load_flags = 0;
2895
2896 MockWrite data_writes1[] = {
2897 MockWrite("GET /x/1 HTTP/1.1\r\n"
2898 "Host: www.google.com\r\n"
2899 "Connection: keep-alive\r\n\r\n"),
2900 };
2901
2902 MockRead data_reads1[] = {
2903 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2904 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2905 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422906 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232907 };
2908
2909 // Resend with authorization from MyRealm's cache.
2910 MockWrite data_writes2[] = {
2911 MockWrite("GET /x/1 HTTP/1.1\r\n"
2912 "Host: www.google.com\r\n"
2913 "Connection: keep-alive\r\n"
2914 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2915 };
2916
2917 // Sever accepts the authorization.
2918 MockRead data_reads2[] = {
2919 MockRead("HTTP/1.0 200 OK\r\n"),
2920 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422921 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232922 };
2923
[email protected]31a2bfe2010-02-09 08:03:392924 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2925 data_writes1, arraysize(data_writes1));
2926 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2927 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592928 session_deps.socket_factory.AddSocketDataProvider(&data1);
2929 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232930
2931 TestCompletionCallback callback1;
2932
[email protected]5a1d7ca2010-04-28 20:12:272933 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422934 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232935
2936 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422937 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232938
[email protected]0757e7702009-03-27 04:00:222939 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2940 TestCompletionCallback callback2;
2941 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422942 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222943 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422944 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222945 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2946
[email protected]1c773ea12009-04-28 19:58:422947 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232948 EXPECT_FALSE(response == NULL);
2949 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2950 EXPECT_EQ(100, response->headers->GetContentLength());
2951 }
2952
2953 // ------------------------------------------------------------------------
2954
2955 // Transaction 5: request a URL in MyRealm, but the server rejects the
2956 // cached identity. Should invalidate and re-prompt.
2957 {
[email protected]5695b8c2009-09-30 21:36:432958 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232959
[email protected]1c773ea12009-04-28 19:58:422960 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232961 request.method = "GET";
2962 request.url = GURL("http://www.google.com/p/q/t");
2963 request.load_flags = 0;
2964
2965 MockWrite data_writes1[] = {
2966 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2967 "Host: www.google.com\r\n"
2968 "Connection: keep-alive\r\n\r\n"),
2969 };
2970
2971 MockRead data_reads1[] = {
2972 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2973 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2974 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422975 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232976 };
2977
2978 // Resend with authorization from cache for MyRealm.
2979 MockWrite data_writes2[] = {
2980 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2981 "Host: www.google.com\r\n"
2982 "Connection: keep-alive\r\n"
2983 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2984 };
2985
2986 // Sever rejects the authorization.
2987 MockRead data_reads2[] = {
2988 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2989 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2990 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422991 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232992 };
2993
2994 // At this point we should prompt for new credentials for MyRealm.
2995 // Restart with username=foo3, password=foo4.
2996 MockWrite data_writes3[] = {
2997 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2998 "Host: www.google.com\r\n"
2999 "Connection: keep-alive\r\n"
3000 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3001 };
3002
3003 // Sever accepts the authorization.
3004 MockRead data_reads3[] = {
3005 MockRead("HTTP/1.0 200 OK\r\n"),
3006 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423007 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233008 };
3009
[email protected]31a2bfe2010-02-09 08:03:393010 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3011 data_writes1, arraysize(data_writes1));
3012 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3013 data_writes2, arraysize(data_writes2));
3014 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3015 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593016 session_deps.socket_factory.AddSocketDataProvider(&data1);
3017 session_deps.socket_factory.AddSocketDataProvider(&data2);
3018 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233019
3020 TestCompletionCallback callback1;
3021
[email protected]5a1d7ca2010-04-28 20:12:273022 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423023 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233024
3025 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423026 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233027
[email protected]0757e7702009-03-27 04:00:223028 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3029 TestCompletionCallback callback2;
3030 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423031 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223032 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423033 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223034 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3035
[email protected]1c773ea12009-04-28 19:58:423036 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233037 EXPECT_FALSE(response == NULL);
3038
3039 // The password prompt info should have been set in
3040 // response->auth_challenge.
3041 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3042
[email protected]71e4573a2009-05-21 22:03:003043 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233044 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3045 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3046
[email protected]0757e7702009-03-27 04:00:223047 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233048
[email protected]0757e7702009-03-27 04:00:223049 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:423050 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233051
[email protected]0757e7702009-03-27 04:00:223052 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423053 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233054
3055 response = trans->GetResponseInfo();
3056 EXPECT_FALSE(response == NULL);
3057 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3058 EXPECT_EQ(100, response->headers->GetContentLength());
3059 }
3060}
[email protected]89ceba9a2009-03-21 03:46:063061
[email protected]3c32c5f2010-05-18 15:18:123062// Tests that nonce count increments when multiple auth attempts
3063// are started with the same nonce.
3064TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3065 SessionDependencies session_deps;
3066 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3067 HttpAuthHandlerDigest::SetFixedCnonce(true);
3068
3069 // Transaction 1: authenticate (foo, bar) on MyRealm1
3070 {
3071 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3072
3073 HttpRequestInfo request;
3074 request.method = "GET";
3075 request.url = GURL("http://www.google.com/x/y/z");
3076 request.load_flags = 0;
3077
3078 MockWrite data_writes1[] = {
3079 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3080 "Host: www.google.com\r\n"
3081 "Connection: keep-alive\r\n\r\n"),
3082 };
3083
3084 MockRead data_reads1[] = {
3085 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3086 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3087 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3088 MockRead(false, OK),
3089 };
3090
3091 // Resend with authorization (username=foo, password=bar)
3092 MockWrite data_writes2[] = {
3093 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3094 "Host: www.google.com\r\n"
3095 "Connection: keep-alive\r\n"
3096 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3097 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3098 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3099 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3100 };
3101
3102 // Sever accepts the authorization.
3103 MockRead data_reads2[] = {
3104 MockRead("HTTP/1.0 200 OK\r\n"),
3105 MockRead(false, OK),
3106 };
3107
3108 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3109 data_writes1, arraysize(data_writes1));
3110 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3111 data_writes2, arraysize(data_writes2));
3112 session_deps.socket_factory.AddSocketDataProvider(&data1);
3113 session_deps.socket_factory.AddSocketDataProvider(&data2);
3114
3115 TestCompletionCallback callback1;
3116
3117 int rv = trans->Start(&request, &callback1, BoundNetLog());
3118 EXPECT_EQ(ERR_IO_PENDING, rv);
3119
3120 rv = callback1.WaitForResult();
3121 EXPECT_EQ(OK, rv);
3122
3123 const HttpResponseInfo* response = trans->GetResponseInfo();
3124 ASSERT_FALSE(response == NULL);
3125
3126 // The password prompt info should have been set in
3127 // response->auth_challenge.
3128 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3129
3130 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3131 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3132 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3133
3134 TestCompletionCallback callback2;
3135
3136 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3137 EXPECT_EQ(ERR_IO_PENDING, rv);
3138
3139 rv = callback2.WaitForResult();
3140 EXPECT_EQ(OK, rv);
3141
3142 response = trans->GetResponseInfo();
3143 ASSERT_FALSE(response == NULL);
3144 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3145 }
3146
3147 // ------------------------------------------------------------------------
3148
3149 // Transaction 2: Request another resource in digestive's protection space.
3150 // This will preemptively add an Authorization header which should have an
3151 // "nc" value of 2 (as compared to 1 in the first use.
3152 {
3153 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3154
3155 HttpRequestInfo request;
3156 request.method = "GET";
3157 // Note that Transaction 1 was at /x/y/z, so this is in the same
3158 // protection space as digest.
3159 request.url = GURL("http://www.google.com/x/y/a/b");
3160 request.load_flags = 0;
3161
3162 MockWrite data_writes1[] = {
3163 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3164 "Host: www.google.com\r\n"
3165 "Connection: keep-alive\r\n"
3166 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3167 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3168 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3169 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3170 };
3171
3172 // Sever accepts the authorization.
3173 MockRead data_reads1[] = {
3174 MockRead("HTTP/1.0 200 OK\r\n"),
3175 MockRead("Content-Length: 100\r\n\r\n"),
3176 MockRead(false, OK),
3177 };
3178
3179 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3180 data_writes1, arraysize(data_writes1));
3181 session_deps.socket_factory.AddSocketDataProvider(&data1);
3182
3183 TestCompletionCallback callback1;
3184
3185 int rv = trans->Start(&request, &callback1, BoundNetLog());
3186 EXPECT_EQ(ERR_IO_PENDING, rv);
3187
3188 rv = callback1.WaitForResult();
3189 EXPECT_EQ(OK, rv);
3190
3191 const HttpResponseInfo* response = trans->GetResponseInfo();
3192 ASSERT_FALSE(response == NULL);
3193 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3194 }
3195}
3196
[email protected]89ceba9a2009-03-21 03:46:063197// Test the ResetStateForRestart() private method.
3198TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3199 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593200 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403201 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433202 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063203
3204 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063205 trans->read_buf_ = new IOBuffer(15);
3206 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573207 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063208
3209 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143210 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573211 response->auth_challenge = new AuthChallengeInfo();
3212 response->ssl_info.cert_status = -15;
3213 response->response_time = base::Time::Now();
3214 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063215
3216 { // Setup state for response_.vary_data
3217 HttpRequestInfo request;
3218 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3219 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573220 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433221 request.extra_headers.SetHeader("Foo", "1");
3222 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573223 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063224 }
3225
3226 // Cause the above state to be reset.
3227 trans->ResetStateForRestart();
3228
3229 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073230 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063231 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573232 EXPECT_EQ(0U, trans->request_headers_.size());
3233 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3234 EXPECT_TRUE(response->headers.get() == NULL);
3235 EXPECT_EQ(false, response->was_cached);
3236 EXPECT_EQ(0, response->ssl_info.cert_status);
3237 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063238}
3239
[email protected]bacff652009-03-31 17:50:333240// Test HTTPS connections to a site with a bad certificate
3241TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593242 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403243 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433244 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333245
3246 HttpRequestInfo request;
3247 request.method = "GET";
3248 request.url = GURL("https://www.google.com/");
3249 request.load_flags = 0;
3250
3251 MockWrite data_writes[] = {
3252 MockWrite("GET / HTTP/1.1\r\n"
3253 "Host: www.google.com\r\n"
3254 "Connection: keep-alive\r\n\r\n"),
3255 };
3256
3257 MockRead data_reads[] = {
3258 MockRead("HTTP/1.0 200 OK\r\n"),
3259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3260 MockRead("Content-Length: 100\r\n\r\n"),
3261 MockRead(false, OK),
3262 };
3263
[email protected]5ecc992a42009-11-11 01:41:593264 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393265 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3266 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593267 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3268 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333269
[email protected]5ecc992a42009-11-11 01:41:593270 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3271 session_deps.socket_factory.AddSocketDataProvider(&data);
3272 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3273 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333274
3275 TestCompletionCallback callback;
3276
[email protected]5a1d7ca2010-04-28 20:12:273277 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333278 EXPECT_EQ(ERR_IO_PENDING, rv);
3279
3280 rv = callback.WaitForResult();
3281 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3282
3283 rv = trans->RestartIgnoringLastError(&callback);
3284 EXPECT_EQ(ERR_IO_PENDING, rv);
3285
3286 rv = callback.WaitForResult();
3287 EXPECT_EQ(OK, rv);
3288
3289 const HttpResponseInfo* response = trans->GetResponseInfo();
3290
3291 EXPECT_FALSE(response == NULL);
3292 EXPECT_EQ(100, response->headers->GetContentLength());
3293}
3294
3295// Test HTTPS connections to a site with a bad certificate, going through a
3296// proxy
3297TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593298 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333299
3300 HttpRequestInfo request;
3301 request.method = "GET";
3302 request.url = GURL("https://www.google.com/");
3303 request.load_flags = 0;
3304
3305 MockWrite proxy_writes[] = {
3306 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453307 "Host: www.google.com\r\n"
3308 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333309 };
3310
3311 MockRead proxy_reads[] = {
3312 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423313 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333314 };
3315
3316 MockWrite data_writes[] = {
3317 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453318 "Host: www.google.com\r\n"
3319 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333320 MockWrite("GET / HTTP/1.1\r\n"
3321 "Host: www.google.com\r\n"
3322 "Connection: keep-alive\r\n\r\n"),
3323 };
3324
3325 MockRead data_reads[] = {
3326 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3327 MockRead("HTTP/1.0 200 OK\r\n"),
3328 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3329 MockRead("Content-Length: 100\r\n\r\n"),
3330 MockRead(false, OK),
3331 };
3332
[email protected]31a2bfe2010-02-09 08:03:393333 StaticSocketDataProvider ssl_bad_certificate(
3334 proxy_reads, arraysize(proxy_reads),
3335 proxy_writes, arraysize(proxy_writes));
3336 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3337 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593338 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3339 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333340
[email protected]5ecc992a42009-11-11 01:41:593341 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3342 session_deps.socket_factory.AddSocketDataProvider(&data);
3343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3344 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333345
3346 TestCompletionCallback callback;
3347
3348 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593349 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333350
[email protected]d207a5f2009-06-04 05:28:403351 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433352 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333353
[email protected]5a1d7ca2010-04-28 20:12:273354 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333355 EXPECT_EQ(ERR_IO_PENDING, rv);
3356
3357 rv = callback.WaitForResult();
3358 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3359
3360 rv = trans->RestartIgnoringLastError(&callback);
3361 EXPECT_EQ(ERR_IO_PENDING, rv);
3362
3363 rv = callback.WaitForResult();
3364 EXPECT_EQ(OK, rv);
3365
3366 const HttpResponseInfo* response = trans->GetResponseInfo();
3367
3368 EXPECT_FALSE(response == NULL);
3369 EXPECT_EQ(100, response->headers->GetContentLength());
3370 }
3371}
3372
[email protected]1c773ea12009-04-28 19:58:423373TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593374 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403375 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433376 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423377
3378 HttpRequestInfo request;
3379 request.method = "GET";
3380 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433381 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3382 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423383
3384 MockWrite data_writes[] = {
3385 MockWrite("GET / HTTP/1.1\r\n"
3386 "Host: www.google.com\r\n"
3387 "Connection: keep-alive\r\n"
3388 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3389 };
3390
3391 // Lastly, the server responds with the actual content.
3392 MockRead data_reads[] = {
3393 MockRead("HTTP/1.0 200 OK\r\n"),
3394 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3395 MockRead("Content-Length: 100\r\n\r\n"),
3396 MockRead(false, OK),
3397 };
3398
[email protected]31a2bfe2010-02-09 08:03:393399 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3400 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593401 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423402
3403 TestCompletionCallback callback;
3404
[email protected]5a1d7ca2010-04-28 20:12:273405 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423406 EXPECT_EQ(ERR_IO_PENDING, rv);
3407
3408 rv = callback.WaitForResult();
3409 EXPECT_EQ(OK, rv);
3410}
3411
3412TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593413 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403414 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433415 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423416
3417 HttpRequestInfo request;
3418 request.method = "GET";
3419 request.url = GURL("http://www.google.com/");
3420 request.load_flags = 0;
3421 request.referrer = GURL("http://the.previous.site.com/");
3422
3423 MockWrite data_writes[] = {
3424 MockWrite("GET / HTTP/1.1\r\n"
3425 "Host: www.google.com\r\n"
3426 "Connection: keep-alive\r\n"
3427 "Referer: http://the.previous.site.com/\r\n\r\n"),
3428 };
3429
3430 // Lastly, the server responds with the actual content.
3431 MockRead data_reads[] = {
3432 MockRead("HTTP/1.0 200 OK\r\n"),
3433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3434 MockRead("Content-Length: 100\r\n\r\n"),
3435 MockRead(false, OK),
3436 };
3437
[email protected]31a2bfe2010-02-09 08:03:393438 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3439 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593440 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423441
3442 TestCompletionCallback callback;
3443
[email protected]5a1d7ca2010-04-28 20:12:273444 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423445 EXPECT_EQ(ERR_IO_PENDING, rv);
3446
3447 rv = callback.WaitForResult();
3448 EXPECT_EQ(OK, rv);
3449}
3450
3451TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593452 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403453 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433454 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423455
3456 HttpRequestInfo request;
3457 request.method = "POST";
3458 request.url = GURL("http://www.google.com/");
3459
3460 MockWrite data_writes[] = {
3461 MockWrite("POST / HTTP/1.1\r\n"
3462 "Host: www.google.com\r\n"
3463 "Connection: keep-alive\r\n"
3464 "Content-Length: 0\r\n\r\n"),
3465 };
3466
3467 // Lastly, the server responds with the actual content.
3468 MockRead data_reads[] = {
3469 MockRead("HTTP/1.0 200 OK\r\n"),
3470 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3471 MockRead("Content-Length: 100\r\n\r\n"),
3472 MockRead(false, OK),
3473 };
3474
[email protected]31a2bfe2010-02-09 08:03:393475 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3476 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593477 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423478
3479 TestCompletionCallback callback;
3480
[email protected]5a1d7ca2010-04-28 20:12:273481 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423482 EXPECT_EQ(ERR_IO_PENDING, rv);
3483
3484 rv = callback.WaitForResult();
3485 EXPECT_EQ(OK, rv);
3486}
3487
3488TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593489 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403490 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433491 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423492
3493 HttpRequestInfo request;
3494 request.method = "PUT";
3495 request.url = GURL("http://www.google.com/");
3496
3497 MockWrite data_writes[] = {
3498 MockWrite("PUT / HTTP/1.1\r\n"
3499 "Host: www.google.com\r\n"
3500 "Connection: keep-alive\r\n"
3501 "Content-Length: 0\r\n\r\n"),
3502 };
3503
3504 // Lastly, the server responds with the actual content.
3505 MockRead data_reads[] = {
3506 MockRead("HTTP/1.0 200 OK\r\n"),
3507 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3508 MockRead("Content-Length: 100\r\n\r\n"),
3509 MockRead(false, OK),
3510 };
3511
[email protected]31a2bfe2010-02-09 08:03:393512 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3513 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593514 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423515
3516 TestCompletionCallback callback;
3517
[email protected]5a1d7ca2010-04-28 20:12:273518 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423519 EXPECT_EQ(ERR_IO_PENDING, rv);
3520
3521 rv = callback.WaitForResult();
3522 EXPECT_EQ(OK, rv);
3523}
3524
3525TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593526 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403527 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433528 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423529
3530 HttpRequestInfo request;
3531 request.method = "HEAD";
3532 request.url = GURL("http://www.google.com/");
3533
3534 MockWrite data_writes[] = {
3535 MockWrite("HEAD / HTTP/1.1\r\n"
3536 "Host: www.google.com\r\n"
3537 "Connection: keep-alive\r\n"
3538 "Content-Length: 0\r\n\r\n"),
3539 };
3540
3541 // Lastly, the server responds with the actual content.
3542 MockRead data_reads[] = {
3543 MockRead("HTTP/1.0 200 OK\r\n"),
3544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3545 MockRead("Content-Length: 100\r\n\r\n"),
3546 MockRead(false, OK),
3547 };
3548
[email protected]31a2bfe2010-02-09 08:03:393549 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3550 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593551 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423552
3553 TestCompletionCallback callback;
3554
[email protected]5a1d7ca2010-04-28 20:12:273555 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423556 EXPECT_EQ(ERR_IO_PENDING, rv);
3557
3558 rv = callback.WaitForResult();
3559 EXPECT_EQ(OK, rv);
3560}
3561
3562TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593563 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403564 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433565 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423566
3567 HttpRequestInfo request;
3568 request.method = "GET";
3569 request.url = GURL("http://www.google.com/");
3570 request.load_flags = LOAD_BYPASS_CACHE;
3571
3572 MockWrite data_writes[] = {
3573 MockWrite("GET / HTTP/1.1\r\n"
3574 "Host: www.google.com\r\n"
3575 "Connection: keep-alive\r\n"
3576 "Pragma: no-cache\r\n"
3577 "Cache-Control: no-cache\r\n\r\n"),
3578 };
3579
3580 // Lastly, the server responds with the actual content.
3581 MockRead data_reads[] = {
3582 MockRead("HTTP/1.0 200 OK\r\n"),
3583 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3584 MockRead("Content-Length: 100\r\n\r\n"),
3585 MockRead(false, OK),
3586 };
3587
[email protected]31a2bfe2010-02-09 08:03:393588 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3589 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593590 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423591
3592 TestCompletionCallback callback;
3593
[email protected]5a1d7ca2010-04-28 20:12:273594 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423595 EXPECT_EQ(ERR_IO_PENDING, rv);
3596
3597 rv = callback.WaitForResult();
3598 EXPECT_EQ(OK, rv);
3599}
3600
3601TEST_F(HttpNetworkTransactionTest,
3602 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593603 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403604 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433605 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423606
3607 HttpRequestInfo request;
3608 request.method = "GET";
3609 request.url = GURL("http://www.google.com/");
3610 request.load_flags = LOAD_VALIDATE_CACHE;
3611
3612 MockWrite data_writes[] = {
3613 MockWrite("GET / HTTP/1.1\r\n"
3614 "Host: www.google.com\r\n"
3615 "Connection: keep-alive\r\n"
3616 "Cache-Control: max-age=0\r\n\r\n"),
3617 };
3618
3619 // Lastly, the server responds with the actual content.
3620 MockRead data_reads[] = {
3621 MockRead("HTTP/1.0 200 OK\r\n"),
3622 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3623 MockRead("Content-Length: 100\r\n\r\n"),
3624 MockRead(false, OK),
3625 };
3626
[email protected]31a2bfe2010-02-09 08:03:393627 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3628 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593629 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423630
3631 TestCompletionCallback callback;
3632
[email protected]5a1d7ca2010-04-28 20:12:273633 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423634 EXPECT_EQ(ERR_IO_PENDING, rv);
3635
3636 rv = callback.WaitForResult();
3637 EXPECT_EQ(OK, rv);
3638}
3639
3640TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593641 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403642 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433643 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423644
3645 HttpRequestInfo request;
3646 request.method = "GET";
3647 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433648 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423649
3650 MockWrite data_writes[] = {
3651 MockWrite("GET / HTTP/1.1\r\n"
3652 "Host: www.google.com\r\n"
3653 "Connection: keep-alive\r\n"
3654 "FooHeader: Bar\r\n\r\n"),
3655 };
3656
3657 // Lastly, the server responds with the actual content.
3658 MockRead data_reads[] = {
3659 MockRead("HTTP/1.0 200 OK\r\n"),
3660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3661 MockRead("Content-Length: 100\r\n\r\n"),
3662 MockRead(false, OK),
3663 };
3664
[email protected]31a2bfe2010-02-09 08:03:393665 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3666 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593667 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423668
3669 TestCompletionCallback callback;
3670
[email protected]5a1d7ca2010-04-28 20:12:273671 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423672 EXPECT_EQ(ERR_IO_PENDING, rv);
3673
3674 rv = callback.WaitForResult();
3675 EXPECT_EQ(OK, rv);
3676}
3677
[email protected]270c6412010-03-29 22:02:473678TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3679 SessionDependencies session_deps;
3680 scoped_ptr<HttpTransaction> trans(
3681 new HttpNetworkTransaction(CreateSession(&session_deps)));
3682
3683 HttpRequestInfo request;
3684 request.method = "GET";
3685 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433686 request.extra_headers.SetHeader("referer", "www.foo.com");
3687 request.extra_headers.SetHeader("hEllo", "Kitty");
3688 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473689
3690 MockWrite data_writes[] = {
3691 MockWrite("GET / HTTP/1.1\r\n"
3692 "Host: www.google.com\r\n"
3693 "Connection: keep-alive\r\n"
3694 "hEllo: Kitty\r\n"
3695 "FoO: bar\r\n\r\n"),
3696 };
3697
3698 // Lastly, the server responds with the actual content.
3699 MockRead data_reads[] = {
3700 MockRead("HTTP/1.0 200 OK\r\n"),
3701 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3702 MockRead("Content-Length: 100\r\n\r\n"),
3703 MockRead(false, OK),
3704 };
3705
3706 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3707 data_writes, arraysize(data_writes));
3708 session_deps.socket_factory.AddSocketDataProvider(&data);
3709
3710 TestCompletionCallback callback;
3711
[email protected]5a1d7ca2010-04-28 20:12:273712 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473713 EXPECT_EQ(ERR_IO_PENDING, rv);
3714
3715 rv = callback.WaitForResult();
3716 EXPECT_EQ(OK, rv);
3717}
3718
[email protected]3cd17242009-06-23 02:59:023719TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093720 SessionDependencies session_deps(
3721 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023722
3723 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433724 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023725
3726 HttpRequestInfo request;
3727 request.method = "GET";
3728 request.url = GURL("http://www.google.com/");
3729 request.load_flags = 0;
3730
3731 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3732 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3733
3734 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353735 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023736 MockWrite("GET / HTTP/1.1\r\n"
3737 "Host: www.google.com\r\n"
3738 "Connection: keep-alive\r\n\r\n")
3739 };
3740
3741 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593742 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023743 MockRead("HTTP/1.0 200 OK\r\n"),
3744 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3745 MockRead("Payload"),
3746 MockRead(false, OK)
3747 };
3748
[email protected]31a2bfe2010-02-09 08:03:393749 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3750 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593751 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023752
3753 TestCompletionCallback callback;
3754
[email protected]5a1d7ca2010-04-28 20:12:273755 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023756 EXPECT_EQ(ERR_IO_PENDING, rv);
3757
3758 rv = callback.WaitForResult();
3759 EXPECT_EQ(OK, rv);
3760
3761 const HttpResponseInfo* response = trans->GetResponseInfo();
3762 EXPECT_FALSE(response == NULL);
3763
3764 std::string response_text;
3765 rv = ReadTransaction(trans.get(), &response_text);
3766 EXPECT_EQ(OK, rv);
3767 EXPECT_EQ("Payload", response_text);
3768}
3769
3770TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093771 SessionDependencies session_deps(
3772 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023773
3774 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433775 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023776
3777 HttpRequestInfo request;
3778 request.method = "GET";
3779 request.url = GURL("https://www.google.com/");
3780 request.load_flags = 0;
3781
3782 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3783 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3784
3785 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353786 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3787 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023788 MockWrite("GET / HTTP/1.1\r\n"
3789 "Host: www.google.com\r\n"
3790 "Connection: keep-alive\r\n\r\n")
3791 };
3792
3793 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353794 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3795 arraysize(read_buffer)),
3796 MockRead("HTTP/1.0 200 OK\r\n"),
3797 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3798 MockRead("Payload"),
3799 MockRead(false, OK)
3800 };
3801
[email protected]31a2bfe2010-02-09 08:03:393802 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3803 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593804 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353805
[email protected]5ecc992a42009-11-11 01:41:593806 SSLSocketDataProvider ssl(true, OK);
3807 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353808
3809 TestCompletionCallback callback;
3810
[email protected]5a1d7ca2010-04-28 20:12:273811 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353812 EXPECT_EQ(ERR_IO_PENDING, rv);
3813
3814 rv = callback.WaitForResult();
3815 EXPECT_EQ(OK, rv);
3816
3817 const HttpResponseInfo* response = trans->GetResponseInfo();
3818 EXPECT_FALSE(response == NULL);
3819
3820 std::string response_text;
3821 rv = ReadTransaction(trans.get(), &response_text);
3822 EXPECT_EQ(OK, rv);
3823 EXPECT_EQ("Payload", response_text);
3824}
3825
3826TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093827 SessionDependencies session_deps(
3828 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353829
3830 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433831 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353832
3833 HttpRequestInfo request;
3834 request.method = "GET";
3835 request.url = GURL("http://www.google.com/");
3836 request.load_flags = 0;
3837
3838 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3839 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373840 const char kSOCKS5OkRequest[] = {
3841 0x05, // Version
3842 0x01, // Command (CONNECT)
3843 0x00, // Reserved.
3844 0x03, // Address type (DOMAINNAME).
3845 0x0E, // Length of domain (14)
3846 // Domain string:
3847 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3848 0x00, 0x50, // 16-bit port (80)
3849 };
[email protected]e0c27be2009-07-15 13:09:353850 const char kSOCKS5OkResponse[] =
3851 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3852
3853 MockWrite data_writes[] = {
3854 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3855 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3856 MockWrite("GET / HTTP/1.1\r\n"
3857 "Host: www.google.com\r\n"
3858 "Connection: keep-alive\r\n\r\n")
3859 };
3860
3861 MockRead data_reads[] = {
3862 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3863 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3864 MockRead("HTTP/1.0 200 OK\r\n"),
3865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3866 MockRead("Payload"),
3867 MockRead(false, OK)
3868 };
3869
[email protected]31a2bfe2010-02-09 08:03:393870 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3871 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593872 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353873
3874 TestCompletionCallback callback;
3875
[email protected]5a1d7ca2010-04-28 20:12:273876 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353877 EXPECT_EQ(ERR_IO_PENDING, rv);
3878
3879 rv = callback.WaitForResult();
3880 EXPECT_EQ(OK, rv);
3881
3882 const HttpResponseInfo* response = trans->GetResponseInfo();
3883 EXPECT_FALSE(response == NULL);
3884
3885 std::string response_text;
3886 rv = ReadTransaction(trans.get(), &response_text);
3887 EXPECT_EQ(OK, rv);
3888 EXPECT_EQ("Payload", response_text);
3889}
3890
3891TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093892 SessionDependencies session_deps(
3893 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353894
3895 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433896 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353897
3898 HttpRequestInfo request;
3899 request.method = "GET";
3900 request.url = GURL("https://www.google.com/");
3901 request.load_flags = 0;
3902
3903 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3904 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373905 const unsigned char kSOCKS5OkRequest[] = {
3906 0x05, // Version
3907 0x01, // Command (CONNECT)
3908 0x00, // Reserved.
3909 0x03, // Address type (DOMAINNAME).
3910 0x0E, // Length of domain (14)
3911 // Domain string:
3912 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3913 0x01, 0xBB, // 16-bit port (443)
3914 };
3915
[email protected]e0c27be2009-07-15 13:09:353916 const char kSOCKS5OkResponse[] =
3917 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3918
3919 MockWrite data_writes[] = {
3920 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3921 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3922 arraysize(kSOCKS5OkRequest)),
3923 MockWrite("GET / HTTP/1.1\r\n"
3924 "Host: www.google.com\r\n"
3925 "Connection: keep-alive\r\n\r\n")
3926 };
3927
3928 MockRead data_reads[] = {
3929 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3930 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023931 MockRead("HTTP/1.0 200 OK\r\n"),
3932 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3933 MockRead("Payload"),
3934 MockRead(false, OK)
3935 };
3936
[email protected]31a2bfe2010-02-09 08:03:393937 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3938 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593939 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023940
[email protected]5ecc992a42009-11-11 01:41:593941 SSLSocketDataProvider ssl(true, OK);
3942 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023943
3944 TestCompletionCallback callback;
3945
[email protected]5a1d7ca2010-04-28 20:12:273946 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023947 EXPECT_EQ(ERR_IO_PENDING, rv);
3948
3949 rv = callback.WaitForResult();
3950 EXPECT_EQ(OK, rv);
3951
3952 const HttpResponseInfo* response = trans->GetResponseInfo();
3953 EXPECT_FALSE(response == NULL);
3954
3955 std::string response_text;
3956 rv = ReadTransaction(trans.get(), &response_text);
3957 EXPECT_EQ(OK, rv);
3958 EXPECT_EQ("Payload", response_text);
3959}
3960
[email protected]04e5be32009-06-26 20:00:313961// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063962
3963struct GroupNameTest {
3964 std::string proxy_server;
3965 std::string url;
3966 std::string expected_group_name;
3967};
3968
3969scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3970 const std::string& proxy_server) {
3971 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3972 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3973
3974 HttpAlternateProtocols* alternate_protocols =
3975 session->mutable_alternate_protocols();
3976 alternate_protocols->SetAlternateProtocolFor(
3977 HostPortPair("host.with.alternate", 80), 443,
3978 HttpAlternateProtocols::NPN_SPDY_1);
3979
3980 return session;
3981}
3982
3983int GroupNameTransactionHelper(
3984 const std::string& url,
3985 const scoped_refptr<HttpNetworkSession>& session) {
3986 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3987
3988 HttpRequestInfo request;
3989 request.method = "GET";
3990 request.url = GURL(url);
3991 request.load_flags = 0;
3992
3993 TestCompletionCallback callback;
3994
3995 // We do not complete this request, the dtor will clean the transaction up.
3996 return trans->Start(&request, &callback, BoundNetLog());
3997}
3998
3999TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4000 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314001 {
[email protected]2d731a32010-04-29 01:04:064002 "", // unused
[email protected]04e5be32009-06-26 20:00:314003 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544004 "www.google.com:80",
4005 },
4006 {
[email protected]2d731a32010-04-29 01:04:064007 "", // unused
[email protected]2ff8b312010-04-26 22:20:544008 "http://[2001:1418:13:1::25]/direct",
4009 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:314010 },
[email protected]04e5be32009-06-26 20:00:314011
4012 // SSL Tests
4013 {
[email protected]2d731a32010-04-29 01:04:064014 "", // unused
[email protected]04e5be32009-06-26 20:00:314015 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024016 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:314017 },
4018 {
[email protected]2d731a32010-04-29 01:04:064019 "", // unused
4020 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024021 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:314022 },
4023 {
[email protected]2d731a32010-04-29 01:04:064024 "", // unused
[email protected]2ff8b312010-04-26 22:20:544025 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024026 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:544027 },
[email protected]2d731a32010-04-29 01:04:064028 };
[email protected]2ff8b312010-04-26 22:20:544029
[email protected]2d731a32010-04-29 01:04:064030 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4031
4032 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4033 scoped_refptr<HttpNetworkSession> session(
4034 SetupSessionForGroupNameTests(tests[i].proxy_server));
4035
4036 HttpNetworkSessionPeer peer(session);
4037 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4038 new CaptureGroupNameTCPSocketPool(session.get()));
4039 peer.SetTCPSocketPool(tcp_conn_pool);
4040
4041 EXPECT_EQ(ERR_IO_PENDING,
4042 GroupNameTransactionHelper(tests[i].url, session));
4043 EXPECT_EQ(tests[i].expected_group_name,
4044 tcp_conn_pool->last_group_name_received());
4045 }
4046
4047 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4048}
4049
4050TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4051 const GroupNameTest tests[] = {
4052 {
4053 "http_proxy",
4054 "http://www.google.com/http_proxy_normal",
4055 "www.google.com:80",
4056 },
4057
4058 // SSL Tests
4059 {
4060 "http_proxy",
4061 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024062 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064063 },
4064
[email protected]9faeded92010-04-29 20:03:054065 {
4066 "http_proxy",
4067 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024068 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054069 },
[email protected]2d731a32010-04-29 01:04:064070 };
4071
4072 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4073
4074 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4075 scoped_refptr<HttpNetworkSession> session(
4076 SetupSessionForGroupNameTests(tests[i].proxy_server));
4077
4078 HttpNetworkSessionPeer peer(session);
4079
4080 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
4081 new CaptureGroupNameTCPSocketPool(session.get()));
4082 peer.SetSocketPoolForHTTPProxy(
4083 HostPortPair("http_proxy", 80), http_proxy_pool);
4084
4085 EXPECT_EQ(ERR_IO_PENDING,
4086 GroupNameTransactionHelper(tests[i].url, session));
4087 EXPECT_EQ(tests[i].expected_group_name,
4088 http_proxy_pool->last_group_name_received());
4089 }
4090
4091 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4092}
4093
4094TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4095 const GroupNameTest tests[] = {
4096 {
4097 "socks4://socks_proxy:1080",
4098 "http://www.google.com/socks4_direct",
4099 "socks4/www.google.com:80",
4100 },
4101 {
4102 "socks5://socks_proxy:1080",
4103 "http://www.google.com/socks5_direct",
4104 "socks5/www.google.com:80",
4105 },
4106
4107 // SSL Tests
4108 {
4109 "socks4://socks_proxy:1080",
4110 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024111 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064112 },
4113 {
4114 "socks5://socks_proxy:1080",
4115 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024116 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064117 },
4118
[email protected]9faeded92010-04-29 20:03:054119 {
4120 "socks4://socks_proxy:1080",
4121 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024122 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054123 },
[email protected]04e5be32009-06-26 20:00:314124 };
4125
[email protected]2ff8b312010-04-26 22:20:544126 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4127
[email protected]04e5be32009-06-26 20:00:314128 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064129 scoped_refptr<HttpNetworkSession> session(
4130 SetupSessionForGroupNameTests(tests[i].proxy_server));
4131 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314132
[email protected]a796bcec2010-03-22 17:17:264133 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064134 new CaptureGroupNameSOCKSSocketPool(session.get()));
4135 peer.SetSocketPoolForSOCKSProxy(
4136 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:314137
[email protected]5695b8c2009-09-30 21:36:434138 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314139
[email protected]2d731a32010-04-29 01:04:064140 EXPECT_EQ(ERR_IO_PENDING,
4141 GroupNameTransactionHelper(tests[i].url, session));
4142 EXPECT_EQ(tests[i].expected_group_name,
4143 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314144 }
[email protected]2ff8b312010-04-26 22:20:544145
4146 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314147}
4148
[email protected]9172a982009-06-06 00:30:254149TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544150 SessionDependencies session_deps(
4151 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324152
[email protected]69719062010-01-05 20:09:214153 // This simulates failure resolving all hostnames; that means we will fail
4154 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324155 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4156
[email protected]9172a982009-06-06 00:30:254157 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434158 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254159
4160 HttpRequestInfo request;
4161 request.method = "GET";
4162 request.url = GURL("http://www.google.com/");
4163
4164 TestCompletionCallback callback;
4165
[email protected]5a1d7ca2010-04-28 20:12:274166 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254167 EXPECT_EQ(ERR_IO_PENDING, rv);
4168
[email protected]9172a982009-06-06 00:30:254169 rv = callback.WaitForResult();
4170 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4171}
4172
[email protected]f3e6c1e2009-06-15 20:52:124173// Host resolution observer used by
4174// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4175// resovle requests are issued with a referrer of |expected_referrer|.
4176class ResolutionReferrerObserver : public HostResolver::Observer {
4177 public:
4178 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4179 : expected_referrer_(expected_referrer),
4180 called_start_with_referrer_(false),
4181 called_finish_with_referrer_(false) {
4182 }
4183
4184 virtual void OnStartResolution(int id,
4185 const HostResolver::RequestInfo& info) {
4186 if (info.referrer() == expected_referrer_)
4187 called_start_with_referrer_ = true;
4188 }
4189
4190 virtual void OnFinishResolutionWithStatus(
4191 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4192 if (info.referrer() == expected_referrer_)
4193 called_finish_with_referrer_ = true;
4194 }
4195
[email protected]eb255d32009-06-17 02:11:034196 virtual void OnCancelResolution(int id,
4197 const HostResolver::RequestInfo& info ) {
4198 FAIL() << "Should not be cancelling any requests!";
4199 }
4200
[email protected]f3e6c1e2009-06-15 20:52:124201 bool did_complete_with_expected_referrer() const {
4202 return called_start_with_referrer_ && called_finish_with_referrer_;
4203 }
4204
4205 private:
4206 GURL expected_referrer_;
4207 bool called_start_with_referrer_;
4208 bool called_finish_with_referrer_;
4209
4210 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4211};
4212
4213// Make sure that when HostResolver::Resolve() is invoked, it passes through
4214// the "referrer". This is depended on by the DNS prefetch observer.
4215TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4216 GURL referrer = GURL("http://expected-referrer/");
4217 EXPECT_TRUE(referrer.is_valid());
4218 ResolutionReferrerObserver resolution_observer(referrer);
4219
4220 SessionDependencies session_deps;
4221 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434222 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124223
4224 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144225 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124226
4227 // Connect up a mock socket which will fail when reading.
4228 MockRead data_reads[] = {
4229 MockRead(false, ERR_FAILED),
4230 };
[email protected]31a2bfe2010-02-09 08:03:394231 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594232 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124233
4234 // Issue a request, containing an HTTP referrer.
4235 HttpRequestInfo request;
4236 request.method = "GET";
4237 request.referrer = referrer;
4238 request.url = GURL("http://www.google.com/");
4239
4240 // Run the request until it fails reading from the socket.
4241 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274242 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124243 EXPECT_EQ(ERR_IO_PENDING, rv);
4244 rv = callback.WaitForResult();
4245 EXPECT_EQ(ERR_FAILED, rv);
4246
4247 // Check that the host resolution observer saw |referrer|.
4248 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4249}
4250
[email protected]685af592010-05-11 19:31:244251// Base test to make sure that when the load flags for a request specify to
4252// bypass the cache, the DNS cache is not used.
4253void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284254 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324255
[email protected]a2c2fb92009-07-18 07:31:044256 // Select a host resolver that does caching.
4257 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324258
[email protected]3b9cca42009-06-16 01:08:284259 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434260 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284261
4262 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4263 // a synchronous lookup.)
4264 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144265 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464266 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274267 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284268 EXPECT_EQ(OK, rv);
4269
4270 // Verify that it was added to host cache, by doing a subsequent async lookup
4271 // and confirming it completes synchronously.
4272 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464273 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284274 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274275 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324276 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284277
4278 // Inject a failure the next time that "www.google.com" is resolved. This way
4279 // we can tell if the next lookup hit the cache, or the "network".
4280 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324281 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284282
4283 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4284 // first read -- this won't be reached as the host resolution will fail first.
4285 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394286 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594287 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284288
4289 // Issue a request, asking to bypass the cache(s).
4290 HttpRequestInfo request;
4291 request.method = "GET";
[email protected]685af592010-05-11 19:31:244292 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284293 request.url = GURL("http://www.google.com/");
4294
4295 // Run the request.
4296 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274297 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284298 ASSERT_EQ(ERR_IO_PENDING, rv);
4299 rv = callback.WaitForResult();
4300
4301 // If we bypassed the cache, we would have gotten a failure while resolving
4302 // "www.google.com".
4303 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4304}
4305
[email protected]685af592010-05-11 19:31:244306// There are multiple load flags that should trigger the host cache bypass.
4307// Test each in isolation:
4308TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4309 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4310}
4311
4312TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4313 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4314}
4315
4316TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4317 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4318}
4319
[email protected]0877e3d2009-10-17 22:29:574320// Make sure we can handle an error when writing the request.
4321TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4322 SessionDependencies session_deps;
4323 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4324
4325 HttpRequestInfo request;
4326 request.method = "GET";
4327 request.url = GURL("http://www.foo.com/");
4328 request.load_flags = 0;
4329
4330 MockWrite write_failure[] = {
4331 MockWrite(true, ERR_CONNECTION_RESET),
4332 };
[email protected]31a2bfe2010-02-09 08:03:394333 StaticSocketDataProvider data(NULL, 0,
4334 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594335 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574336
4337 TestCompletionCallback callback;
4338
4339 scoped_ptr<HttpTransaction> trans(
4340 new HttpNetworkTransaction(CreateSession(&session_deps)));
4341
[email protected]5a1d7ca2010-04-28 20:12:274342 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574343 EXPECT_EQ(ERR_IO_PENDING, rv);
4344
4345 rv = callback.WaitForResult();
4346 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4347}
4348
4349// Check that a connection closed after the start of the headers finishes ok.
4350TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4351 SessionDependencies session_deps;
4352 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4353
4354 HttpRequestInfo request;
4355 request.method = "GET";
4356 request.url = GURL("http://www.foo.com/");
4357 request.load_flags = 0;
4358
4359 MockRead data_reads[] = {
4360 MockRead("HTTP/1."),
4361 MockRead(false, OK),
4362 };
4363
[email protected]31a2bfe2010-02-09 08:03:394364 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594365 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574366
4367 TestCompletionCallback callback;
4368
4369 scoped_ptr<HttpTransaction> trans(
4370 new HttpNetworkTransaction(CreateSession(&session_deps)));
4371
[email protected]5a1d7ca2010-04-28 20:12:274372 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574373 EXPECT_EQ(ERR_IO_PENDING, rv);
4374
4375 rv = callback.WaitForResult();
4376 EXPECT_EQ(OK, rv);
4377
4378 const HttpResponseInfo* response = trans->GetResponseInfo();
4379 EXPECT_TRUE(response != NULL);
4380
4381 EXPECT_TRUE(response->headers != NULL);
4382 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4383
4384 std::string response_data;
4385 rv = ReadTransaction(trans.get(), &response_data);
4386 EXPECT_EQ(OK, rv);
4387 EXPECT_EQ("", response_data);
4388}
4389
4390// Make sure that a dropped connection while draining the body for auth
4391// restart does the right thing.
4392TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4393 SessionDependencies session_deps;
4394 scoped_ptr<HttpTransaction> trans(
4395 new HttpNetworkTransaction(CreateSession(&session_deps)));
4396
4397 HttpRequestInfo request;
4398 request.method = "GET";
4399 request.url = GURL("http://www.google.com/");
4400 request.load_flags = 0;
4401
4402 MockWrite data_writes1[] = {
4403 MockWrite("GET / HTTP/1.1\r\n"
4404 "Host: www.google.com\r\n"
4405 "Connection: keep-alive\r\n\r\n"),
4406 };
4407
4408 MockRead data_reads1[] = {
4409 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4410 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4412 MockRead("Content-Length: 14\r\n\r\n"),
4413 MockRead("Unauth"),
4414 MockRead(true, ERR_CONNECTION_RESET),
4415 };
4416
[email protected]31a2bfe2010-02-09 08:03:394417 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4418 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594419 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574420
4421 // After calling trans->RestartWithAuth(), this is the request we should
4422 // be issuing -- the final header line contains the credentials.
4423 MockWrite data_writes2[] = {
4424 MockWrite("GET / HTTP/1.1\r\n"
4425 "Host: www.google.com\r\n"
4426 "Connection: keep-alive\r\n"
4427 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4428 };
4429
4430 // Lastly, the server responds with the actual content.
4431 MockRead data_reads2[] = {
4432 MockRead("HTTP/1.1 200 OK\r\n"),
4433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4434 MockRead("Content-Length: 100\r\n\r\n"),
4435 MockRead(false, OK),
4436 };
4437
[email protected]31a2bfe2010-02-09 08:03:394438 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4439 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594440 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574441
4442 TestCompletionCallback callback1;
4443
[email protected]5a1d7ca2010-04-28 20:12:274444 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574445 EXPECT_EQ(ERR_IO_PENDING, rv);
4446
4447 rv = callback1.WaitForResult();
4448 EXPECT_EQ(OK, rv);
4449
4450 const HttpResponseInfo* response = trans->GetResponseInfo();
4451 EXPECT_FALSE(response == NULL);
4452
4453 // The password prompt info should have been set in response->auth_challenge.
4454 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4455
4456 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4457 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4458 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4459
4460 TestCompletionCallback callback2;
4461
4462 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4463 EXPECT_EQ(ERR_IO_PENDING, rv);
4464
4465 rv = callback2.WaitForResult();
4466 EXPECT_EQ(OK, rv);
4467
4468 response = trans->GetResponseInfo();
4469 EXPECT_FALSE(response == NULL);
4470 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4471 EXPECT_EQ(100, response->headers->GetContentLength());
4472}
4473
4474// Test HTTPS connections going through a proxy that sends extra data.
4475TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4476 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4477
4478 HttpRequestInfo request;
4479 request.method = "GET";
4480 request.url = GURL("https://www.google.com/");
4481 request.load_flags = 0;
4482
4483 MockRead proxy_reads[] = {
4484 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4485 MockRead(false, OK)
4486 };
4487
[email protected]31a2bfe2010-02-09 08:03:394488 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594489 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574490
[email protected]5ecc992a42009-11-11 01:41:594491 session_deps.socket_factory.AddSocketDataProvider(&data);
4492 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574493
4494 TestCompletionCallback callback;
4495
4496 session_deps.socket_factory.ResetNextMockIndexes();
4497
4498 scoped_ptr<HttpTransaction> trans(
4499 new HttpNetworkTransaction(CreateSession(&session_deps)));
4500
[email protected]5a1d7ca2010-04-28 20:12:274501 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574502 EXPECT_EQ(ERR_IO_PENDING, rv);
4503
4504 rv = callback.WaitForResult();
4505 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4506}
4507
[email protected]e22e1362009-11-23 21:31:124508TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464509 SessionDependencies session_deps;
4510 scoped_ptr<HttpTransaction> trans(
4511 new HttpNetworkTransaction(CreateSession(&session_deps)));
4512
4513 HttpRequestInfo request;
4514 request.method = "GET";
4515 request.url = GURL("http://www.google.com/");
4516 request.load_flags = 0;
4517
[email protected]e22e1362009-11-23 21:31:124518 MockRead data_reads[] = {
4519 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4520 MockRead(false, OK),
4521 };
[email protected]9492e4a2010-02-24 00:58:464522
4523 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4524 session_deps.socket_factory.AddSocketDataProvider(&data);
4525
4526 TestCompletionCallback callback;
4527
[email protected]5a1d7ca2010-04-28 20:12:274528 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464529 EXPECT_EQ(ERR_IO_PENDING, rv);
4530
4531 EXPECT_EQ(OK, callback.WaitForResult());
4532
4533 const HttpResponseInfo* response = trans->GetResponseInfo();
4534 EXPECT_TRUE(response != NULL);
4535
4536 EXPECT_TRUE(response->headers != NULL);
4537 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4538
4539 std::string response_data;
4540 rv = ReadTransaction(trans.get(), &response_data);
4541 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124542}
4543
[email protected]95d88ffe2010-02-04 21:25:334544TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4545 SessionDependencies session_deps;
4546 scoped_ptr<HttpTransaction> trans(
4547 new HttpNetworkTransaction(CreateSession(&session_deps)));
4548
4549 HttpRequestInfo request;
4550 request.method = "POST";
4551 request.url = GURL("http://www.google.com/upload");
4552 request.upload_data = new UploadData;
4553 request.load_flags = 0;
4554
4555 FilePath temp_file_path;
4556 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4557 const uint64 kFakeSize = 100000; // file is actually blank
4558
4559 std::vector<UploadData::Element> elements;
4560 UploadData::Element element;
4561 element.SetToFilePath(temp_file_path);
4562 element.SetContentLength(kFakeSize);
4563 elements.push_back(element);
4564 request.upload_data->set_elements(elements);
4565 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4566
4567 MockRead data_reads[] = {
4568 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4569 MockRead("hello world"),
4570 MockRead(false, OK),
4571 };
[email protected]31a2bfe2010-02-09 08:03:394572 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334573 session_deps.socket_factory.AddSocketDataProvider(&data);
4574
4575 TestCompletionCallback callback;
4576
[email protected]5a1d7ca2010-04-28 20:12:274577 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334578 EXPECT_EQ(ERR_IO_PENDING, rv);
4579
4580 rv = callback.WaitForResult();
4581 EXPECT_EQ(OK, rv);
4582
4583 const HttpResponseInfo* response = trans->GetResponseInfo();
4584 EXPECT_TRUE(response != NULL);
4585
4586 EXPECT_TRUE(response->headers != NULL);
4587 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4588
4589 std::string response_data;
4590 rv = ReadTransaction(trans.get(), &response_data);
4591 EXPECT_EQ(OK, rv);
4592 EXPECT_EQ("hello world", response_data);
4593
4594 file_util::Delete(temp_file_path, false);
4595}
4596
[email protected]6624b4622010-03-29 19:58:364597TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4598 // If we try to upload an unreadable file, the network stack should report
4599 // the file size as zero and upload zero bytes for that file.
4600 SessionDependencies session_deps;
4601 scoped_ptr<HttpTransaction> trans(
4602 new HttpNetworkTransaction(CreateSession(&session_deps)));
4603
4604 FilePath temp_file;
4605 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4606 std::string temp_file_content("Unreadable file.");
4607 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4608 temp_file_content.length()));
4609 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4610
4611 HttpRequestInfo request;
4612 request.method = "POST";
4613 request.url = GURL("http://www.google.com/upload");
4614 request.upload_data = new UploadData;
4615 request.load_flags = 0;
4616
4617 std::vector<UploadData::Element> elements;
4618 UploadData::Element element;
4619 element.SetToFilePath(temp_file);
4620 elements.push_back(element);
4621 request.upload_data->set_elements(elements);
4622
4623 MockRead data_reads[] = {
4624 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4625 MockRead(false, OK),
4626 };
4627 MockWrite data_writes[] = {
4628 MockWrite("POST /upload HTTP/1.1\r\n"
4629 "Host: www.google.com\r\n"
4630 "Connection: keep-alive\r\n"
4631 "Content-Length: 0\r\n\r\n"),
4632 MockWrite(false, OK),
4633 };
4634 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4635 arraysize(data_writes));
4636 session_deps.socket_factory.AddSocketDataProvider(&data);
4637
4638 TestCompletionCallback callback;
4639
[email protected]5a1d7ca2010-04-28 20:12:274640 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364641 EXPECT_EQ(ERR_IO_PENDING, rv);
4642
4643 rv = callback.WaitForResult();
4644 EXPECT_EQ(OK, rv);
4645
4646 const HttpResponseInfo* response = trans->GetResponseInfo();
4647 EXPECT_TRUE(response != NULL);
4648 EXPECT_TRUE(response->headers != NULL);
4649 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4650
4651 file_util::Delete(temp_file, false);
4652}
4653
4654TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4655 SessionDependencies session_deps;
4656 scoped_ptr<HttpTransaction> trans(
4657 new HttpNetworkTransaction(CreateSession(&session_deps)));
4658
4659 FilePath temp_file;
4660 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4661 std::string temp_file_contents("Unreadable file.");
4662 std::string unreadable_contents(temp_file_contents.length(), '\0');
4663 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4664 temp_file_contents.length()));
4665
4666 HttpRequestInfo request;
4667 request.method = "POST";
4668 request.url = GURL("http://www.google.com/upload");
4669 request.upload_data = new UploadData;
4670 request.load_flags = 0;
4671
4672 std::vector<UploadData::Element> elements;
4673 UploadData::Element element;
4674 element.SetToFilePath(temp_file);
4675 elements.push_back(element);
4676 request.upload_data->set_elements(elements);
4677
4678 MockRead data_reads[] = {
4679 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4680 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4681 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4682
4683 MockRead("HTTP/1.1 200 OK\r\n"),
4684 MockRead("Content-Length: 0\r\n\r\n"),
4685 MockRead(false, OK),
4686 };
4687 MockWrite data_writes[] = {
4688 MockWrite("POST /upload HTTP/1.1\r\n"
4689 "Host: www.google.com\r\n"
4690 "Connection: keep-alive\r\n"
4691 "Content-Length: 16\r\n\r\n"),
4692 MockWrite(false, temp_file_contents.c_str()),
4693
4694 MockWrite("POST /upload HTTP/1.1\r\n"
4695 "Host: www.google.com\r\n"
4696 "Connection: keep-alive\r\n"
4697 "Content-Length: 16\r\n"
4698 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4699 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4700 MockWrite(false, OK),
4701 };
4702 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4703 arraysize(data_writes));
4704 session_deps.socket_factory.AddSocketDataProvider(&data);
4705
4706 TestCompletionCallback callback1;
4707
[email protected]5a1d7ca2010-04-28 20:12:274708 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364709 EXPECT_EQ(ERR_IO_PENDING, rv);
4710
4711 rv = callback1.WaitForResult();
4712 EXPECT_EQ(OK, rv);
4713
4714 const HttpResponseInfo* response = trans->GetResponseInfo();
4715 EXPECT_TRUE(response != NULL);
4716 EXPECT_TRUE(response->headers != NULL);
4717 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4718
4719 // The password prompt info should have been set in response->auth_challenge.
4720 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4721 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4722 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4723 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4724
4725 // Now make the file unreadable and try again.
4726 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4727
4728 TestCompletionCallback callback2;
4729
4730 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4731 EXPECT_EQ(ERR_IO_PENDING, rv);
4732
4733 rv = callback2.WaitForResult();
4734 EXPECT_EQ(OK, rv);
4735
4736 response = trans->GetResponseInfo();
4737 EXPECT_TRUE(response != NULL);
4738 EXPECT_TRUE(response->headers != NULL);
4739 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4740 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4741
4742 file_util::Delete(temp_file, false);
4743}
4744
[email protected]aeefc9e82010-02-19 16:18:274745// Tests that changes to Auth realms are treated like auth rejections.
4746TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4747 SessionDependencies session_deps;
4748 scoped_ptr<HttpTransaction> trans(
4749 new HttpNetworkTransaction(CreateSession(&session_deps)));
4750
4751 HttpRequestInfo request;
4752 request.method = "GET";
4753 request.url = GURL("http://www.google.com/");
4754 request.load_flags = 0;
4755
4756 // First transaction will request a resource and receive a Basic challenge
4757 // with realm="first_realm".
4758 MockWrite data_writes1[] = {
4759 MockWrite("GET / HTTP/1.1\r\n"
4760 "Host: www.google.com\r\n"
4761 "Connection: keep-alive\r\n"
4762 "\r\n"),
4763 };
4764 MockRead data_reads1[] = {
4765 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4766 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4767 "\r\n"),
4768 };
4769
4770 // After calling trans->RestartWithAuth(), provide an Authentication header
4771 // for first_realm. The server will reject and provide a challenge with
4772 // second_realm.
4773 MockWrite data_writes2[] = {
4774 MockWrite("GET / HTTP/1.1\r\n"
4775 "Host: www.google.com\r\n"
4776 "Connection: keep-alive\r\n"
4777 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4778 "\r\n"),
4779 };
4780 MockRead data_reads2[] = {
4781 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4782 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4783 "\r\n"),
4784 };
4785
4786 // This again fails, and goes back to first_realm. Make sure that the
4787 // entry is removed from cache.
4788 MockWrite data_writes3[] = {
4789 MockWrite("GET / HTTP/1.1\r\n"
4790 "Host: www.google.com\r\n"
4791 "Connection: keep-alive\r\n"
4792 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4793 "\r\n"),
4794 };
4795 MockRead data_reads3[] = {
4796 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4797 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4798 "\r\n"),
4799 };
4800
4801 // Try one last time (with the correct password) and get the resource.
4802 MockWrite data_writes4[] = {
4803 MockWrite("GET / HTTP/1.1\r\n"
4804 "Host: www.google.com\r\n"
4805 "Connection: keep-alive\r\n"
4806 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4807 "\r\n"),
4808 };
4809 MockRead data_reads4[] = {
4810 MockRead("HTTP/1.1 200 OK\r\n"
4811 "Content-Type: text/html; charset=iso-8859-1\r\n"
4812 "Content-Length: 100\r\n"
4813 "\r\n"),
4814 };
4815
4816 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4817 data_writes1, arraysize(data_writes1));
4818 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4819 data_writes2, arraysize(data_writes2));
4820 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4821 data_writes3, arraysize(data_writes3));
4822 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4823 data_writes4, arraysize(data_writes4));
4824 session_deps.socket_factory.AddSocketDataProvider(&data1);
4825 session_deps.socket_factory.AddSocketDataProvider(&data2);
4826 session_deps.socket_factory.AddSocketDataProvider(&data3);
4827 session_deps.socket_factory.AddSocketDataProvider(&data4);
4828
4829 TestCompletionCallback callback1;
4830
4831 // Issue the first request with Authorize headers. There should be a
4832 // password prompt for first_realm waiting to be filled in after the
4833 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274834 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274835 EXPECT_EQ(ERR_IO_PENDING, rv);
4836 rv = callback1.WaitForResult();
4837 EXPECT_EQ(OK, rv);
4838 const HttpResponseInfo* response = trans->GetResponseInfo();
4839 ASSERT_FALSE(response == NULL);
4840 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4841 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4842 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4843 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4844
4845 // Issue the second request with an incorrect password. There should be a
4846 // password prompt for second_realm waiting to be filled in after the
4847 // transaction completes.
4848 TestCompletionCallback callback2;
4849 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4850 EXPECT_EQ(ERR_IO_PENDING, rv);
4851 rv = callback2.WaitForResult();
4852 EXPECT_EQ(OK, rv);
4853 response = trans->GetResponseInfo();
4854 ASSERT_FALSE(response == NULL);
4855 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4856 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4857 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4858 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4859
4860 // Issue the third request with another incorrect password. There should be
4861 // a password prompt for first_realm waiting to be filled in. If the password
4862 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4863 // first_realm was not correctly removed.
4864 TestCompletionCallback callback3;
4865 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4866 EXPECT_EQ(ERR_IO_PENDING, rv);
4867 rv = callback3.WaitForResult();
4868 EXPECT_EQ(OK, rv);
4869 response = trans->GetResponseInfo();
4870 ASSERT_FALSE(response == NULL);
4871 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4872 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4873 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4874 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4875
4876 // Issue the fourth request with the correct password and username.
4877 TestCompletionCallback callback4;
4878 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4879 EXPECT_EQ(ERR_IO_PENDING, rv);
4880 rv = callback4.WaitForResult();
4881 EXPECT_EQ(OK, rv);
4882 response = trans->GetResponseInfo();
4883 ASSERT_FALSE(response == NULL);
4884 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4885}
4886
[email protected]564b4912010-03-09 16:30:424887TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424888 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064889 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424890
[email protected]564b4912010-03-09 16:30:424891 SessionDependencies session_deps;
4892
4893 MockRead data_reads[] = {
4894 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064895 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424896 MockRead("hello world"),
4897 MockRead(false, OK),
4898 };
4899
4900 HttpRequestInfo request;
4901 request.method = "GET";
4902 request.url = GURL("http://www.google.com/");
4903 request.load_flags = 0;
4904
4905 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4906
4907 session_deps.socket_factory.AddSocketDataProvider(&data);
4908
4909 TestCompletionCallback callback;
4910
4911 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4912 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4913
[email protected]5a1d7ca2010-04-28 20:12:274914 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424915 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534916
[email protected]564b4912010-03-09 16:30:424917 HostPortPair http_host_port_pair;
4918 http_host_port_pair.host = "www.google.com";
4919 http_host_port_pair.port = 80;
4920 const HttpAlternateProtocols& alternate_protocols =
4921 session->alternate_protocols();
4922 EXPECT_FALSE(
4923 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4924
4925 EXPECT_EQ(OK, callback.WaitForResult());
4926
4927 const HttpResponseInfo* response = trans->GetResponseInfo();
4928 ASSERT_TRUE(response != NULL);
4929 ASSERT_TRUE(response->headers != NULL);
4930 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:534931 EXPECT_FALSE(response->was_fetched_via_spdy);
4932 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:574933 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:424934
4935 std::string response_data;
4936 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4937 EXPECT_EQ("hello world", response_data);
4938
4939 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4940 const HttpAlternateProtocols::PortProtocolPair alternate =
4941 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4942 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4943 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064944 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424945 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424946
[email protected]31e2c69e2010-04-15 18:06:064947 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424948 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424949}
4950
4951TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064952 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424953 SessionDependencies session_deps;
4954
4955 HttpRequestInfo request;
4956 request.method = "GET";
4957 request.url = GURL("http://www.google.com/");
4958 request.load_flags = 0;
4959
4960 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4961 StaticSocketDataProvider first_data;
4962 first_data.set_connect_data(mock_connect);
4963 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4964
4965 MockRead data_reads[] = {
4966 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4967 MockRead("hello world"),
4968 MockRead(true, OK),
4969 };
4970 StaticSocketDataProvider second_data(
4971 data_reads, arraysize(data_reads), NULL, 0);
4972 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4973
4974 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4975 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4976 // http://crbug.com/37454.
4977 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4978
4979 TestCompletionCallback callback;
4980
4981 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4982
4983 HostPortPair http_host_port_pair;
4984 http_host_port_pair.host = "www.google.com";
4985 http_host_port_pair.port = 80;
4986 HttpAlternateProtocols* alternate_protocols =
4987 session->mutable_alternate_protocols();
4988 alternate_protocols->SetAlternateProtocolFor(
4989 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064990 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424991
4992 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4993
[email protected]5a1d7ca2010-04-28 20:12:274994 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424995 EXPECT_EQ(ERR_IO_PENDING, rv);
4996 EXPECT_EQ(OK, callback.WaitForResult());
4997
4998 const HttpResponseInfo* response = trans->GetResponseInfo();
4999 ASSERT_TRUE(response != NULL);
5000 ASSERT_TRUE(response->headers != NULL);
5001 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5002
5003 std::string response_data;
5004 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5005 EXPECT_EQ("hello world", response_data);
5006
5007 ASSERT_TRUE(
5008 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5009 const HttpAlternateProtocols::PortProtocolPair alternate =
5010 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5011 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065012 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425013}
5014
5015// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5016// says that it does SPDY, but it just does the TLS handshake, but the NPN
5017// response does not indicate SPDY, so we just do standard HTTPS over the port.
5018// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5019// on the original port.
[email protected]a2cb8122010-03-10 17:22:425020// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5021// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535022//
[email protected]a2cb8122010-03-10 17:22:425023// HttpRequestInfo request;
5024// request.method = "GET";
5025// request.url = GURL("http://www.google.com/");
5026// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535027//
[email protected]a2cb8122010-03-10 17:22:425028// MockRead data_reads[] = {
5029// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5030// MockRead("hello world"),
5031// MockRead(true, OK),
5032// };
5033// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5034// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535035//
[email protected]a2cb8122010-03-10 17:22:425036// SSLSocketDataProvider ssl(true, OK);
5037// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535038//
[email protected]a2cb8122010-03-10 17:22:425039// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535040//
[email protected]a2cb8122010-03-10 17:22:425041// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535042//
[email protected]a2cb8122010-03-10 17:22:425043// HostPortPair http_host_port_pair;
5044// http_host_port_pair.host = "www.google.com";
5045// http_host_port_pair.port = 80;
5046// HttpAlternateProtocols* alternate_protocols =
5047// session->mutable_alternate_protocols();
5048// alternate_protocols->SetAlternateProtocolFor(
5049// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065050// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535051//
[email protected]a2cb8122010-03-10 17:22:425052// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535053//
[email protected]5a1d7ca2010-04-28 20:12:275054// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425055// EXPECT_EQ(ERR_IO_PENDING, rv);
5056// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535057//
[email protected]a2cb8122010-03-10 17:22:425058// const HttpResponseInfo* response = trans->GetResponseInfo();
5059// ASSERT_TRUE(response != NULL);
5060// ASSERT_TRUE(response->headers != NULL);
5061// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535062//
[email protected]a2cb8122010-03-10 17:22:425063// std::string response_data;
5064// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5065// EXPECT_EQ("hello world", response_data);
5066// }
5067
5068TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065069 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545070 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115071 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425072 SessionDependencies session_deps;
5073
5074 HttpRequestInfo request;
5075 request.method = "GET";
5076 request.url = GURL("http://www.google.com/");
5077 request.load_flags = 0;
5078
[email protected]a2cb8122010-03-10 17:22:425079 StaticSocketDataProvider first_tcp_connect;
5080 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5081
5082 SSLSocketDataProvider ssl(true, OK);
5083 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5084
[email protected]564b4912010-03-09 16:30:425085 MockRead data_reads[] = {
5086 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5087 MockRead("hello world"),
5088 MockRead(true, OK),
5089 };
[email protected]a2cb8122010-03-10 17:22:425090 StaticSocketDataProvider fallback_data(
5091 data_reads, arraysize(data_reads), NULL, 0);
5092 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425093
5094 TestCompletionCallback callback;
5095
5096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5097
5098 HostPortPair http_host_port_pair;
5099 http_host_port_pair.host = "www.google.com";
5100 http_host_port_pair.port = 80;
5101 HttpAlternateProtocols* alternate_protocols =
5102 session->mutable_alternate_protocols();
5103 alternate_protocols->SetAlternateProtocolFor(
5104 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065105 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425106
5107 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5108
[email protected]5a1d7ca2010-04-28 20:12:275109 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425110 EXPECT_EQ(ERR_IO_PENDING, rv);
5111 EXPECT_EQ(OK, callback.WaitForResult());
5112
5113 const HttpResponseInfo* response = trans->GetResponseInfo();
5114 ASSERT_TRUE(response != NULL);
5115 ASSERT_TRUE(response->headers != NULL);
5116 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5117
5118 std::string response_data;
5119 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5120 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545121 HttpNetworkTransaction::SetNextProtos("");
5122 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5123}
5124
5125TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5126 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5127 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115128 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545129 SessionDependencies session_deps;
5130
5131 HttpRequestInfo request;
5132 request.method = "GET";
5133 request.url = GURL("http://www.google.com/");
5134 request.load_flags = 0;
5135
5136 MockRead data_reads[] = {
5137 MockRead("HTTP/1.1 200 OK\r\n"),
5138 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5139 MockRead("hello world"),
5140 MockRead(true, OK),
5141 };
5142
5143 StaticSocketDataProvider first_transaction(
5144 data_reads, arraysize(data_reads), NULL, 0);
5145 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5146
5147 SSLSocketDataProvider ssl(true, OK);
5148 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5149 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535150 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545151 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5152
5153 MockWrite spdy_writes[] = {
5154 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5155 arraysize(kGetSyn)),
5156 };
5157
5158 MockRead spdy_reads[] = {
5159 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5160 arraysize(kGetSynReply)),
5161 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5162 arraysize(kGetBodyFrame)),
5163 MockRead(true, 0, 0),
5164 };
5165
5166 scoped_refptr<DelayedSocketData> spdy_data(
5167 new DelayedSocketData(
5168 1, // wait for one write to finish before reading.
5169 spdy_reads, arraysize(spdy_reads),
5170 spdy_writes, arraysize(spdy_writes)));
5171 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5172
5173 TestCompletionCallback callback;
5174
5175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5176 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5177
[email protected]5a1d7ca2010-04-28 20:12:275178 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545179 EXPECT_EQ(ERR_IO_PENDING, rv);
5180 EXPECT_EQ(OK, callback.WaitForResult());
5181
5182 const HttpResponseInfo* response = trans->GetResponseInfo();
5183 ASSERT_TRUE(response != NULL);
5184 ASSERT_TRUE(response->headers != NULL);
5185 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5186
5187 std::string response_data;
5188 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5189 EXPECT_EQ("hello world", response_data);
5190
5191 trans.reset(new HttpNetworkTransaction(session));
5192
[email protected]5a1d7ca2010-04-28 20:12:275193 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545194 EXPECT_EQ(ERR_IO_PENDING, rv);
5195 EXPECT_EQ(OK, callback.WaitForResult());
5196
5197 response = trans->GetResponseInfo();
5198 ASSERT_TRUE(response != NULL);
5199 ASSERT_TRUE(response->headers != NULL);
5200 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535201 EXPECT_TRUE(response->was_fetched_via_spdy);
5202 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575203 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545204
5205 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5206 EXPECT_EQ("hello!", response_data);
5207
5208 HttpNetworkTransaction::SetNextProtos("");
5209 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5210}
5211
[email protected]631f1322010-04-30 17:59:115212class CapturingProxyResolver : public ProxyResolver {
5213 public:
5214 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5215 virtual ~CapturingProxyResolver() {}
5216
5217 virtual int GetProxyForURL(const GURL& url,
5218 ProxyInfo* results,
5219 CompletionCallback* callback,
5220 RequestHandle* request,
5221 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425222 ProxyServer proxy_server(
5223 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5224 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115225 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425226 return OK;
[email protected]631f1322010-04-30 17:59:115227 }
5228
5229 virtual void CancelRequest(RequestHandle request) {
5230 NOTREACHED();
5231 }
5232
5233 const std::vector<GURL>& resolved() const { return resolved_; }
5234
5235 private:
5236 virtual int SetPacScript(const GURL& /*pac_url*/,
5237 const std::string& /*pac_bytes*/,
5238 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425239 return OK;
[email protected]631f1322010-04-30 17:59:115240 }
5241
5242 std::vector<GURL> resolved_;
5243
5244 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5245};
5246
[email protected]631f1322010-04-30 17:59:115247TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5248 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5249 HttpNetworkTransaction::SetNextProtos(
5250 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5251
5252 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425253 proxy_config.set_auto_detect(true);
5254 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115255
[email protected]631f1322010-04-30 17:59:115256 CapturingProxyResolver* capturing_proxy_resolver =
5257 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385258 SessionDependencies session_deps(new ProxyService(
5259 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5260 NULL));
[email protected]631f1322010-04-30 17:59:115261
5262 HttpRequestInfo request;
5263 request.method = "GET";
5264 request.url = GURL("http://www.google.com/");
5265 request.load_flags = 0;
5266
5267 MockRead data_reads[] = {
5268 MockRead("HTTP/1.1 200 OK\r\n"),
5269 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5270 MockRead("hello world"),
5271 MockRead(true, OK),
5272 };
5273
5274 StaticSocketDataProvider first_transaction(
5275 data_reads, arraysize(data_reads), NULL, 0);
5276 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5277
5278 SSLSocketDataProvider ssl(true, OK);
5279 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5280 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535281 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115282 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5283
5284 MockWrite spdy_writes[] = {
5285 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5286 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425287 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]631f1322010-04-30 17:59:115288 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
[email protected]d911f1b2010-05-05 22:39:425289 arraysize(kGetSyn)), // 3
[email protected]631f1322010-04-30 17:59:115290 };
5291
[email protected]d911f1b2010-05-05 22:39:425292 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5293
[email protected]631f1322010-04-30 17:59:115294 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425295 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
5296 MockRead(true, reinterpret_cast<const char*>(kGetSynReply), // 2, 4
5297 arraysize(kGetSynReply), 4),
5298 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame), // 5
5299 arraysize(kGetBodyFrame), 4),
5300 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115301 };
5302
[email protected]d911f1b2010-05-05 22:39:425303 scoped_refptr<OrderedSocketData> spdy_data(
5304 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115305 spdy_reads, arraysize(spdy_reads),
5306 spdy_writes, arraysize(spdy_writes)));
5307 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5308
5309 TestCompletionCallback callback;
5310
5311 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5312 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5313
5314 int rv = trans->Start(&request, &callback, BoundNetLog());
5315 EXPECT_EQ(ERR_IO_PENDING, rv);
5316 EXPECT_EQ(OK, callback.WaitForResult());
5317
5318 const HttpResponseInfo* response = trans->GetResponseInfo();
5319 ASSERT_TRUE(response != NULL);
5320 ASSERT_TRUE(response->headers != NULL);
5321 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535322 EXPECT_FALSE(response->was_fetched_via_spdy);
5323 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115324
5325 std::string response_data;
5326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5327 EXPECT_EQ("hello world", response_data);
5328
5329 trans.reset(new HttpNetworkTransaction(session));
5330
5331 rv = trans->Start(&request, &callback, BoundNetLog());
5332 EXPECT_EQ(ERR_IO_PENDING, rv);
5333 EXPECT_EQ(OK, callback.WaitForResult());
5334
5335 response = trans->GetResponseInfo();
5336 ASSERT_TRUE(response != NULL);
5337 ASSERT_TRUE(response->headers != NULL);
5338 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535339 EXPECT_TRUE(response->was_fetched_via_spdy);
5340 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115341
5342 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5343 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425344 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5345 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115346 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425347 EXPECT_EQ("https://www.google.com/",
5348 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115349
5350 HttpNetworkTransaction::SetNextProtos("");
5351 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5352}
[email protected]631f1322010-04-30 17:59:115353
[email protected]2ff8b312010-04-26 22:20:545354TEST_F(HttpNetworkTransactionTest,
5355 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5356 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5357 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115358 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545359 SessionDependencies session_deps;
5360
5361 HttpRequestInfo request;
5362 request.method = "GET";
5363 request.url = GURL("http://www.google.com/");
5364 request.load_flags = 0;
5365
5366 MockRead data_reads[] = {
5367 MockRead("HTTP/1.1 200 OK\r\n"),
5368 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5369 MockRead("hello world"),
5370 MockRead(true, OK),
5371 };
5372
5373 StaticSocketDataProvider first_transaction(
5374 data_reads, arraysize(data_reads), NULL, 0);
5375 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5376
5377 SSLSocketDataProvider ssl(true, OK);
5378 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5379 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535380 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545381 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535382 // Make sure we use ssl for spdy here.
5383 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545384
5385 MockWrite spdy_writes[] = {
5386 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5387 arraysize(kGetSyn)),
5388 };
5389
5390 MockRead spdy_reads[] = {
5391 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5392 arraysize(kGetSynReply)),
5393 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5394 arraysize(kGetBodyFrame)),
5395 MockRead(true, 0, 0),
5396 };
5397
5398 scoped_refptr<DelayedSocketData> spdy_data(
5399 new DelayedSocketData(
5400 1, // wait for one write to finish before reading.
5401 spdy_reads, arraysize(spdy_reads),
5402 spdy_writes, arraysize(spdy_writes)));
5403 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5404
5405 TestCompletionCallback callback;
5406
5407 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5408
5409 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5410
[email protected]5a1d7ca2010-04-28 20:12:275411 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545412 EXPECT_EQ(ERR_IO_PENDING, rv);
5413 EXPECT_EQ(OK, callback.WaitForResult());
5414
5415 const HttpResponseInfo* response = trans->GetResponseInfo();
5416 ASSERT_TRUE(response != NULL);
5417 ASSERT_TRUE(response->headers != NULL);
5418 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5419
5420 std::string response_data;
5421 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5422 EXPECT_EQ("hello world", response_data);
5423
5424 // Set up an initial SpdySession in the pool to reuse.
5425 scoped_refptr<SpdySession> spdy_session =
5426 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365427 session, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545428 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365429 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545430 trans.reset(new HttpNetworkTransaction(session));
5431
[email protected]5a1d7ca2010-04-28 20:12:275432 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545433 EXPECT_EQ(ERR_IO_PENDING, rv);
5434 EXPECT_EQ(OK, callback.WaitForResult());
5435
5436 response = trans->GetResponseInfo();
5437 ASSERT_TRUE(response != NULL);
5438 ASSERT_TRUE(response->headers != NULL);
5439 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535440 EXPECT_TRUE(response->was_fetched_via_spdy);
5441 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575442 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545443
5444 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5445 EXPECT_EQ("hello!", response_data);
5446
5447 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065448 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425449}
5450
[email protected]e5ae96a2010-04-14 20:12:455451// Tests that ResolveCanonicalName is handled correctly by the
5452// HttpNetworkTransaction.
5453TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5454 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:005455 HttpAuthHandlerMock::Factory* auth_factory(
5456 new HttpAuthHandlerMock::Factory());
[email protected]e5ae96a2010-04-14 20:12:455457 session_deps.http_auth_handler_factory.reset(auth_factory);
5458
5459 for (int i = 0; i < 2; ++i) {
[email protected]3fd9dae2010-06-21 11:39:005460 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]bcc528e2010-06-10 15:03:245461 std::string auth_challenge = "Mock";
5462 GURL origin("http://www.example.com");
5463 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5464 auth_challenge.end());
5465 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5466 origin, BoundNetLog());
[email protected]044de0642010-06-17 10:42:155467 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]36c8e5f72010-06-07 14:17:145468
[email protected]e5ae96a2010-04-14 20:12:455469 scoped_ptr<HttpTransaction> trans(
5470 new HttpNetworkTransaction(CreateSession(&session_deps)));
5471
5472 // Set up expectations for this pass of the test. Many of the EXPECT calls
[email protected]3fd9dae2010-06-21 11:39:005473 // are contained inside the HttpAuthHandlerMock codebase in response to
[email protected]e5ae96a2010-04-14 20:12:455474 // the expectations.
[email protected]3fd9dae2010-06-21 11:39:005475 HttpAuthHandlerMock::Resolve resolve = ((i == 0) ?
5476 HttpAuthHandlerMock::RESOLVE_SYNC :
5477 HttpAuthHandlerMock::RESOLVE_ASYNC);
[email protected]e5ae96a2010-04-14 20:12:455478 auth_handler->SetResolveExpectation(resolve);
5479 HttpRequestInfo request;
5480 request.method = "GET";
5481 request.url = GURL("http://myserver/");
5482 request.load_flags = 0;
5483
5484 MockWrite data_writes1[] = {
5485 MockWrite("GET / HTTP/1.1\r\n"
5486 "Host: myserver\r\n"
5487 "Connection: keep-alive\r\n\r\n"),
5488 };
5489
5490 MockRead data_reads1[] = {
5491 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5492 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5493 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5494 MockRead("Content-Length: 14\r\n\r\n"),
5495 MockRead("Unauthorized\r\n"),
5496 };
5497
5498 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5499 data_writes1, arraysize(data_writes1));
5500 session_deps.socket_factory.AddSocketDataProvider(&data1);
5501
5502 TestCompletionCallback callback1;
5503
[email protected]5a1d7ca2010-04-28 20:12:275504 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455505 EXPECT_EQ(ERR_IO_PENDING, rv);
5506
5507 rv = callback1.WaitForResult();
5508 EXPECT_EQ(OK, rv);
5509
5510 const HttpResponseInfo* response = trans->GetResponseInfo();
5511 EXPECT_FALSE(response == NULL);
5512
5513 // The password prompt is set after the canonical name is resolved.
5514 // If it isn't present or is incorrect, it indicates that the scheme
5515 // did not complete correctly.
5516 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5517
5518 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5519 EXPECT_EQ(L"", response->auth_challenge->realm);
5520 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
[email protected]044de0642010-06-17 10:42:155521 }
5522}
5523
5524// GenerateAuthToken is a mighty big test.
5525// It tests all permutation of GenerateAuthToken behavior:
5526// - Synchronous and Asynchronous completion.
5527// - OK or error on completion.
5528// - Direct connection, non-authenticating proxy, and authenticating proxy.
5529// - HTTP or HTTPS backend (to include proxy tunneling).
5530// - Non-authenticating and authenticating backend.
5531//
5532// In all, there are 44 reasonable permuations (for example, if there are
5533// problems generating an auth token for an authenticating proxy, we don't
5534// need to test all permutations of the backend server).
5535//
5536// The test proceeds by going over each of the configuration cases, and
5537// potentially running up to three rounds in each of the tests. The TestConfig
5538// specifies both the configuration for the test as well as the expectations
5539// for the results.
5540TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5541 const char* kServer = "http://www.example.com";
5542 const char* kSecureServer = "https://www.example.com";
5543 const char* kProxy = "myproxy:70";
5544 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5545
5546 enum AuthTiming {
5547 AUTH_NONE,
5548 AUTH_SYNC,
5549 AUTH_ASYNC,
5550 };
5551
5552 const MockWrite kGet(
5553 "GET / HTTP/1.1\r\n"
5554 "Host: www.example.com\r\n"
5555 "Connection: keep-alive\r\n\r\n");
5556 const MockWrite kGetProxy(
5557 "GET http://www.example.com/ HTTP/1.1\r\n"
5558 "Host: www.example.com\r\n"
5559 "Proxy-Connection: keep-alive\r\n\r\n");
5560 const MockWrite kGetAuth(
5561 "GET / HTTP/1.1\r\n"
5562 "Host: www.example.com\r\n"
5563 "Connection: keep-alive\r\n"
5564 "Authorization: auth_token\r\n\r\n");
5565 const MockWrite kGetProxyAuth(
5566 "GET http://www.example.com/ HTTP/1.1\r\n"
5567 "Host: www.example.com\r\n"
5568 "Proxy-Connection: keep-alive\r\n"
5569 "Proxy-Authorization: auth_token\r\n\r\n");
5570 const MockWrite kGetAuthThroughProxy(
5571 "GET http://www.example.com/ HTTP/1.1\r\n"
5572 "Host: www.example.com\r\n"
5573 "Proxy-Connection: keep-alive\r\n"
5574 "Authorization: auth_token\r\n\r\n");
5575 const MockWrite kGetAuthWithProxyAuth(
5576 "GET http://www.example.com/ HTTP/1.1\r\n"
5577 "Host: www.example.com\r\n"
5578 "Proxy-Connection: keep-alive\r\n"
5579 "Proxy-Authorization: auth_token\r\n"
5580 "Authorization: auth_token\r\n\r\n");
5581 const MockWrite kConnect(
5582 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5583 "Host: www.example.com\r\n"
5584 "Proxy-Connection: keep-alive\r\n\r\n");
5585 const MockWrite kConnectProxyAuth(
5586 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5587 "Host: www.example.com\r\n"
5588 "Proxy-Connection: keep-alive\r\n"
5589 "Proxy-Authorization: auth_token\r\n\r\n");
5590
5591 const MockRead kSuccess(
5592 "HTTP/1.1 200 OK\r\n"
5593 "Content-Type: text/html; charset=iso-8859-1\r\n"
5594 "Content-Length: 3\r\n\r\n"
5595 "Yes");
5596 const MockRead kFailure(
5597 "Should not be called.");
5598 const MockRead kServerChallenge(
5599 "HTTP/1.1 401 Unauthorized\r\n"
5600 "WWW-Authenticate: Mock realm=server\r\n"
5601 "Content-Type: text/html; charset=iso-8859-1\r\n"
5602 "Content-Length: 14\r\n\r\n"
5603 "Unauthorized\r\n");
5604 const MockRead kProxyChallenge(
5605 "HTTP/1.1 407 Unauthorized\r\n"
5606 "Proxy-Authenticate: Mock realm=proxy\r\n"
5607 "Proxy-Connection: close\r\n"
5608 "Content-Type: text/html; charset=iso-8859-1\r\n"
5609 "Content-Length: 14\r\n\r\n"
5610 "Unauthorized\r\n");
5611 const MockRead kProxyConnected(
5612 "HTTP/1.1 200 Connection Established\r\n\r\n");
5613
5614 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5615 // no constructors, but the C++ compiler on Windows warns about
5616 // unspecified data in compound literals. So, moved to using constructors,
5617 // and TestRound's created with the default constructor should not be used.
5618 struct TestRound {
5619 TestRound()
5620 : expected_rv(ERR_UNEXPECTED),
5621 extra_write(NULL),
5622 extra_read(NULL) {
5623 }
5624 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5625 int expected_rv_arg)
5626 : write(write_arg),
5627 read(read_arg),
5628 expected_rv(expected_rv_arg),
5629 extra_write(NULL),
5630 extra_read(NULL) {
5631 }
5632 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5633 int expected_rv_arg, const MockWrite* extra_write_arg,
5634 const MockWrite* extra_read_arg)
5635 : write(write_arg),
5636 read(read_arg),
5637 expected_rv(expected_rv_arg),
5638 extra_write(extra_write_arg),
5639 extra_read(extra_read_arg) {
5640 }
5641 MockWrite write;
5642 MockRead read;
5643 int expected_rv;
5644 const MockWrite* extra_write;
5645 const MockRead* extra_read;
5646 };
5647
5648 static const int kNoSSL = 500;
5649
5650 struct TestConfig {
5651 const char* proxy_url;
5652 AuthTiming proxy_auth_timing;
5653 int proxy_auth_rv;
5654 const char* server_url;
5655 AuthTiming server_auth_timing;
5656 int server_auth_rv;
5657 int num_auth_rounds;
5658 int first_ssl_round;
5659 TestRound rounds[3];
5660 } test_configs[] = {
5661 // Non-authenticating HTTP server with a direct connection.
5662 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5663 { TestRound(kGet, kSuccess, OK)}},
5664 // Authenticating HTTP server with a direct connection.
5665 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5666 { TestRound(kGet, kServerChallenge, OK),
5667 TestRound(kGetAuth, kSuccess, OK)}},
5668 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5669 { TestRound(kGet, kServerChallenge, OK),
5670 TestRound(kGetAuth, kFailure, kAuthErr)}},
5671 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5672 { TestRound(kGet, kServerChallenge, OK),
5673 TestRound(kGetAuth, kSuccess, OK)}},
5674 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5675 { TestRound(kGet, kServerChallenge, OK),
5676 TestRound(kGetAuth, kFailure, kAuthErr)}},
5677 // Non-authenticating HTTP server through a non-authenticating proxy.
5678 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5679 { TestRound(kGetProxy, kSuccess, OK)}},
5680 // Authenticating HTTP server through a non-authenticating proxy.
5681 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5682 { TestRound(kGetProxy, kServerChallenge, OK),
5683 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5684 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5685 { TestRound(kGetProxy, kServerChallenge, OK),
5686 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5687 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5688 { TestRound(kGetProxy, kServerChallenge, OK),
5689 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5690 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5691 { TestRound(kGetProxy, kServerChallenge, OK),
5692 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5693 // Non-authenticating HTTP server through an authenticating proxy.
5694 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5695 { TestRound(kGetProxy, kProxyChallenge, OK),
5696 TestRound(kGetProxyAuth, kSuccess, OK)}},
5697 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5698 { TestRound(kGetProxy, kProxyChallenge, OK),
5699 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5700 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5701 { TestRound(kGetProxy, kProxyChallenge, OK),
5702 TestRound(kGetProxyAuth, kSuccess, OK)}},
5703 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5704 { TestRound(kGetProxy, kProxyChallenge, OK),
5705 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5706 // Authenticating HTTP server through an authenticating proxy.
5707 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5708 { TestRound(kGetProxy, kProxyChallenge, OK),
5709 TestRound(kGetProxyAuth, kServerChallenge, OK),
5710 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5711 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5712 { TestRound(kGetProxy, kProxyChallenge, OK),
5713 TestRound(kGetProxyAuth, kServerChallenge, OK),
5714 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5715 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5716 { TestRound(kGetProxy, kProxyChallenge, OK),
5717 TestRound(kGetProxyAuth, kServerChallenge, OK),
5718 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5719 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5720 { TestRound(kGetProxy, kProxyChallenge, OK),
5721 TestRound(kGetProxyAuth, kServerChallenge, OK),
5722 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5723 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5724 { TestRound(kGetProxy, kProxyChallenge, OK),
5725 TestRound(kGetProxyAuth, kServerChallenge, OK),
5726 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5727 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5728 { TestRound(kGetProxy, kProxyChallenge, OK),
5729 TestRound(kGetProxyAuth, kServerChallenge, OK),
5730 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5731 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5732 { TestRound(kGetProxy, kProxyChallenge, OK),
5733 TestRound(kGetProxyAuth, kServerChallenge, OK),
5734 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5735 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5736 { TestRound(kGetProxy, kProxyChallenge, OK),
5737 TestRound(kGetProxyAuth, kServerChallenge, OK),
5738 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5739 // Non-authenticating HTTPS server with a direct connection.
5740 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5741 { TestRound(kGet, kSuccess, OK)}},
5742 // Authenticating HTTPS server with a direct connection.
5743 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5744 { TestRound(kGet, kServerChallenge, OK),
5745 TestRound(kGetAuth, kSuccess, OK)}},
5746 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5747 { TestRound(kGet, kServerChallenge, OK),
5748 TestRound(kGetAuth, kFailure, kAuthErr)}},
5749 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5750 { TestRound(kGet, kServerChallenge, OK),
5751 TestRound(kGetAuth, kSuccess, OK)}},
5752 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5753 { TestRound(kGet, kServerChallenge, OK),
5754 TestRound(kGetAuth, kFailure, kAuthErr)}},
5755 // Non-authenticating HTTPS server with a non-authenticating proxy.
5756 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5757 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5758 // Authenticating HTTPS server through a non-authenticating proxy.
5759 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5760 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5761 TestRound(kGetAuth, kSuccess, OK)}},
5762 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5763 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5764 TestRound(kGetAuth, kFailure, kAuthErr)}},
5765 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5766 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5767 TestRound(kGetAuth, kSuccess, OK)}},
5768 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5769 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5770 TestRound(kGetAuth, kFailure, kAuthErr)}},
5771 // Non-Authenticating HTTPS server through an authenticating proxy.
5772 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5773 { TestRound(kConnect, kProxyChallenge, OK),
5774 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5775 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5776 { TestRound(kConnect, kProxyChallenge, OK),
5777 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5778 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5779 { TestRound(kConnect, kProxyChallenge, OK),
5780 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5781 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5782 { TestRound(kConnect, kProxyChallenge, OK),
5783 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5784 // Authenticating HTTPS server through an authenticating proxy.
5785 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5786 { TestRound(kConnect, kProxyChallenge, OK),
5787 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5788 &kGet, &kServerChallenge),
5789 TestRound(kGetAuth, kSuccess, OK)}},
5790 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5791 { TestRound(kConnect, kProxyChallenge, OK),
5792 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5793 &kGet, &kServerChallenge),
5794 TestRound(kGetAuth, kFailure, kAuthErr)}},
5795 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5796 { TestRound(kConnect, kProxyChallenge, OK),
5797 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5798 &kGet, &kServerChallenge),
5799 TestRound(kGetAuth, kSuccess, OK)}},
5800 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5801 { TestRound(kConnect, kProxyChallenge, OK),
5802 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5803 &kGet, &kServerChallenge),
5804 TestRound(kGetAuth, kFailure, kAuthErr)}},
5805 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5806 { TestRound(kConnect, kProxyChallenge, OK),
5807 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5808 &kGet, &kServerChallenge),
5809 TestRound(kGetAuth, kSuccess, OK)}},
5810 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5811 { TestRound(kConnect, kProxyChallenge, OK),
5812 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5813 &kGet, &kServerChallenge),
5814 TestRound(kGetAuth, kFailure, kAuthErr)}},
5815 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5816 { TestRound(kConnect, kProxyChallenge, OK),
5817 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5818 &kGet, &kServerChallenge),
5819 TestRound(kGetAuth, kSuccess, OK)}},
5820 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5821 { TestRound(kConnect, kProxyChallenge, OK),
5822 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5823 &kGet, &kServerChallenge),
5824 TestRound(kGetAuth, kFailure, kAuthErr)}},
5825 };
5826
5827 SessionDependencies session_deps;
5828 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005829 HttpAuthHandlerMock::Factory* auth_factory(
5830 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155831 session_deps.http_auth_handler_factory.reset(auth_factory);
5832
5833 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5834 const TestConfig& test_config = test_configs[i];
5835 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005836 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155837 std::string auth_challenge = "Mock realm=proxy";
5838 GURL origin(test_config.proxy_url);
5839 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5840 auth_challenge.end());
5841 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5842 origin, BoundNetLog());
5843 auth_handler->SetGenerateExpectation(
5844 test_config.proxy_auth_timing == AUTH_ASYNC,
5845 test_config.proxy_auth_rv);
[email protected]3fd9dae2010-06-21 11:39:005846 auth_handler->SetResolveExpectation(HttpAuthHandlerMock::RESOLVE_SKIP);
[email protected]044de0642010-06-17 10:42:155847 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5848 }
5849 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005850 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155851 std::string auth_challenge = "Mock realm=server";
5852 GURL origin(test_config.server_url);
5853 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5854 auth_challenge.end());
5855 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5856 origin, BoundNetLog());
5857 auth_handler->SetGenerateExpectation(
5858 test_config.server_auth_timing == AUTH_ASYNC,
5859 test_config.server_auth_rv);
[email protected]3fd9dae2010-06-21 11:39:005860 auth_handler->SetResolveExpectation(HttpAuthHandlerMock::RESOLVE_SKIP);
[email protected]044de0642010-06-17 10:42:155861 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5862 }
5863 if (test_config.proxy_url) {
5864 session_deps.proxy_service =
5865 CreateFixedProxyService(test_config.proxy_url);
5866 } else {
5867 session_deps.proxy_service = ProxyService::CreateNull();
5868 }
5869
5870 HttpRequestInfo request;
5871 request.method = "GET";
5872 request.url = GURL(test_config.server_url);
5873 request.load_flags = 0;
5874
5875 scoped_ptr<HttpTransaction> trans(
5876 new HttpNetworkTransaction(CreateSession(&session_deps)));
5877
5878 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5879 const TestRound& read_write_round = test_config.rounds[round];
5880
5881 // Set up expected reads and writes.
5882 MockRead reads[2];
5883 reads[0] = read_write_round.read;
5884 size_t length_reads = 1;
5885 if (read_write_round.extra_read) {
5886 reads[1] = *read_write_round.extra_read;
5887 length_reads = 2;
5888 }
5889
5890 MockWrite writes[2];
5891 writes[0] = read_write_round.write;
5892 size_t length_writes = 1;
5893 if (read_write_round.extra_write) {
5894 writes[1] = *read_write_round.extra_write;
5895 length_writes = 2;
5896 }
5897 StaticSocketDataProvider data_provider(
5898 reads, length_reads, writes, length_writes);
5899 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
5900
5901 // Add an SSL sequence if necessary.
5902 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
5903 if (round >= test_config.first_ssl_round)
5904 session_deps.socket_factory.AddSSLSocketDataProvider(
5905 &ssl_socket_data_provider);
5906
5907 // Start or restart the transaction.
5908 TestCompletionCallback callback;
5909 int rv;
5910 if (round == 0) {
5911 rv = trans->Start(&request, &callback, BoundNetLog());
5912 } else {
5913 rv = trans->RestartWithAuth(L"foo", L"bar", &callback);
5914 }
5915 if (rv == ERR_IO_PENDING)
5916 rv = callback.WaitForResult();
5917
5918 // Compare results with expected data.
5919 EXPECT_EQ(read_write_round.expected_rv, rv);
5920 const HttpResponseInfo* response = trans->GetResponseInfo();
5921 if (read_write_round.expected_rv == OK) {
5922 EXPECT_FALSE(response == NULL);
5923 } else {
5924 EXPECT_TRUE(response == NULL);
5925 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
5926 continue;
5927 }
5928 if (round + 1 < test_config.num_auth_rounds) {
5929 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5930 } else {
5931 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5932 }
5933 }
[email protected]e5ae96a2010-04-14 20:12:455934 }
5935}
5936
[email protected]aeaca1f2010-04-20 22:05:215937class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5938 public:
[email protected]06650c52010-06-03 00:49:175939 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:215940 : fail_all_(fail_all) {
5941 }
5942
5943 virtual MockRead GetNextRead() {
5944 if (fail_all_)
5945 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5946
5947 return MockRead(false /* async */,
5948 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5949 }
5950
5951 virtual MockWriteResult OnWrite(const std::string& data) {
5952 return MockWriteResult(false /* async */, data.size());
5953 }
5954
5955 void Reset() {
5956 }
5957
5958 private:
5959 const bool fail_all_;
5960};
5961
5962// Test that we restart a connection when we see a decompression failure from
5963// the peer during the handshake. (In the real world we'll restart with SSLv3
5964// and we won't offer DEFLATE in that case.)
5965TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5966 HttpRequestInfo request;
5967 request.method = "GET";
5968 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5969 request.load_flags = 0;
5970
5971 SessionDependencies session_deps;
5972 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5973 false /* fail all reads */);
5974 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5975 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115976 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215977 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5978 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5979 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5980 session_deps.socket_factory.AddSSLSocketDataProvider(
5981 &ssl_socket_data_provider1);
5982 session_deps.socket_factory.AddSSLSocketDataProvider(
5983 &ssl_socket_data_provider2);
5984
5985 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5986 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5987 TestCompletionCallback callback;
5988
[email protected]5a1d7ca2010-04-28 20:12:275989 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215990 EXPECT_EQ(ERR_IO_PENDING, rv);
5991 EXPECT_EQ(OK, callback.WaitForResult());
5992
5993 const HttpResponseInfo* response = trans->GetResponseInfo();
5994 ASSERT_TRUE(response != NULL);
5995 ASSERT_TRUE(response->headers != NULL);
5996 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5997
5998 std::string response_data;
5999 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6000 EXPECT_EQ("ok.", response_data);
6001}
6002
6003// Test that we restart a connection if we get a decompression failure from the
6004// peer while reading the first bytes from the connection. This occurs when the
6005// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6006// in the handshake.
6007TEST_F(HttpNetworkTransactionTest,
6008 RestartAfterTLSDecompressionFailureWithFalseStart) {
6009 HttpRequestInfo request;
6010 request.method = "GET";
6011 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6012 request.load_flags = 0;
6013
6014 SessionDependencies session_deps;
6015 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6016 true /* fail all reads */);
6017 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6018 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6019 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6020 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6021 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6022 session_deps.socket_factory.AddSSLSocketDataProvider(
6023 &ssl_socket_data_provider1);
6024 session_deps.socket_factory.AddSSLSocketDataProvider(
6025 &ssl_socket_data_provider2);
6026
6027 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6028 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6029 TestCompletionCallback callback;
6030
[email protected]5a1d7ca2010-04-28 20:12:276031 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216032 EXPECT_EQ(ERR_IO_PENDING, rv);
6033 EXPECT_EQ(OK, callback.WaitForResult());
6034
6035 const HttpResponseInfo* response = trans->GetResponseInfo();
6036 ASSERT_TRUE(response != NULL);
6037 ASSERT_TRUE(response->headers != NULL);
6038 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6039
6040 std::string response_data;
6041 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6042 EXPECT_EQ("ok.", response_data);
6043}
6044
[email protected]65041fa2010-05-21 06:56:536045// This tests the case that a request is issued via http instead of spdy after
6046// npn is negotiated.
6047TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6048 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6049 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6050 SessionDependencies session_deps;
6051 HttpRequestInfo request;
6052 request.method = "GET";
6053 request.url = GURL("https://www.google.com/");
6054 request.load_flags = 0;
6055
6056 MockWrite data_writes[] = {
6057 MockWrite("GET / HTTP/1.1\r\n"
6058 "Host: www.google.com\r\n"
6059 "Connection: keep-alive\r\n\r\n"),
6060 };
6061
6062 MockRead data_reads[] = {
6063 MockRead("HTTP/1.1 200 OK\r\n"),
6064 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
6065 MockRead("hello world"),
6066 MockRead(false, OK),
6067 };
6068
6069 SSLSocketDataProvider ssl(true, OK);
6070 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6071 ssl.next_proto = "http/1.1";
6072
6073 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6074
6075 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6076 data_writes, arraysize(data_writes));
6077 session_deps.socket_factory.AddSocketDataProvider(&data);
6078
6079 TestCompletionCallback callback;
6080
6081 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6082 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6083
6084 int rv = trans->Start(&request, &callback, BoundNetLog());
6085
6086 EXPECT_EQ(ERR_IO_PENDING, rv);
6087 EXPECT_EQ(OK, callback.WaitForResult());
6088
6089 const HttpResponseInfo* response = trans->GetResponseInfo();
6090 ASSERT_TRUE(response != NULL);
6091 ASSERT_TRUE(response->headers != NULL);
6092 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6093
6094 std::string response_data;
6095 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6096 EXPECT_EQ("hello world", response_data);
6097
6098 EXPECT_FALSE(response->was_fetched_via_spdy);
6099 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576100 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536101
6102 HttpNetworkTransaction::SetNextProtos("");
6103 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6104}
[email protected]26ef6582010-06-24 02:30:476105
6106TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6107 // Simulate the SSL handshake completing with an NPN negotiation
6108 // followed by an immediate server closing of the socket.
6109 // Fix crash: http://crbug.com/46369
6110 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6111 HttpNetworkTransaction::SetNextProtos(
6112 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
6113 SessionDependencies session_deps;
6114
6115 HttpRequestInfo request;
6116 request.method = "GET";
6117 request.url = GURL("https://www.google.com/");
6118 request.load_flags = 0;
6119
6120 SSLSocketDataProvider ssl(true, OK);
6121 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6122 ssl.next_proto = "spdy/1";
6123 ssl.was_npn_negotiated = true;
6124 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6125
6126 MockWrite spdy_writes[] = {
6127 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
6128 arraysize(kGetSyn)),
6129 };
6130
6131 MockRead spdy_reads[] = {
6132 MockRead(false, 0, 0) // Not async - return 0 immediately.
6133 };
6134
6135 scoped_refptr<DelayedSocketData> spdy_data(
6136 new DelayedSocketData(
6137 0, // don't wait in this case, immediate hangup.
6138 spdy_reads, arraysize(spdy_reads),
6139 spdy_writes, arraysize(spdy_writes)));
6140 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6141
6142 TestCompletionCallback callback;
6143
6144 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6145 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6146
6147 int rv = trans->Start(&request, &callback, BoundNetLog());
6148 EXPECT_EQ(ERR_IO_PENDING, rv);
6149 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6150
6151 HttpNetworkTransaction::SetNextProtos("");
6152 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6153}
[email protected]89ceba9a2009-03-21 03:46:066154} // namespace net