blob: b8eb6e4c848832f4b2687dc0fca796f5622ffe3a [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]bacff652009-03-31 17:50:3315#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3216#include "net/base/mock_host_resolver.h"
[email protected]ac790b42009-12-02 04:31:3117#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4218#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3319#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5220#include "net/base/test_completion_callback.h"
21#include "net/base/upload_data.h"
[email protected]385a4672009-03-11 22:21:2922#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5723#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5725#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5226#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5327#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1128#include "net/proxy/proxy_resolver.h"
29#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4430#include "net/socket/client_socket_factory.h"
31#include "net/socket/socket_test_util.h"
32#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5433#include "net/spdy/spdy_framer.h"
34#include "net/spdy/spdy_session.h"
35#include "net/spdy/spdy_session_pool.h"
36#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1538#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5239
40//-----------------------------------------------------------------------------
41
[email protected]89ceba9a2009-03-21 03:46:0642namespace net {
43
[email protected]2d731a32010-04-29 01:04:0644class HttpNetworkSessionPeer {
45 public:
46 explicit HttpNetworkSessionPeer(
47 const scoped_refptr<HttpNetworkSession>& session)
48 : session_(session) {}
49
50 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
51 session_->tcp_socket_pool_ = pool;
52 }
53
54 void SetSocketPoolForSOCKSProxy(
55 const HostPortPair& socks_proxy,
56 const scoped_refptr<SOCKSClientSocketPool>& pool) {
57 session_->socks_socket_pool_[socks_proxy] = pool;
58 }
59
60 void SetSocketPoolForHTTPProxy(
61 const HostPortPair& http_proxy,
62 const scoped_refptr<TCPClientSocketPool>& pool) {
63 session_->http_proxy_socket_pool_[http_proxy] = pool;
64 }
65
66 private:
67 const scoped_refptr<HttpNetworkSession> session_;
68
69 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
70};
71
[email protected]e44de5d2009-06-05 20:12:4572// Helper to manage the lifetimes of the dependencies for a
73// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5974class SessionDependencies {
75 public:
76 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4277 SessionDependencies()
78 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3779 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1080 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]61a86c42010-04-19 22:45:5381 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
82 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5983
84 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4585 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4286 : host_resolver(new MockHostResolver),
87 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1088 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]61a86c42010-04-19 22:45:5389 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
90 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5991
[email protected]a2c2fb92009-07-18 07:31:0492 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0993 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4294 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5995 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5096 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]61a86c42010-04-19 22:45:5397 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:5998};
99
[email protected]1c773ea12009-04-28 19:58:42100ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50101 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48102 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39103 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53104}
105
[email protected]228ff742009-06-05 01:19:59106HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:51107 return new HttpNetworkSession(NULL,
108 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09109 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42110 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10111 session_deps->ssl_config_service,
[email protected]61a86c42010-04-19 22:45:53112 session_deps->spdy_session_pool,
[email protected]fa55e192010-02-15 14:25:50113 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:14114}
115
[email protected]89836e22008-09-25 20:33:42116class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52117 public:
[email protected]2ff8b312010-04-26 22:20:54118 virtual void SetUp() {
119 spdy::SpdyFramer::set_enable_compression_default(false);
120 }
121
[email protected]0e75a732008-10-16 20:36:09122 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54123 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09124 // Empty the current queue.
125 MessageLoop::current()->RunAllPending();
126 PlatformTest::TearDown();
127 }
128
[email protected]3d2a59b2008-09-26 19:44:25129 protected:
130 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52131
[email protected]ff007e162009-05-23 09:13:15132 struct SimpleGetHelperResult {
133 int rv;
134 std::string status_line;
135 std::string response_data;
136 };
initial.commit586acc5fe2008-07-26 22:42:52137
[email protected]31a2bfe2010-02-09 08:03:39138 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
139 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15140 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52141
[email protected]228ff742009-06-05 01:19:59142 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40143 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43144 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]ff007e162009-05-23 09:13:15146 HttpRequestInfo request;
147 request.method = "GET";
148 request.url = GURL("http://www.google.com/");
149 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]31a2bfe2010-02-09 08:03:39151 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59152 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]ff007e162009-05-23 09:13:15154 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]5a1d7ca2010-04-28 20:12:27156 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ff007e162009-05-23 09:13:15157 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]ff007e162009-05-23 09:13:15159 out.rv = callback.WaitForResult();
160 if (out.rv != OK)
161 return out;
162
163 const HttpResponseInfo* response = trans->GetResponseInfo();
164 EXPECT_TRUE(response != NULL);
165
166 EXPECT_TRUE(response->headers != NULL);
167 out.status_line = response->headers->GetStatusLine();
168
169 rv = ReadTransaction(trans.get(), &out.response_data);
170 EXPECT_EQ(OK, rv);
171
[email protected]aecfbf22008-10-16 02:02:47172 return out;
[email protected]ff007e162009-05-23 09:13:15173 }
initial.commit586acc5fe2008-07-26 22:42:52174
[email protected]ff007e162009-05-23 09:13:15175 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
176 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52177
[email protected]ff007e162009-05-23 09:13:15178 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15179};
[email protected]231d5a32008-09-13 00:45:27180
[email protected]15a5ccf82008-10-23 19:57:43181// Fill |str| with a long header list that consumes >= |size| bytes.
182void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19183 const char* row =
184 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
185 const int sizeof_row = strlen(row);
186 const int num_rows = static_cast<int>(
187 ceil(static_cast<float>(size) / sizeof_row));
188 const int sizeof_data = num_rows * sizeof_row;
189 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43190 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51191
[email protected]4ddaf2502008-10-23 18:26:19192 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43193 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19194}
195
[email protected]385a4672009-03-11 22:21:29196// Alternative functions that eliminate randomness and dependency on the local
197// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20198void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29199 static const uint8 bytes[] = {
200 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
201 };
202 static size_t current_byte = 0;
203 for (size_t i = 0; i < n; ++i) {
204 output[i] = bytes[current_byte++];
205 current_byte %= arraysize(bytes);
206 }
207}
208
[email protected]fe2bc6a2009-03-23 16:52:20209void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29210 static const uint8 bytes[] = {
211 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
212 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
213 };
214 static size_t current_byte = 0;
215 for (size_t i = 0; i < n; ++i) {
216 output[i] = bytes[current_byte++];
217 current_byte %= arraysize(bytes);
218 }
219}
220
[email protected]fe2bc6a2009-03-23 16:52:20221std::string MockGetHostName() {
222 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29223}
224
[email protected]2d731a32010-04-29 01:04:06225template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26226class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31227 public:
[email protected]2d731a32010-04-29 01:04:06228 CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]a796bcec2010-03-22 17:17:26229 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
[email protected]2d731a32010-04-29 01:04:06230 session->host_resolver(), NULL,
[email protected]61a86c42010-04-19 22:45:53231 NULL) {}
[email protected]d80a4322009-08-14 07:07:49232 const std::string last_group_name_received() const {
233 return last_group_name_;
234 }
235
[email protected]684970b2009-08-14 04:54:46236 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49237 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31238 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31239 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46240 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53241 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31242 last_group_name_ = group_name;
243 return ERR_IO_PENDING;
244 }
[email protected]04e5be32009-06-26 20:00:31245 virtual void CancelRequest(const std::string& group_name,
246 const ClientSocketHandle* handle) { }
247 virtual void ReleaseSocket(const std::string& group_name,
248 ClientSocket* socket) {}
249 virtual void CloseIdleSockets() {}
250 virtual HostResolver* GetHostResolver() const {
251 return NULL;
252 }
253 virtual int IdleSocketCount() const {
254 return 0;
255 }
256 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
257 return 0;
258 }
259 virtual LoadState GetLoadState(const std::string& group_name,
260 const ClientSocketHandle* handle) const {
261 return LOAD_STATE_IDLE;
262 }
[email protected]a796bcec2010-03-22 17:17:26263 virtual base::TimeDelta ConnectionTimeout() const {
264 return base::TimeDelta();
265 }
[email protected]d80a4322009-08-14 07:07:49266
267 private:
[email protected]04e5be32009-06-26 20:00:31268 std::string last_group_name_;
269};
270
[email protected]2d731a32010-04-29 01:04:06271typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11272CaptureGroupNameTCPSocketPool;
[email protected]2d731a32010-04-29 01:04:06273typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11274CaptureGroupNameSOCKSSocketPool;
275
[email protected]231d5a32008-09-13 00:45:27276//-----------------------------------------------------------------------------
277
278TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59279 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40280 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43281 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27282}
283
284TEST_F(HttpNetworkTransactionTest, SimpleGET) {
285 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35286 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
287 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42288 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27289 };
[email protected]31a2bfe2010-02-09 08:03:39290 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
291 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42292 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27293 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
294 EXPECT_EQ("hello world", out.response_data);
295}
296
297// Response with no status line.
298TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
299 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35300 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/0.9 200 OK", out.status_line);
307 EXPECT_EQ("hello world", out.response_data);
308}
309
310// Allow up to 4 bytes of junk to precede status line.
311TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
312 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35313 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[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/1.0 404 Not Found", out.status_line);
320 EXPECT_EQ("DATA", out.response_data);
321}
322
323// Allow up to 4 bytes of junk to precede status line.
324TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
325 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35326 MockRead("\n\nQJHTTP/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// Beyond 4 bytes of slop and it should fail to find a status line.
337TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
338 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35339 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[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]3d2a59b2008-09-26 19:44:25345 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
346 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27347}
348
349// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
350TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35352 MockRead("\n"),
353 MockRead("\n"),
354 MockRead("Q"),
355 MockRead("J"),
356 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42357 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27358 };
[email protected]31a2bfe2010-02-09 08:03:39359 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
360 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42361 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27362 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
363 EXPECT_EQ("DATA", out.response_data);
364}
365
366// Close the connection before enough bytes to have a status line.
367TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
368 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35369 MockRead("HTT"),
[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/0.9 200 OK", out.status_line);
376 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52377}
378
[email protected]f9d44aa2008-09-23 23:57:17379// Simulate a 204 response, lacking a Content-Length header, sent over a
380// persistent connection. The response should still terminate since a 204
381// cannot have a response body.
382TEST_F(HttpNetworkTransactionTest, StopsReading204) {
383 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35384 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
385 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42386 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17387 };
[email protected]31a2bfe2010-02-09 08:03:39388 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
389 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42390 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17391 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
392 EXPECT_EQ("", out.response_data);
393}
394
[email protected]0877e3d2009-10-17 22:29:57395// A simple request using chunked encoding with some extra data after.
396// (Like might be seen in a pipelined response.)
397TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
398 MockRead data_reads[] = {
399 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
400 MockRead("5\r\nHello\r\n"),
401 MockRead("1\r\n"),
402 MockRead(" \r\n"),
403 MockRead("5\r\nworld\r\n"),
404 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
405 MockRead(false, OK),
406 };
[email protected]31a2bfe2010-02-09 08:03:39407 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
408 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57409 EXPECT_EQ(OK, out.rv);
410 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
411 EXPECT_EQ("Hello world", out.response_data);
412}
413
[email protected]ef0faf2e72009-03-05 23:27:23414// Do a request using the HEAD method. Verify that we don't try to read the
415// message body (since HEAD has none).
416TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59417 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40418 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43419 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23420
[email protected]1c773ea12009-04-28 19:58:42421 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23422 request.method = "HEAD";
423 request.url = GURL("http://www.google.com/");
424 request.load_flags = 0;
425
426 MockWrite data_writes1[] = {
427 MockWrite("HEAD / HTTP/1.1\r\n"
428 "Host: www.google.com\r\n"
429 "Connection: keep-alive\r\n"
430 "Content-Length: 0\r\n\r\n"),
431 };
432 MockRead data_reads1[] = {
433 MockRead("HTTP/1.1 404 Not Found\r\n"),
434 MockRead("Server: Blah\r\n"),
435 MockRead("Content-Length: 1234\r\n\r\n"),
436
437 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42438 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23439 };
440
[email protected]31a2bfe2010-02-09 08:03:39441 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
442 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59443 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23444
445 TestCompletionCallback callback1;
446
[email protected]5a1d7ca2010-04-28 20:12:27447 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42448 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23449
450 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42451 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23452
[email protected]1c773ea12009-04-28 19:58:42453 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23454 EXPECT_FALSE(response == NULL);
455
456 // Check that the headers got parsed.
457 EXPECT_TRUE(response->headers != NULL);
458 EXPECT_EQ(1234, response->headers->GetContentLength());
459 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
460
461 std::string server_header;
462 void* iter = NULL;
463 bool has_server_header = response->headers->EnumerateHeader(
464 &iter, "Server", &server_header);
465 EXPECT_TRUE(has_server_header);
466 EXPECT_EQ("Blah", server_header);
467
468 // Reading should give EOF right away, since there is no message body
469 // (despite non-zero content-length).
470 std::string response_data;
471 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42472 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23473 EXPECT_EQ("", response_data);
474}
475
initial.commit586acc5fe2008-07-26 22:42:52476TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59477 SessionDependencies session_deps;
478 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52479
480 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35481 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
482 MockRead("hello"),
483 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
484 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42485 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52486 };
[email protected]31a2bfe2010-02-09 08:03:39487 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59488 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52489
490 const char* kExpectedResponseData[] = {
491 "hello", "world"
492 };
493
494 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43495 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52496
[email protected]1c773ea12009-04-28 19:58:42497 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52498 request.method = "GET";
499 request.url = GURL("http://www.google.com/");
500 request.load_flags = 0;
501
502 TestCompletionCallback callback;
503
[email protected]5a1d7ca2010-04-28 20:12:27504 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42505 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52506
507 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42508 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52509
[email protected]1c773ea12009-04-28 19:58:42510 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52511 EXPECT_TRUE(response != NULL);
512
513 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25514 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52515
516 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57517 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42518 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25519 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52520 }
521}
522
523TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59524 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40525 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43526 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52527
[email protected]1c773ea12009-04-28 19:58:42528 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52529 request.method = "POST";
530 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42531 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52532 request.upload_data->AppendBytes("foo", 3);
533 request.load_flags = 0;
534
535 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35536 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
537 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
538 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42539 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52540 };
[email protected]31a2bfe2010-02-09 08:03:39541 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59542 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52543
544 TestCompletionCallback callback;
545
[email protected]5a1d7ca2010-04-28 20:12:27546 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42547 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52548
549 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42550 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52551
[email protected]1c773ea12009-04-28 19:58:42552 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52553 EXPECT_TRUE(response != NULL);
554
555 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25556 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52557
558 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57559 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42560 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25561 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52562}
563
[email protected]3a2d3662009-03-27 03:49:14564// This test is almost the same as Ignores100 above, but the response contains
565// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57566// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14567TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59568 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40569 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43570 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14571
[email protected]1c773ea12009-04-28 19:58:42572 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14573 request.method = "GET";
574 request.url = GURL("http://www.foo.com/");
575 request.load_flags = 0;
576
577 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57578 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
579 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14580 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42581 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14582 };
[email protected]31a2bfe2010-02-09 08:03:39583 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59584 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14585
586 TestCompletionCallback callback;
587
[email protected]5a1d7ca2010-04-28 20:12:27588 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42589 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14590
591 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42592 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14593
[email protected]1c773ea12009-04-28 19:58:42594 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14595 EXPECT_TRUE(response != NULL);
596
597 EXPECT_TRUE(response->headers != NULL);
598 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
599
600 std::string response_data;
601 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42602 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14603 EXPECT_EQ("hello world", response_data);
604}
605
[email protected]ee9410e72010-01-07 01:42:38606TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
607 SessionDependencies session_deps;
608 scoped_ptr<HttpTransaction> trans(
609 new HttpNetworkTransaction(CreateSession(&session_deps)));
610
611 HttpRequestInfo request;
612 request.method = "POST";
613 request.url = GURL("http://www.foo.com/");
614 request.load_flags = 0;
615
616 MockRead data_reads[] = {
617 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
618 MockRead(true, 0),
619 };
[email protected]31a2bfe2010-02-09 08:03:39620 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38621 session_deps.socket_factory.AddSocketDataProvider(&data);
622
623 TestCompletionCallback callback;
624
[email protected]5a1d7ca2010-04-28 20:12:27625 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38626 EXPECT_EQ(ERR_IO_PENDING, rv);
627
628 rv = callback.WaitForResult();
629 EXPECT_EQ(OK, rv);
630
631 std::string response_data;
632 rv = ReadTransaction(trans.get(), &response_data);
633 EXPECT_EQ(OK, rv);
634 EXPECT_EQ("", response_data);
635}
636
637TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
638 SessionDependencies session_deps;
639 scoped_ptr<HttpTransaction> trans(
640 new HttpNetworkTransaction(CreateSession(&session_deps)));
641
642 HttpRequestInfo request;
643 request.method = "POST";
644 request.url = GURL("http://www.foo.com/");
645 request.load_flags = 0;
646
647 MockRead data_reads[] = {
648 MockRead(true, 0),
649 };
[email protected]31a2bfe2010-02-09 08:03:39650 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38651 session_deps.socket_factory.AddSocketDataProvider(&data);
652
653 TestCompletionCallback callback;
654
[email protected]5a1d7ca2010-04-28 20:12:27655 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38656 EXPECT_EQ(ERR_IO_PENDING, rv);
657
658 rv = callback.WaitForResult();
659 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
660}
661
[email protected]3d2a59b2008-09-26 19:44:25662// read_failure specifies a read failure that should cause the network
663// transaction to resend the request.
664void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
665 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59666 SessionDependencies session_deps;
667 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52668
[email protected]1c773ea12009-04-28 19:58:42669 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52670 request.method = "GET";
671 request.url = GURL("http://www.foo.com/");
672 request.load_flags = 0;
673
674 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35675 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
676 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25677 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52678 };
[email protected]31a2bfe2010-02-09 08:03:39679 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59680 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52681
682 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35683 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
684 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42685 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52686 };
[email protected]31a2bfe2010-02-09 08:03:39687 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59688 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52689
690 const char* kExpectedResponseData[] = {
691 "hello", "world"
692 };
693
694 for (int i = 0; i < 2; ++i) {
695 TestCompletionCallback callback;
696
[email protected]5695b8c2009-09-30 21:36:43697 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52698
[email protected]5a1d7ca2010-04-28 20:12:27699 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52701
702 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42703 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52704
[email protected]1c773ea12009-04-28 19:58:42705 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52706 EXPECT_TRUE(response != NULL);
707
708 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25709 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52710
711 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57712 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25714 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52715 }
716}
[email protected]3d2a59b2008-09-26 19:44:25717
718TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42719 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25720 KeepAliveConnectionResendRequestTest(read_failure);
721}
722
723TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42724 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25725 KeepAliveConnectionResendRequestTest(read_failure);
726}
727
728TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59729 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40730 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43731 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25732
[email protected]1c773ea12009-04-28 19:58:42733 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25734 request.method = "GET";
735 request.url = GURL("http://www.google.com/");
736 request.load_flags = 0;
737
738 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42739 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35740 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
741 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42742 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25743 };
[email protected]31a2bfe2010-02-09 08:03:39744 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59745 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25746
747 TestCompletionCallback callback;
748
[email protected]5a1d7ca2010-04-28 20:12:27749 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42750 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25751
752 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42753 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25754
[email protected]1c773ea12009-04-28 19:58:42755 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25756 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25757}
758
759// What do various browsers do when the server closes a non-keepalive
760// connection without sending any response header or body?
761//
762// IE7: error page
763// Safari 3.1.2 (Windows): error page
764// Firefox 3.0.1: blank page
765// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42766// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
767// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25768TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
769 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42770 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35771 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
772 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42773 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25774 };
[email protected]31a2bfe2010-02-09 08:03:39775 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
776 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42777 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25778}
[email protected]038e9a32008-10-08 22:40:16779
780// Test the request-challenge-retry sequence for basic auth.
781// (basic auth is the easiest to mock, because it has no randomness).
782TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59783 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40784 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43785 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16786
[email protected]1c773ea12009-04-28 19:58:42787 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16788 request.method = "GET";
789 request.url = GURL("http://www.google.com/");
790 request.load_flags = 0;
791
[email protected]f9ee6b52008-11-08 06:46:23792 MockWrite data_writes1[] = {
793 MockWrite("GET / HTTP/1.1\r\n"
794 "Host: www.google.com\r\n"
795 "Connection: keep-alive\r\n\r\n"),
796 };
797
[email protected]038e9a32008-10-08 22:40:16798 MockRead data_reads1[] = {
799 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
800 // Give a couple authenticate options (only the middle one is actually
801 // supported).
[email protected]22927ad2009-09-21 19:56:19802 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16803 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
804 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
805 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
806 // Large content-length -- won't matter, as connection will be reset.
807 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42808 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16809 };
810
811 // After calling trans->RestartWithAuth(), this is the request we should
812 // be issuing -- the final header line contains the credentials.
813 MockWrite data_writes2[] = {
814 MockWrite("GET / HTTP/1.1\r\n"
815 "Host: www.google.com\r\n"
816 "Connection: keep-alive\r\n"
817 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
818 };
819
820 // Lastly, the server responds with the actual content.
821 MockRead data_reads2[] = {
822 MockRead("HTTP/1.0 200 OK\r\n"),
823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
824 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42825 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16826 };
827
[email protected]31a2bfe2010-02-09 08:03:39828 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
829 data_writes1, arraysize(data_writes1));
830 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
831 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59832 session_deps.socket_factory.AddSocketDataProvider(&data1);
833 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16834
835 TestCompletionCallback callback1;
836
[email protected]5a1d7ca2010-04-28 20:12:27837 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42838 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16839
840 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42841 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16842
[email protected]1c773ea12009-04-28 19:58:42843 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16844 EXPECT_FALSE(response == NULL);
845
846 // The password prompt info should have been set in response->auth_challenge.
847 EXPECT_FALSE(response->auth_challenge.get() == NULL);
848
[email protected]71e4573a2009-05-21 22:03:00849 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16850 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
851 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
852
853 TestCompletionCallback callback2;
854
855 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42856 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16857
858 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42859 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16860
861 response = trans->GetResponseInfo();
862 EXPECT_FALSE(response == NULL);
863 EXPECT_TRUE(response->auth_challenge.get() == NULL);
864 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16865}
866
[email protected]861fcd52009-08-26 02:33:46867TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
868 SessionDependencies session_deps;
869 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43870 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46871
872 HttpRequestInfo request;
873 request.method = "GET";
874 request.url = GURL("http://www.google.com/");
875 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
876
877 MockWrite data_writes[] = {
878 MockWrite("GET / HTTP/1.1\r\n"
879 "Host: www.google.com\r\n"
880 "Connection: keep-alive\r\n\r\n"),
881 };
882
883 MockRead data_reads[] = {
884 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
885 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
886 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
887 // Large content-length -- won't matter, as connection will be reset.
888 MockRead("Content-Length: 10000\r\n\r\n"),
889 MockRead(false, ERR_FAILED),
890 };
891
[email protected]31a2bfe2010-02-09 08:03:39892 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
893 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59894 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46895 TestCompletionCallback callback;
896
[email protected]5a1d7ca2010-04-28 20:12:27897 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46898 EXPECT_EQ(ERR_IO_PENDING, rv);
899
900 rv = callback.WaitForResult();
901 EXPECT_EQ(0, rv);
902
903 const HttpResponseInfo* response = trans->GetResponseInfo();
904 ASSERT_FALSE(response == NULL);
905 EXPECT_TRUE(response->auth_challenge.get() == NULL);
906}
907
[email protected]2d2697f92009-02-18 21:00:32908// Test the request-challenge-retry sequence for basic auth, over a keep-alive
909// connection.
910TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59911 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40912 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43913 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32914
[email protected]1c773ea12009-04-28 19:58:42915 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32916 request.method = "GET";
917 request.url = GURL("http://www.google.com/");
918 request.load_flags = 0;
919
920 MockWrite data_writes1[] = {
921 MockWrite("GET / HTTP/1.1\r\n"
922 "Host: www.google.com\r\n"
923 "Connection: keep-alive\r\n\r\n"),
924
925 // After calling trans->RestartWithAuth(), this is the request we should
926 // be issuing -- the final header line contains the credentials.
927 MockWrite("GET / HTTP/1.1\r\n"
928 "Host: www.google.com\r\n"
929 "Connection: keep-alive\r\n"
930 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
931 };
932
933 MockRead data_reads1[] = {
934 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
935 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
936 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
937 MockRead("Content-Length: 14\r\n\r\n"),
938 MockRead("Unauthorized\r\n"),
939
940 // Lastly, the server responds with the actual content.
941 MockRead("HTTP/1.1 200 OK\r\n"),
942 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
943 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42944 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32945 };
946
[email protected]31a2bfe2010-02-09 08:03:39947 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
948 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59949 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32950
951 TestCompletionCallback callback1;
952
[email protected]5a1d7ca2010-04-28 20:12:27953 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42954 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32955
956 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42957 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32958
[email protected]1c773ea12009-04-28 19:58:42959 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32960 EXPECT_FALSE(response == NULL);
961
962 // The password prompt info should have been set in response->auth_challenge.
963 EXPECT_FALSE(response->auth_challenge.get() == NULL);
964
[email protected]71e4573a2009-05-21 22:03:00965 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32966 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
967 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
968
969 TestCompletionCallback callback2;
970
971 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42972 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32973
974 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42975 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32976
977 response = trans->GetResponseInfo();
978 EXPECT_FALSE(response == NULL);
979 EXPECT_TRUE(response->auth_challenge.get() == NULL);
980 EXPECT_EQ(100, response->headers->GetContentLength());
981}
982
983// Test the request-challenge-retry sequence for basic auth, over a keep-alive
984// connection and with no response body to drain.
985TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59986 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40987 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43988 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32989
[email protected]1c773ea12009-04-28 19:58:42990 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32991 request.method = "GET";
992 request.url = GURL("http://www.google.com/");
993 request.load_flags = 0;
994
995 MockWrite data_writes1[] = {
996 MockWrite("GET / HTTP/1.1\r\n"
997 "Host: www.google.com\r\n"
998 "Connection: keep-alive\r\n\r\n"),
999
1000 // After calling trans->RestartWithAuth(), this is the request we should
1001 // be issuing -- the final header line contains the credentials.
1002 MockWrite("GET / HTTP/1.1\r\n"
1003 "Host: www.google.com\r\n"
1004 "Connection: keep-alive\r\n"
1005 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1006 };
1007
[email protected]2d2697f92009-02-18 21:00:321008 MockRead data_reads1[] = {
1009 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1010 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311011 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321012
1013 // Lastly, the server responds with the actual content.
1014 MockRead("HTTP/1.1 200 OK\r\n"),
1015 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1016 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421017 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321018 };
1019
[email protected]31a2bfe2010-02-09 08:03:391020 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1021 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591022 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321023
1024 TestCompletionCallback callback1;
1025
[email protected]5a1d7ca2010-04-28 20:12:271026 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321028
1029 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421030 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321031
[email protected]1c773ea12009-04-28 19:58:421032 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321033 EXPECT_FALSE(response == NULL);
1034
1035 // The password prompt info should have been set in response->auth_challenge.
1036 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1037
[email protected]71e4573a2009-05-21 22:03:001038 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321039 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1040 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1041
1042 TestCompletionCallback callback2;
1043
1044 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421045 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321046
1047 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421048 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321049
1050 response = trans->GetResponseInfo();
1051 EXPECT_FALSE(response == NULL);
1052 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1053 EXPECT_EQ(100, response->headers->GetContentLength());
1054}
1055
1056// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1057// connection and with a large response body to drain.
1058TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591059 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401060 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431061 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321062
[email protected]1c773ea12009-04-28 19:58:421063 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321064 request.method = "GET";
1065 request.url = GURL("http://www.google.com/");
1066 request.load_flags = 0;
1067
1068 MockWrite data_writes1[] = {
1069 MockWrite("GET / HTTP/1.1\r\n"
1070 "Host: www.google.com\r\n"
1071 "Connection: keep-alive\r\n\r\n"),
1072
1073 // After calling trans->RestartWithAuth(), this is the request we should
1074 // be issuing -- the final header line contains the credentials.
1075 MockWrite("GET / HTTP/1.1\r\n"
1076 "Host: www.google.com\r\n"
1077 "Connection: keep-alive\r\n"
1078 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1079 };
1080
1081 // Respond with 5 kb of response body.
1082 std::string large_body_string("Unauthorized");
1083 large_body_string.append(5 * 1024, ' ');
1084 large_body_string.append("\r\n");
1085
1086 MockRead data_reads1[] = {
1087 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1088 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1090 // 5134 = 12 + 5 * 1024 + 2
1091 MockRead("Content-Length: 5134\r\n\r\n"),
1092 MockRead(true, large_body_string.data(), large_body_string.size()),
1093
1094 // Lastly, the server responds with the actual content.
1095 MockRead("HTTP/1.1 200 OK\r\n"),
1096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1097 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421098 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321099 };
1100
[email protected]31a2bfe2010-02-09 08:03:391101 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1102 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591103 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321104
1105 TestCompletionCallback callback1;
1106
[email protected]5a1d7ca2010-04-28 20:12:271107 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321109
1110 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421111 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321112
[email protected]1c773ea12009-04-28 19:58:421113 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321114 EXPECT_FALSE(response == NULL);
1115
1116 // The password prompt info should have been set in response->auth_challenge.
1117 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1118
[email protected]71e4573a2009-05-21 22:03:001119 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321120 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1121 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1122
1123 TestCompletionCallback callback2;
1124
1125 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421126 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321127
1128 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421129 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321130
1131 response = trans->GetResponseInfo();
1132 EXPECT_FALSE(response == NULL);
1133 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1134 EXPECT_EQ(100, response->headers->GetContentLength());
1135}
1136
1137// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311138// connection, but the server gets impatient and closes the connection.
1139TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1140 SessionDependencies session_deps;
1141 scoped_ptr<HttpTransaction> trans(
1142 new HttpNetworkTransaction(CreateSession(&session_deps)));
1143
1144 HttpRequestInfo request;
1145 request.method = "GET";
1146 request.url = GURL("http://www.google.com/");
1147 request.load_flags = 0;
1148
1149 MockWrite data_writes1[] = {
1150 MockWrite("GET / HTTP/1.1\r\n"
1151 "Host: www.google.com\r\n"
1152 "Connection: keep-alive\r\n\r\n"),
1153 // This simulates the seemingly successful write to a closed connection
1154 // if the bug is not fixed.
1155 MockWrite("GET / HTTP/1.1\r\n"
1156 "Host: www.google.com\r\n"
1157 "Connection: keep-alive\r\n"
1158 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1159 };
1160
1161 MockRead data_reads1[] = {
1162 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1163 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1165 MockRead("Content-Length: 14\r\n\r\n"),
1166 // Tell MockTCPClientSocket to simulate the server closing the connection.
1167 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1168 MockRead("Unauthorized\r\n"),
1169 MockRead(false, OK), // The server closes the connection.
1170 };
1171
1172 // After calling trans->RestartWithAuth(), this is the request we should
1173 // be issuing -- the final header line contains the credentials.
1174 MockWrite data_writes2[] = {
1175 MockWrite("GET / HTTP/1.1\r\n"
1176 "Host: www.google.com\r\n"
1177 "Connection: keep-alive\r\n"
1178 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1179 };
1180
1181 // Lastly, the server responds with the actual content.
1182 MockRead data_reads2[] = {
1183 MockRead("HTTP/1.1 200 OK\r\n"),
1184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1185 MockRead("Content-Length: 100\r\n\r\n"),
1186 MockRead(false, OK),
1187 };
1188
[email protected]31a2bfe2010-02-09 08:03:391189 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1190 data_writes1, arraysize(data_writes1));
1191 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1192 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311193 session_deps.socket_factory.AddSocketDataProvider(&data1);
1194 session_deps.socket_factory.AddSocketDataProvider(&data2);
1195
1196 TestCompletionCallback callback1;
1197
[email protected]5a1d7ca2010-04-28 20:12:271198 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311199 EXPECT_EQ(ERR_IO_PENDING, rv);
1200
1201 rv = callback1.WaitForResult();
1202 EXPECT_EQ(OK, rv);
1203
1204 const HttpResponseInfo* response = trans->GetResponseInfo();
1205 EXPECT_FALSE(response == NULL);
1206
1207 // The password prompt info should have been set in response->auth_challenge.
1208 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1209
1210 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1211 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1212 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1213
1214 TestCompletionCallback callback2;
1215
1216 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1217 EXPECT_EQ(ERR_IO_PENDING, rv);
1218
1219 rv = callback2.WaitForResult();
1220 EXPECT_EQ(OK, rv);
1221
1222 response = trans->GetResponseInfo();
1223 ASSERT_FALSE(response == NULL);
1224 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1225 EXPECT_EQ(100, response->headers->GetContentLength());
1226}
1227
1228// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321229// proxy connection, when setting up an SSL tunnel.
1230TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1231 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591232 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1233 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321234
[email protected]5695b8c2009-09-30 21:36:431235 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321236
[email protected]1c773ea12009-04-28 19:58:421237 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321238 request.method = "GET";
1239 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461240 // Ensure that proxy authentication is attempted even
1241 // when the no authentication data flag is set.
1242 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321243
1244 // Since we have proxy, should try to establish tunnel.
1245 MockWrite data_writes1[] = {
1246 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451247 "Host: www.google.com\r\n"
1248 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321249
1250 // After calling trans->RestartWithAuth(), this is the request we should
1251 // be issuing -- the final header line contains the credentials.
1252 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1253 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451254 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321255 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1256 };
1257
1258 // The proxy responds to the connect with a 407, using a persistent
1259 // connection.
1260 MockRead data_reads1[] = {
1261 // No credentials.
1262 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1263 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1264 MockRead("Content-Length: 10\r\n\r\n"),
1265 MockRead("0123456789"),
1266
1267 // Wrong credentials (wrong password).
1268 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1269 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1270 MockRead("Content-Length: 10\r\n\r\n"),
1271 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421272 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321273 };
1274
[email protected]31a2bfe2010-02-09 08:03:391275 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1276 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591277 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321278
1279 TestCompletionCallback callback1;
1280
[email protected]5a1d7ca2010-04-28 20:12:271281 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421282 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321283
1284 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421285 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321286
[email protected]1c773ea12009-04-28 19:58:421287 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321288 EXPECT_FALSE(response == NULL);
1289
1290 EXPECT_TRUE(response->headers->IsKeepAlive());
1291 EXPECT_EQ(407, response->headers->response_code());
1292 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421293 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321294
1295 // The password prompt info should have been set in response->auth_challenge.
1296 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1297
[email protected]71e4573a2009-05-21 22:03:001298 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321299 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1300 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1301
1302 TestCompletionCallback callback2;
1303
1304 // Wrong password (should be "bar").
1305 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421306 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321307
1308 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421309 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321310
1311 response = trans->GetResponseInfo();
1312 EXPECT_FALSE(response == NULL);
1313
1314 EXPECT_TRUE(response->headers->IsKeepAlive());
1315 EXPECT_EQ(407, response->headers->response_code());
1316 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421317 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321318
1319 // The password prompt info should have been set in response->auth_challenge.
1320 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1321
[email protected]71e4573a2009-05-21 22:03:001322 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321323 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1324 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1325}
1326
[email protected]a8e9b162009-03-12 00:06:441327// Test that we don't read the response body when we fail to establish a tunnel,
1328// even if the user cancels the proxy's auth attempt.
1329TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1330 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591331 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441332
[email protected]e44de5d2009-06-05 20:12:451333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441334
[email protected]5695b8c2009-09-30 21:36:431335 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441336
[email protected]1c773ea12009-04-28 19:58:421337 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441338 request.method = "GET";
1339 request.url = GURL("https://www.google.com/");
1340 request.load_flags = 0;
1341
1342 // Since we have proxy, should try to establish tunnel.
1343 MockWrite data_writes[] = {
1344 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451345 "Host: www.google.com\r\n"
1346 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441347 };
1348
1349 // The proxy responds to the connect with a 407.
1350 MockRead data_reads[] = {
1351 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1352 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1353 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421354 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441355 };
1356
[email protected]31a2bfe2010-02-09 08:03:391357 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1358 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591359 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441360
1361 TestCompletionCallback callback;
1362
[email protected]5a1d7ca2010-04-28 20:12:271363 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421364 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441365
1366 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421367 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441368
[email protected]1c773ea12009-04-28 19:58:421369 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441370 EXPECT_FALSE(response == NULL);
1371
1372 EXPECT_TRUE(response->headers->IsKeepAlive());
1373 EXPECT_EQ(407, response->headers->response_code());
1374 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421375 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441376
1377 std::string response_data;
1378 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421379 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441380}
1381
[email protected]8fdbcd22010-05-05 02:54:521382// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1383// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1384TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1385 // We are using a DIRECT connection (i.e. no proxy) for this session.
1386 SessionDependencies session_deps;
1387 scoped_ptr<HttpTransaction> trans(
1388 new HttpNetworkTransaction(CreateSession(&session_deps)));
1389
1390 HttpRequestInfo request;
1391 request.method = "GET";
1392 request.url = GURL("http://www.google.com/");
1393 request.load_flags = 0;
1394
1395 MockWrite data_writes1[] = {
1396 MockWrite("GET / HTTP/1.1\r\n"
1397 "Host: www.google.com\r\n"
1398 "Connection: keep-alive\r\n\r\n"),
1399 };
1400
1401 MockRead data_reads1[] = {
1402 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1403 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1404 // Large content-length -- won't matter, as connection will be reset.
1405 MockRead("Content-Length: 10000\r\n\r\n"),
1406 MockRead(false, ERR_FAILED),
1407 };
1408
1409 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1410 data_writes1, arraysize(data_writes1));
1411 session_deps.socket_factory.AddSocketDataProvider(&data1);
1412
1413 TestCompletionCallback callback;
1414
1415 int rv = trans->Start(&request, &callback, BoundNetLog());
1416 EXPECT_EQ(ERR_IO_PENDING, rv);
1417
1418 rv = callback.WaitForResult();
1419 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1420}
1421
[email protected]ff007e162009-05-23 09:13:151422void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081423 const MockRead& status, int expected_status) {
1424 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591425 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081426
[email protected]228ff742009-06-05 01:19:591427 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081428
[email protected]5695b8c2009-09-30 21:36:431429 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081430
[email protected]1c773ea12009-04-28 19:58:421431 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081432 request.method = "GET";
1433 request.url = GURL("https://www.google.com/");
1434 request.load_flags = 0;
1435
1436 // Since we have proxy, should try to establish tunnel.
1437 MockWrite data_writes[] = {
1438 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451439 "Host: www.google.com\r\n"
1440 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081441 };
1442
1443 MockRead data_reads[] = {
1444 status,
1445 MockRead("Content-Length: 10\r\n\r\n"),
1446 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421447 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081448 };
1449
[email protected]31a2bfe2010-02-09 08:03:391450 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1451 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591452 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081453
1454 TestCompletionCallback callback;
1455
[email protected]5a1d7ca2010-04-28 20:12:271456 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421457 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081458
1459 rv = callback.WaitForResult();
1460 EXPECT_EQ(expected_status, rv);
1461}
1462
[email protected]ff007e162009-05-23 09:13:151463void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081464 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421465 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081466}
1467
1468TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1469 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1470}
1471
1472TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1473 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1474}
1475
1476TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1477 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1478}
1479
1480TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1481 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1482}
1483
1484TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1485 ConnectStatusHelper(
1486 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1487}
1488
1489TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1490 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1491}
1492
1493TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1494 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1495}
1496
1497TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1498 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1499}
1500
1501TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1502 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1503}
1504
1505TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1506 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1507}
1508
1509TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1510 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1511}
1512
1513TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1514 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1515}
1516
1517TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1518 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1519}
1520
1521TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1522 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1523}
1524
1525TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1526 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1527}
1528
1529TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1530 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1531}
1532
1533TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1534 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1535}
1536
1537TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1538 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1539}
1540
1541TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1542 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1543}
1544
1545TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1546 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1547}
1548
1549TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1550 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1551}
1552
1553TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1554 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1555}
1556
1557TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1558 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1559}
1560
1561TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1562 ConnectStatusHelperWithExpectedStatus(
1563 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421564 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081565}
1566
1567TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1568 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1569}
1570
1571TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1572 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1573}
1574
1575TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1576 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1577}
1578
1579TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1580 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1581}
1582
1583TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1584 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1585}
1586
1587TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1588 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1589}
1590
1591TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1592 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1593}
1594
1595TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1596 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1597}
1598
1599TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1600 ConnectStatusHelper(
1601 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1602}
1603
1604TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1605 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1606}
1607
1608TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1609 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1610}
1611
1612TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1613 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1614}
1615
1616TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1617 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1618}
1619
1620TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1621 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1622}
1623
1624TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1625 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1626}
1627
1628TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1629 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1630}
1631
[email protected]038e9a32008-10-08 22:40:161632// Test the flow when both the proxy server AND origin server require
1633// authentication. Again, this uses basic auth for both since that is
1634// the simplest to mock.
1635TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591636 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011637
[email protected]038e9a32008-10-08 22:40:161638 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421639 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431640 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161641
[email protected]1c773ea12009-04-28 19:58:421642 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161643 request.method = "GET";
1644 request.url = GURL("http://www.google.com/");
1645 request.load_flags = 0;
1646
[email protected]f9ee6b52008-11-08 06:46:231647 MockWrite data_writes1[] = {
1648 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1649 "Host: www.google.com\r\n"
1650 "Proxy-Connection: keep-alive\r\n\r\n"),
1651 };
1652
[email protected]038e9a32008-10-08 22:40:161653 MockRead data_reads1[] = {
1654 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1655 // Give a couple authenticate options (only the middle one is actually
1656 // supported).
[email protected]22927ad2009-09-21 19:56:191657 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161658 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1659 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1661 // Large content-length -- won't matter, as connection will be reset.
1662 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421663 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161664 };
1665
1666 // After calling trans->RestartWithAuth() the first time, this is the
1667 // request we should be issuing -- the final header line contains the
1668 // proxy's credentials.
1669 MockWrite data_writes2[] = {
1670 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1671 "Host: www.google.com\r\n"
1672 "Proxy-Connection: keep-alive\r\n"
1673 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1674 };
1675
1676 // Now the proxy server lets the request pass through to origin server.
1677 // The origin server responds with a 401.
1678 MockRead data_reads2[] = {
1679 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1680 // Note: We are using the same realm-name as the proxy server. This is
1681 // completely valid, as realms are unique across hosts.
1682 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1683 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1684 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421685 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161686 };
1687
1688 // After calling trans->RestartWithAuth() the second time, we should send
1689 // the credentials for both the proxy and origin server.
1690 MockWrite data_writes3[] = {
1691 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1692 "Host: www.google.com\r\n"
1693 "Proxy-Connection: keep-alive\r\n"
1694 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1695 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1696 };
1697
1698 // Lastly we get the desired content.
1699 MockRead data_reads3[] = {
1700 MockRead("HTTP/1.0 200 OK\r\n"),
1701 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1702 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421703 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161704 };
1705
[email protected]31a2bfe2010-02-09 08:03:391706 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1707 data_writes1, arraysize(data_writes1));
1708 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1709 data_writes2, arraysize(data_writes2));
1710 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1711 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591712 session_deps.socket_factory.AddSocketDataProvider(&data1);
1713 session_deps.socket_factory.AddSocketDataProvider(&data2);
1714 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161715
1716 TestCompletionCallback callback1;
1717
[email protected]5a1d7ca2010-04-28 20:12:271718 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421719 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161720
1721 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421722 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161723
[email protected]1c773ea12009-04-28 19:58:421724 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161725 EXPECT_FALSE(response == NULL);
1726
1727 // The password prompt info should have been set in response->auth_challenge.
1728 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1729
[email protected]71e4573a2009-05-21 22:03:001730 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161731 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1732 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1733
1734 TestCompletionCallback callback2;
1735
1736 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421737 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161738
1739 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421740 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161741
1742 response = trans->GetResponseInfo();
1743 EXPECT_FALSE(response == NULL);
1744 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1745
[email protected]71e4573a2009-05-21 22:03:001746 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161747 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1748 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1749
1750 TestCompletionCallback callback3;
1751
1752 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421753 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161754
1755 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421756 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161757
1758 response = trans->GetResponseInfo();
1759 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1760 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161761}
[email protected]4ddaf2502008-10-23 18:26:191762
[email protected]ea9dc9a2009-09-05 00:43:321763// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1764// can't hook into its internals to cause it to generate predictable NTLM
1765// authorization headers.
1766#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291767// The NTLM authentication unit tests were generated by capturing the HTTP
1768// requests and responses using Fiddler 2 and inspecting the generated random
1769// bytes in the debugger.
1770
1771// Enter the correct password and authenticate successfully.
1772TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421773 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111774 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591775 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401776 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431777 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241778
[email protected]1c773ea12009-04-28 19:58:421779 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241780 request.method = "GET";
1781 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1782 request.load_flags = 0;
1783
1784 MockWrite data_writes1[] = {
1785 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1786 "Host: 172.22.68.17\r\n"
1787 "Connection: keep-alive\r\n\r\n"),
1788 };
1789
1790 MockRead data_reads1[] = {
1791 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1792 // Negotiate and NTLM are often requested together. We only support NTLM.
1793 MockRead("WWW-Authenticate: Negotiate\r\n"),
1794 MockRead("WWW-Authenticate: NTLM\r\n"),
1795 MockRead("Connection: close\r\n"),
1796 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361797 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241798 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421799 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241800 };
1801
1802 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221803 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241804 // request we should be issuing -- the final header line contains a Type
1805 // 1 message.
1806 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1807 "Host: 172.22.68.17\r\n"
1808 "Connection: keep-alive\r\n"
1809 "Authorization: NTLM "
1810 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1811
1812 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1813 // (the credentials for the origin server). The second request continues
1814 // on the same connection.
1815 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1816 "Host: 172.22.68.17\r\n"
1817 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291818 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1819 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1820 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1821 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1822 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241823 };
1824
1825 MockRead data_reads2[] = {
1826 // The origin server responds with a Type 2 message.
1827 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1828 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291829 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241830 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1831 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1832 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1833 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1834 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1835 "BtAAAAAAA=\r\n"),
1836 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361837 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241838 MockRead("You are not authorized to view this page\r\n"),
1839
1840 // Lastly we get the desired content.
1841 MockRead("HTTP/1.1 200 OK\r\n"),
1842 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1843 MockRead("Content-Length: 13\r\n\r\n"),
1844 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421845 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241846 };
1847
[email protected]31a2bfe2010-02-09 08:03:391848 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1849 data_writes1, arraysize(data_writes1));
1850 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1851 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591852 session_deps.socket_factory.AddSocketDataProvider(&data1);
1853 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241854
1855 TestCompletionCallback callback1;
1856
[email protected]5a1d7ca2010-04-28 20:12:271857 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421858 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241859
1860 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421861 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241862
[email protected]0757e7702009-03-27 04:00:221863 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1864 TestCompletionCallback callback2;
1865 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421866 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221867 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421868 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221869 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1870
[email protected]1c773ea12009-04-28 19:58:421871 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241872 EXPECT_FALSE(response == NULL);
1873
1874 // The password prompt info should have been set in response->auth_challenge.
1875 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1876
[email protected]71e4573a2009-05-21 22:03:001877 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241878 EXPECT_EQ(L"", response->auth_challenge->realm);
1879 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1880
[email protected]0757e7702009-03-27 04:00:221881 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241882
[email protected]0757e7702009-03-27 04:00:221883 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421884 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241885
[email protected]0757e7702009-03-27 04:00:221886 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421887 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241888
1889 response = trans->GetResponseInfo();
1890 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1891 EXPECT_EQ(13, response->headers->GetContentLength());
1892}
1893
[email protected]385a4672009-03-11 22:21:291894// Enter a wrong password, and then the correct one.
1895TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421896 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111897 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591898 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401899 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431900 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291901
[email protected]1c773ea12009-04-28 19:58:421902 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291903 request.method = "GET";
1904 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1905 request.load_flags = 0;
1906
1907 MockWrite data_writes1[] = {
1908 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1909 "Host: 172.22.68.17\r\n"
1910 "Connection: keep-alive\r\n\r\n"),
1911 };
1912
1913 MockRead data_reads1[] = {
1914 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1915 // Negotiate and NTLM are often requested together. We only support NTLM.
1916 MockRead("WWW-Authenticate: Negotiate\r\n"),
1917 MockRead("WWW-Authenticate: NTLM\r\n"),
1918 MockRead("Connection: close\r\n"),
1919 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361920 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291921 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421922 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291923 };
1924
1925 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221926 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291927 // request we should be issuing -- the final header line contains a Type
1928 // 1 message.
1929 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1930 "Host: 172.22.68.17\r\n"
1931 "Connection: keep-alive\r\n"
1932 "Authorization: NTLM "
1933 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1934
1935 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1936 // (the credentials for the origin server). The second request continues
1937 // on the same connection.
1938 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1939 "Host: 172.22.68.17\r\n"
1940 "Connection: keep-alive\r\n"
1941 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1942 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1943 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1944 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1945 "4Ww7b7E=\r\n\r\n"),
1946 };
1947
1948 MockRead data_reads2[] = {
1949 // The origin server responds with a Type 2 message.
1950 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1951 MockRead("WWW-Authenticate: NTLM "
1952 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1953 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1954 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1955 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1956 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1957 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1958 "BtAAAAAAA=\r\n"),
1959 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361960 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291961 MockRead("You are not authorized to view this page\r\n"),
1962
1963 // Wrong password.
1964 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1965 MockRead("WWW-Authenticate: Negotiate\r\n"),
1966 MockRead("WWW-Authenticate: NTLM\r\n"),
1967 MockRead("Connection: close\r\n"),
1968 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361969 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291970 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421971 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291972 };
1973
1974 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221975 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291976 // request we should be issuing -- the final header line contains a Type
1977 // 1 message.
1978 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1979 "Host: 172.22.68.17\r\n"
1980 "Connection: keep-alive\r\n"
1981 "Authorization: NTLM "
1982 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1983
1984 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1985 // (the credentials for the origin server). The second request continues
1986 // on the same connection.
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"
1990 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1991 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1992 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1993 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1994 "+4MUm7c=\r\n\r\n"),
1995 };
1996
1997 MockRead data_reads3[] = {
1998 // The origin server responds with a Type 2 message.
1999 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2000 MockRead("WWW-Authenticate: NTLM "
2001 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2002 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2003 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2004 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2005 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2006 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2007 "BtAAAAAAA=\r\n"),
2008 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362009 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292010 MockRead("You are not authorized to view this page\r\n"),
2011
2012 // Lastly we get the desired content.
2013 MockRead("HTTP/1.1 200 OK\r\n"),
2014 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2015 MockRead("Content-Length: 13\r\n\r\n"),
2016 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422017 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292018 };
2019
[email protected]31a2bfe2010-02-09 08:03:392020 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2021 data_writes1, arraysize(data_writes1));
2022 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2023 data_writes2, arraysize(data_writes2));
2024 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2025 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592026 session_deps.socket_factory.AddSocketDataProvider(&data1);
2027 session_deps.socket_factory.AddSocketDataProvider(&data2);
2028 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292029
2030 TestCompletionCallback callback1;
2031
[email protected]5a1d7ca2010-04-28 20:12:272032 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422033 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292034
2035 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422036 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292037
[email protected]0757e7702009-03-27 04:00:222038 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292039 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222040 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422041 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292042 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422043 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222044 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292045
[email protected]1c773ea12009-04-28 19:58:422046 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292047 EXPECT_FALSE(response == NULL);
2048
2049 // The password prompt info should have been set in response->auth_challenge.
2050 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2051
[email protected]71e4573a2009-05-21 22:03:002052 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292053 EXPECT_EQ(L"", response->auth_challenge->realm);
2054 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2055
2056 TestCompletionCallback callback3;
2057
[email protected]0757e7702009-03-27 04:00:222058 // Enter the wrong password.
2059 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422060 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292061
2062 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422063 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292064
[email protected]0757e7702009-03-27 04:00:222065 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2066 TestCompletionCallback callback4;
2067 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422068 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222069 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422070 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222071 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2072
2073 response = trans->GetResponseInfo();
2074 EXPECT_FALSE(response == NULL);
2075
2076 // The password prompt info should have been set in response->auth_challenge.
2077 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2078
[email protected]71e4573a2009-05-21 22:03:002079 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222080 EXPECT_EQ(L"", response->auth_challenge->realm);
2081 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2082
2083 TestCompletionCallback callback5;
2084
2085 // Now enter the right password.
2086 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422087 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222088
2089 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422090 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222091
[email protected]385a4672009-03-11 22:21:292092 response = trans->GetResponseInfo();
2093 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2094 EXPECT_EQ(13, response->headers->GetContentLength());
2095}
[email protected]ea9dc9a2009-09-05 00:43:322096#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292097
[email protected]4ddaf2502008-10-23 18:26:192098// Test reading a server response which has only headers, and no body.
2099// After some maximum number of bytes is consumed, the transaction should
2100// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2101TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592102 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402103 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432104 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192105
[email protected]1c773ea12009-04-28 19:58:422106 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192107 request.method = "GET";
2108 request.url = GURL("http://www.google.com/");
2109 request.load_flags = 0;
2110
[email protected]b75b7b2f2009-10-06 00:54:532111 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432112 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532113 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192114
2115 MockRead data_reads[] = {
2116 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432117 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192118 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422119 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192120 };
[email protected]31a2bfe2010-02-09 08:03:392121 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592122 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192123
2124 TestCompletionCallback callback;
2125
[email protected]5a1d7ca2010-04-28 20:12:272126 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422127 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192128
2129 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422130 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192131
[email protected]1c773ea12009-04-28 19:58:422132 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192133 EXPECT_TRUE(response == NULL);
2134}
[email protected]f4e426b2008-11-05 00:24:492135
2136// Make sure that we don't try to reuse a TCPClientSocket when failing to
2137// establish tunnel.
2138// http://code.google.com/p/chromium/issues/detail?id=3772
2139TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2140 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592141 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012142
[email protected]228ff742009-06-05 01:19:592143 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492144
[email protected]5695b8c2009-09-30 21:36:432145 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492146
[email protected]1c773ea12009-04-28 19:58:422147 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492148 request.method = "GET";
2149 request.url = GURL("https://www.google.com/");
2150 request.load_flags = 0;
2151
2152 // Since we have proxy, should try to establish tunnel.
2153 MockWrite data_writes1[] = {
2154 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452155 "Host: www.google.com\r\n"
2156 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492157 };
2158
[email protected]77848d12008-11-14 00:00:222159 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492160 // connection. Usually a proxy would return 501 (not implemented),
2161 // or 200 (tunnel established).
2162 MockRead data_reads1[] = {
2163 MockRead("HTTP/1.1 404 Not Found\r\n"),
2164 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422165 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492166 };
2167
[email protected]31a2bfe2010-02-09 08:03:392168 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2169 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592170 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492171
2172 TestCompletionCallback callback1;
2173
[email protected]5a1d7ca2010-04-28 20:12:272174 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422175 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492176
2177 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422178 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492179
[email protected]1c773ea12009-04-28 19:58:422180 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082181 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492182
[email protected]b4404c02009-04-10 16:38:522183 // Empty the current queue. This is necessary because idle sockets are
2184 // added to the connection pool asynchronously with a PostTask.
2185 MessageLoop::current()->RunAllPending();
2186
[email protected]f4e426b2008-11-05 00:24:492187 // We now check to make sure the TCPClientSocket was not added back to
2188 // the pool.
[email protected]a937a06d2009-08-19 21:19:242189 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492190 trans.reset();
[email protected]b4404c02009-04-10 16:38:522191 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492192 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242193 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492194}
[email protected]372d34a2008-11-05 21:30:512195
[email protected]1b157c02009-04-21 01:55:402196// Make sure that we recycle a socket after reading all of the response body.
2197TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592198 SessionDependencies session_deps;
2199 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402200
[email protected]5695b8c2009-09-30 21:36:432201 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402202
[email protected]1c773ea12009-04-28 19:58:422203 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402204 request.method = "GET";
2205 request.url = GURL("http://www.google.com/");
2206 request.load_flags = 0;
2207
2208 MockRead data_reads[] = {
2209 // A part of the response body is received with the response headers.
2210 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2211 // The rest of the response body is received in two parts.
2212 MockRead("lo"),
2213 MockRead(" world"),
2214 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422215 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402216 };
2217
[email protected]31a2bfe2010-02-09 08:03:392218 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592219 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402220
2221 TestCompletionCallback callback;
2222
[email protected]5a1d7ca2010-04-28 20:12:272223 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422224 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402225
2226 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422227 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402228
[email protected]1c773ea12009-04-28 19:58:422229 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402230 EXPECT_TRUE(response != NULL);
2231
2232 EXPECT_TRUE(response->headers != NULL);
2233 std::string status_line = response->headers->GetStatusLine();
2234 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2235
[email protected]a937a06d2009-08-19 21:19:242236 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402237
2238 std::string response_data;
2239 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422240 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402241 EXPECT_EQ("hello world", response_data);
2242
2243 // Empty the current queue. This is necessary because idle sockets are
2244 // added to the connection pool asynchronously with a PostTask.
2245 MessageLoop::current()->RunAllPending();
2246
2247 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242248 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402249}
2250
[email protected]b4404c02009-04-10 16:38:522251// Make sure that we recycle a socket after a zero-length response.
2252// http://crbug.com/9880
2253TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592254 SessionDependencies session_deps;
2255 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522256
[email protected]5695b8c2009-09-30 21:36:432257 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522258
[email protected]1c773ea12009-04-28 19:58:422259 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522260 request.method = "GET";
2261 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2262 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2263 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2264 "rt=prt.2642,ol.2649,xjs.2951");
2265 request.load_flags = 0;
2266
2267 MockRead data_reads[] = {
2268 MockRead("HTTP/1.1 204 No Content\r\n"
2269 "Content-Length: 0\r\n"
2270 "Content-Type: text/html\r\n\r\n"),
2271 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422272 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522273 };
2274
[email protected]31a2bfe2010-02-09 08:03:392275 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592276 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522277
2278 TestCompletionCallback callback;
2279
[email protected]5a1d7ca2010-04-28 20:12:272280 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422281 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522282
2283 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422284 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522285
[email protected]1c773ea12009-04-28 19:58:422286 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522287 EXPECT_TRUE(response != NULL);
2288
2289 EXPECT_TRUE(response->headers != NULL);
2290 std::string status_line = response->headers->GetStatusLine();
2291 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2292
[email protected]a937a06d2009-08-19 21:19:242293 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522294
2295 std::string response_data;
2296 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422297 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522298 EXPECT_EQ("", response_data);
2299
2300 // Empty the current queue. This is necessary because idle sockets are
2301 // added to the connection pool asynchronously with a PostTask.
2302 MessageLoop::current()->RunAllPending();
2303
2304 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242305 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522306}
2307
[email protected]372d34a2008-11-05 21:30:512308TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422309 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512310 // Transaction 1: a GET request that succeeds. The socket is recycled
2311 // after use.
2312 request[0].method = "GET";
2313 request[0].url = GURL("http://www.google.com/");
2314 request[0].load_flags = 0;
2315 // Transaction 2: a POST request. Reuses the socket kept alive from
2316 // transaction 1. The first attempts fails when writing the POST data.
2317 // This causes the transaction to retry with a new socket. The second
2318 // attempt succeeds.
2319 request[1].method = "POST";
2320 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422321 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512322 request[1].upload_data->AppendBytes("foo", 3);
2323 request[1].load_flags = 0;
2324
[email protected]228ff742009-06-05 01:19:592325 SessionDependencies session_deps;
2326 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512327
2328 // The first socket is used for transaction 1 and the first attempt of
2329 // transaction 2.
2330
2331 // The response of transaction 1.
2332 MockRead data_reads1[] = {
2333 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2334 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422335 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512336 };
2337 // The mock write results of transaction 1 and the first attempt of
2338 // transaction 2.
2339 MockWrite data_writes1[] = {
2340 MockWrite(false, 64), // GET
2341 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422342 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512343 };
[email protected]31a2bfe2010-02-09 08:03:392344 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2345 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512346
2347 // The second socket is used for the second attempt of transaction 2.
2348
2349 // The response of transaction 2.
2350 MockRead data_reads2[] = {
2351 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2352 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422353 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512354 };
2355 // The mock write results of the second attempt of transaction 2.
2356 MockWrite data_writes2[] = {
2357 MockWrite(false, 93), // POST
2358 MockWrite(false, 3), // POST data
2359 };
[email protected]31a2bfe2010-02-09 08:03:392360 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2361 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512362
[email protected]5ecc992a42009-11-11 01:41:592363 session_deps.socket_factory.AddSocketDataProvider(&data1);
2364 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512365
2366 const char* kExpectedResponseData[] = {
2367 "hello world", "welcome"
2368 };
2369
2370 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422371 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432372 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512373
2374 TestCompletionCallback callback;
2375
[email protected]5a1d7ca2010-04-28 20:12:272376 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422377 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512378
2379 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422380 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512381
[email protected]1c773ea12009-04-28 19:58:422382 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512383 EXPECT_TRUE(response != NULL);
2384
2385 EXPECT_TRUE(response->headers != NULL);
2386 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2387
2388 std::string response_data;
2389 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422390 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512391 EXPECT_EQ(kExpectedResponseData[i], response_data);
2392 }
2393}
[email protected]f9ee6b52008-11-08 06:46:232394
2395// Test the request-challenge-retry sequence for basic auth when there is
2396// an identity in the URL. The request should be sent as normal, but when
2397// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322398TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592399 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402400 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432401 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232402
[email protected]1c773ea12009-04-28 19:58:422403 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232404 request.method = "GET";
2405 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292406 request.url = GURL("http://foo:b@[email protected]/");
2407
2408 // The password contains an escaped character -- for this test to pass it
2409 // will need to be unescaped by HttpNetworkTransaction.
2410 EXPECT_EQ("b%40r", request.url.password());
2411
[email protected]ea9dc9a2009-09-05 00:43:322412 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232413
2414 MockWrite data_writes1[] = {
2415 MockWrite("GET / HTTP/1.1\r\n"
2416 "Host: www.google.com\r\n"
2417 "Connection: keep-alive\r\n\r\n"),
2418 };
2419
2420 MockRead data_reads1[] = {
2421 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2422 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2423 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422424 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232425 };
2426
2427 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322428 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232429 MockWrite data_writes2[] = {
2430 MockWrite("GET / HTTP/1.1\r\n"
2431 "Host: www.google.com\r\n"
2432 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292433 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232434 };
2435
2436 MockRead data_reads2[] = {
2437 MockRead("HTTP/1.0 200 OK\r\n"),
2438 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422439 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232440 };
2441
[email protected]31a2bfe2010-02-09 08:03:392442 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2443 data_writes1, arraysize(data_writes1));
2444 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2445 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592446 session_deps.socket_factory.AddSocketDataProvider(&data1);
2447 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232448
2449 TestCompletionCallback callback1;
2450
[email protected]5a1d7ca2010-04-28 20:12:272451 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422452 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232453
2454 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422455 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232456
[email protected]0757e7702009-03-27 04:00:222457 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2458 TestCompletionCallback callback2;
2459 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422460 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222461 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422462 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222463 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2464
[email protected]1c773ea12009-04-28 19:58:422465 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232466 EXPECT_FALSE(response == NULL);
2467
2468 // There is no challenge info, since the identity in URL worked.
2469 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2470
2471 EXPECT_EQ(100, response->headers->GetContentLength());
2472
2473 // Empty the current queue.
2474 MessageLoop::current()->RunAllPending();
2475}
2476
[email protected]ea9dc9a2009-09-05 00:43:322477// Test the request-challenge-retry sequence for basic auth when there is
2478// an incorrect identity in the URL. The identity from the URL should be used
2479// only once.
2480TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2481 SessionDependencies session_deps;
2482 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432483 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322484
2485 HttpRequestInfo request;
2486 request.method = "GET";
2487 // Note: the URL has a username:password in it. The password "baz" is
2488 // wrong (should be "bar").
2489 request.url = GURL("http://foo:[email protected]/");
2490
2491 request.load_flags = LOAD_NORMAL;
2492
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"),
2503 MockRead(false, ERR_FAILED),
2504 };
2505
2506 // After the challenge above, the transaction will be restarted using the
2507 // identity from the url (foo, baz) to answer the challenge.
2508 MockWrite data_writes2[] = {
2509 MockWrite("GET / HTTP/1.1\r\n"
2510 "Host: www.google.com\r\n"
2511 "Connection: keep-alive\r\n"
2512 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2513 };
2514
2515 MockRead data_reads2[] = {
2516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2517 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2518 MockRead("Content-Length: 10\r\n\r\n"),
2519 MockRead(false, ERR_FAILED),
2520 };
2521
2522 // After the challenge above, the transaction will be restarted using the
2523 // identity supplied by the user (foo, bar) to answer the challenge.
2524 MockWrite data_writes3[] = {
2525 MockWrite("GET / HTTP/1.1\r\n"
2526 "Host: www.google.com\r\n"
2527 "Connection: keep-alive\r\n"
2528 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2529 };
2530
2531 MockRead data_reads3[] = {
2532 MockRead("HTTP/1.0 200 OK\r\n"),
2533 MockRead("Content-Length: 100\r\n\r\n"),
2534 MockRead(false, OK),
2535 };
2536
[email protected]31a2bfe2010-02-09 08:03:392537 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2538 data_writes1, arraysize(data_writes1));
2539 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2540 data_writes2, arraysize(data_writes2));
2541 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2542 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592543 session_deps.socket_factory.AddSocketDataProvider(&data1);
2544 session_deps.socket_factory.AddSocketDataProvider(&data2);
2545 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322546
2547 TestCompletionCallback callback1;
2548
[email protected]5a1d7ca2010-04-28 20:12:272549 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322550 EXPECT_EQ(ERR_IO_PENDING, rv);
2551
2552 rv = callback1.WaitForResult();
2553 EXPECT_EQ(OK, rv);
2554
2555 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2556 TestCompletionCallback callback2;
2557 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2558 EXPECT_EQ(ERR_IO_PENDING, rv);
2559 rv = callback2.WaitForResult();
2560 EXPECT_EQ(OK, rv);
2561 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2562
2563 const HttpResponseInfo* response = trans->GetResponseInfo();
2564 EXPECT_FALSE(response == NULL);
2565 // The password prompt info should have been set in response->auth_challenge.
2566 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2567
2568 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2569 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2570 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2571
2572 TestCompletionCallback callback3;
2573 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2574 EXPECT_EQ(ERR_IO_PENDING, rv);
2575 rv = callback3.WaitForResult();
2576 EXPECT_EQ(OK, rv);
2577 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2578
2579 response = trans->GetResponseInfo();
2580 EXPECT_FALSE(response == NULL);
2581
2582 // There is no challenge info, since the identity worked.
2583 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2584
2585 EXPECT_EQ(100, response->headers->GetContentLength());
2586
2587 // Empty the current queue.
2588 MessageLoop::current()->RunAllPending();
2589}
2590
[email protected]f9ee6b52008-11-08 06:46:232591// Test that previously tried username/passwords for a realm get re-used.
2592TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592593 SessionDependencies session_deps;
2594 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232595
2596 // Transaction 1: authenticate (foo, bar) on MyRealm1
2597 {
[email protected]5695b8c2009-09-30 21:36:432598 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232599
[email protected]1c773ea12009-04-28 19:58:422600 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232601 request.method = "GET";
2602 request.url = GURL("http://www.google.com/x/y/z");
2603 request.load_flags = 0;
2604
2605 MockWrite data_writes1[] = {
2606 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2607 "Host: www.google.com\r\n"
2608 "Connection: keep-alive\r\n\r\n"),
2609 };
2610
2611 MockRead data_reads1[] = {
2612 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2613 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2614 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422615 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232616 };
2617
2618 // Resend with authorization (username=foo, password=bar)
2619 MockWrite data_writes2[] = {
2620 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2621 "Host: www.google.com\r\n"
2622 "Connection: keep-alive\r\n"
2623 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2624 };
2625
2626 // Sever accepts the authorization.
2627 MockRead data_reads2[] = {
2628 MockRead("HTTP/1.0 200 OK\r\n"),
2629 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422630 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232631 };
2632
[email protected]31a2bfe2010-02-09 08:03:392633 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2634 data_writes1, arraysize(data_writes1));
2635 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2636 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592637 session_deps.socket_factory.AddSocketDataProvider(&data1);
2638 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232639
2640 TestCompletionCallback callback1;
2641
[email protected]5a1d7ca2010-04-28 20:12:272642 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422643 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232644
2645 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422646 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232647
[email protected]1c773ea12009-04-28 19:58:422648 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232649 EXPECT_FALSE(response == NULL);
2650
2651 // The password prompt info should have been set in
2652 // response->auth_challenge.
2653 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2654
[email protected]71e4573a2009-05-21 22:03:002655 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232656 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2657 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2658
2659 TestCompletionCallback callback2;
2660
2661 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422662 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232663
2664 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422665 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232666
2667 response = trans->GetResponseInfo();
2668 EXPECT_FALSE(response == NULL);
2669 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2670 EXPECT_EQ(100, response->headers->GetContentLength());
2671 }
2672
2673 // ------------------------------------------------------------------------
2674
2675 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
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 // Note that Transaction 1 was at /x/y/z, so this is in the same
2682 // protection space as MyRealm1.
2683 request.url = GURL("http://www.google.com/x/y/a/b");
2684 request.load_flags = 0;
2685
2686 MockWrite data_writes1[] = {
2687 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2688 "Host: www.google.com\r\n"
2689 "Connection: keep-alive\r\n"
2690 // Send preemptive authorization for MyRealm1
2691 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2692 };
2693
2694 // The server didn't like the preemptive authorization, and
2695 // challenges us for a different realm (MyRealm2).
2696 MockRead data_reads1[] = {
2697 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2698 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2699 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422700 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232701 };
2702
2703 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2704 MockWrite data_writes2[] = {
2705 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2706 "Host: www.google.com\r\n"
2707 "Connection: keep-alive\r\n"
2708 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2709 };
2710
2711 // Sever accepts the authorization.
2712 MockRead data_reads2[] = {
2713 MockRead("HTTP/1.0 200 OK\r\n"),
2714 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422715 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232716 };
2717
[email protected]31a2bfe2010-02-09 08:03:392718 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2719 data_writes1, arraysize(data_writes1));
2720 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2721 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592722 session_deps.socket_factory.AddSocketDataProvider(&data1);
2723 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232724
2725 TestCompletionCallback callback1;
2726
[email protected]5a1d7ca2010-04-28 20:12:272727 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422728 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232729
2730 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422731 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232732
[email protected]1c773ea12009-04-28 19:58:422733 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232734 EXPECT_FALSE(response == NULL);
2735
2736 // The password prompt info should have been set in
2737 // response->auth_challenge.
2738 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2739
[email protected]71e4573a2009-05-21 22:03:002740 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232741 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2742 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2743
2744 TestCompletionCallback callback2;
2745
2746 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422747 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232748
2749 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422750 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232751
2752 response = trans->GetResponseInfo();
2753 EXPECT_FALSE(response == NULL);
2754 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2755 EXPECT_EQ(100, response->headers->GetContentLength());
2756 }
2757
2758 // ------------------------------------------------------------------------
2759
2760 // Transaction 3: Resend a request in MyRealm's protection space --
2761 // succeed with preemptive authorization.
2762 {
[email protected]5695b8c2009-09-30 21:36:432763 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232764
[email protected]1c773ea12009-04-28 19:58:422765 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232766 request.method = "GET";
2767 request.url = GURL("http://www.google.com/x/y/z2");
2768 request.load_flags = 0;
2769
2770 MockWrite data_writes1[] = {
2771 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2772 "Host: www.google.com\r\n"
2773 "Connection: keep-alive\r\n"
2774 // The authorization for MyRealm1 gets sent preemptively
2775 // (since the url is in the same protection space)
2776 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2777 };
2778
2779 // Sever accepts the preemptive authorization
2780 MockRead data_reads1[] = {
2781 MockRead("HTTP/1.0 200 OK\r\n"),
2782 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422783 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232784 };
2785
[email protected]31a2bfe2010-02-09 08:03:392786 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2787 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592788 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232789
2790 TestCompletionCallback callback1;
2791
[email protected]5a1d7ca2010-04-28 20:12:272792 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422793 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232794
2795 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422796 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232797
[email protected]1c773ea12009-04-28 19:58:422798 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232799 EXPECT_FALSE(response == NULL);
2800
2801 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2802 EXPECT_EQ(100, response->headers->GetContentLength());
2803 }
2804
2805 // ------------------------------------------------------------------------
2806
2807 // Transaction 4: request another URL in MyRealm (however the
2808 // url is not known to belong to the protection space, so no pre-auth).
2809 {
[email protected]5695b8c2009-09-30 21:36:432810 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232811
[email protected]1c773ea12009-04-28 19:58:422812 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232813 request.method = "GET";
2814 request.url = GURL("http://www.google.com/x/1");
2815 request.load_flags = 0;
2816
2817 MockWrite data_writes1[] = {
2818 MockWrite("GET /x/1 HTTP/1.1\r\n"
2819 "Host: www.google.com\r\n"
2820 "Connection: keep-alive\r\n\r\n"),
2821 };
2822
2823 MockRead data_reads1[] = {
2824 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2825 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2826 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422827 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232828 };
2829
2830 // Resend with authorization from MyRealm's cache.
2831 MockWrite data_writes2[] = {
2832 MockWrite("GET /x/1 HTTP/1.1\r\n"
2833 "Host: www.google.com\r\n"
2834 "Connection: keep-alive\r\n"
2835 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2836 };
2837
2838 // Sever accepts the authorization.
2839 MockRead data_reads2[] = {
2840 MockRead("HTTP/1.0 200 OK\r\n"),
2841 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422842 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232843 };
2844
[email protected]31a2bfe2010-02-09 08:03:392845 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2846 data_writes1, arraysize(data_writes1));
2847 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2848 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592849 session_deps.socket_factory.AddSocketDataProvider(&data1);
2850 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232851
2852 TestCompletionCallback callback1;
2853
[email protected]5a1d7ca2010-04-28 20:12:272854 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422855 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232856
2857 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422858 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232859
[email protected]0757e7702009-03-27 04:00:222860 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2861 TestCompletionCallback callback2;
2862 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422863 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222864 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422865 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222866 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2867
[email protected]1c773ea12009-04-28 19:58:422868 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232869 EXPECT_FALSE(response == NULL);
2870 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2871 EXPECT_EQ(100, response->headers->GetContentLength());
2872 }
2873
2874 // ------------------------------------------------------------------------
2875
2876 // Transaction 5: request a URL in MyRealm, but the server rejects the
2877 // cached identity. Should invalidate and re-prompt.
2878 {
[email protected]5695b8c2009-09-30 21:36:432879 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232880
[email protected]1c773ea12009-04-28 19:58:422881 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232882 request.method = "GET";
2883 request.url = GURL("http://www.google.com/p/q/t");
2884 request.load_flags = 0;
2885
2886 MockWrite data_writes1[] = {
2887 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2888 "Host: www.google.com\r\n"
2889 "Connection: keep-alive\r\n\r\n"),
2890 };
2891
2892 MockRead data_reads1[] = {
2893 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2894 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2895 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422896 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232897 };
2898
2899 // Resend with authorization from cache for MyRealm.
2900 MockWrite data_writes2[] = {
2901 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2902 "Host: www.google.com\r\n"
2903 "Connection: keep-alive\r\n"
2904 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2905 };
2906
2907 // Sever rejects the authorization.
2908 MockRead data_reads2[] = {
2909 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2910 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2911 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422912 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232913 };
2914
2915 // At this point we should prompt for new credentials for MyRealm.
2916 // Restart with username=foo3, password=foo4.
2917 MockWrite data_writes3[] = {
2918 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2919 "Host: www.google.com\r\n"
2920 "Connection: keep-alive\r\n"
2921 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2922 };
2923
2924 // Sever accepts the authorization.
2925 MockRead data_reads3[] = {
2926 MockRead("HTTP/1.0 200 OK\r\n"),
2927 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422928 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232929 };
2930
[email protected]31a2bfe2010-02-09 08:03:392931 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2932 data_writes1, arraysize(data_writes1));
2933 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2934 data_writes2, arraysize(data_writes2));
2935 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2936 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592937 session_deps.socket_factory.AddSocketDataProvider(&data1);
2938 session_deps.socket_factory.AddSocketDataProvider(&data2);
2939 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232940
2941 TestCompletionCallback callback1;
2942
[email protected]5a1d7ca2010-04-28 20:12:272943 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422944 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232945
2946 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422947 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232948
[email protected]0757e7702009-03-27 04:00:222949 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2950 TestCompletionCallback callback2;
2951 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422952 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222953 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422954 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222955 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2956
[email protected]1c773ea12009-04-28 19:58:422957 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232958 EXPECT_FALSE(response == NULL);
2959
2960 // The password prompt info should have been set in
2961 // response->auth_challenge.
2962 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2963
[email protected]71e4573a2009-05-21 22:03:002964 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232965 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2966 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2967
[email protected]0757e7702009-03-27 04:00:222968 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232969
[email protected]0757e7702009-03-27 04:00:222970 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422971 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232972
[email protected]0757e7702009-03-27 04:00:222973 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422974 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232975
2976 response = trans->GetResponseInfo();
2977 EXPECT_FALSE(response == NULL);
2978 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2979 EXPECT_EQ(100, response->headers->GetContentLength());
2980 }
2981}
[email protected]89ceba9a2009-03-21 03:46:062982
2983// Test the ResetStateForRestart() private method.
2984TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2985 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592986 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402987 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432988 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062989
2990 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062991 trans->read_buf_ = new IOBuffer(15);
2992 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572993 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062994
2995 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142996 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572997 response->auth_challenge = new AuthChallengeInfo();
2998 response->ssl_info.cert_status = -15;
2999 response->response_time = base::Time::Now();
3000 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063001
3002 { // Setup state for response_.vary_data
3003 HttpRequestInfo request;
3004 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3005 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573006 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433007 request.extra_headers.SetHeader("Foo", "1");
3008 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573009 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063010 }
3011
3012 // Cause the above state to be reset.
3013 trans->ResetStateForRestart();
3014
3015 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073016 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063017 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573018 EXPECT_EQ(0U, trans->request_headers_.size());
3019 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3020 EXPECT_TRUE(response->headers.get() == NULL);
3021 EXPECT_EQ(false, response->was_cached);
3022 EXPECT_EQ(0, response->ssl_info.cert_status);
3023 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063024}
3025
[email protected]bacff652009-03-31 17:50:333026// Test HTTPS connections to a site with a bad certificate
3027TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593028 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403029 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433030 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333031
3032 HttpRequestInfo request;
3033 request.method = "GET";
3034 request.url = GURL("https://www.google.com/");
3035 request.load_flags = 0;
3036
3037 MockWrite data_writes[] = {
3038 MockWrite("GET / HTTP/1.1\r\n"
3039 "Host: www.google.com\r\n"
3040 "Connection: keep-alive\r\n\r\n"),
3041 };
3042
3043 MockRead data_reads[] = {
3044 MockRead("HTTP/1.0 200 OK\r\n"),
3045 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3046 MockRead("Content-Length: 100\r\n\r\n"),
3047 MockRead(false, OK),
3048 };
3049
[email protected]5ecc992a42009-11-11 01:41:593050 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393051 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3052 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593053 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3054 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333055
[email protected]5ecc992a42009-11-11 01:41:593056 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3057 session_deps.socket_factory.AddSocketDataProvider(&data);
3058 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3059 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333060
3061 TestCompletionCallback callback;
3062
[email protected]5a1d7ca2010-04-28 20:12:273063 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333064 EXPECT_EQ(ERR_IO_PENDING, rv);
3065
3066 rv = callback.WaitForResult();
3067 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3068
3069 rv = trans->RestartIgnoringLastError(&callback);
3070 EXPECT_EQ(ERR_IO_PENDING, rv);
3071
3072 rv = callback.WaitForResult();
3073 EXPECT_EQ(OK, rv);
3074
3075 const HttpResponseInfo* response = trans->GetResponseInfo();
3076
3077 EXPECT_FALSE(response == NULL);
3078 EXPECT_EQ(100, response->headers->GetContentLength());
3079}
3080
3081// Test HTTPS connections to a site with a bad certificate, going through a
3082// proxy
3083TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593084 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333085
3086 HttpRequestInfo request;
3087 request.method = "GET";
3088 request.url = GURL("https://www.google.com/");
3089 request.load_flags = 0;
3090
3091 MockWrite proxy_writes[] = {
3092 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453093 "Host: www.google.com\r\n"
3094 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333095 };
3096
3097 MockRead proxy_reads[] = {
3098 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423099 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333100 };
3101
3102 MockWrite data_writes[] = {
3103 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453104 "Host: www.google.com\r\n"
3105 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333106 MockWrite("GET / HTTP/1.1\r\n"
3107 "Host: www.google.com\r\n"
3108 "Connection: keep-alive\r\n\r\n"),
3109 };
3110
3111 MockRead data_reads[] = {
3112 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3113 MockRead("HTTP/1.0 200 OK\r\n"),
3114 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3115 MockRead("Content-Length: 100\r\n\r\n"),
3116 MockRead(false, OK),
3117 };
3118
[email protected]31a2bfe2010-02-09 08:03:393119 StaticSocketDataProvider ssl_bad_certificate(
3120 proxy_reads, arraysize(proxy_reads),
3121 proxy_writes, arraysize(proxy_writes));
3122 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3123 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593124 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3125 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333126
[email protected]5ecc992a42009-11-11 01:41:593127 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3128 session_deps.socket_factory.AddSocketDataProvider(&data);
3129 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3130 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333131
3132 TestCompletionCallback callback;
3133
3134 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593135 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333136
[email protected]d207a5f2009-06-04 05:28:403137 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433138 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333139
[email protected]5a1d7ca2010-04-28 20:12:273140 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333141 EXPECT_EQ(ERR_IO_PENDING, rv);
3142
3143 rv = callback.WaitForResult();
3144 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3145
3146 rv = trans->RestartIgnoringLastError(&callback);
3147 EXPECT_EQ(ERR_IO_PENDING, rv);
3148
3149 rv = callback.WaitForResult();
3150 EXPECT_EQ(OK, rv);
3151
3152 const HttpResponseInfo* response = trans->GetResponseInfo();
3153
3154 EXPECT_FALSE(response == NULL);
3155 EXPECT_EQ(100, response->headers->GetContentLength());
3156 }
3157}
3158
[email protected]1c773ea12009-04-28 19:58:423159TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593160 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403161 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433162 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423163
3164 HttpRequestInfo request;
3165 request.method = "GET";
3166 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433167 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3168 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423169
3170 MockWrite data_writes[] = {
3171 MockWrite("GET / HTTP/1.1\r\n"
3172 "Host: www.google.com\r\n"
3173 "Connection: keep-alive\r\n"
3174 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3175 };
3176
3177 // Lastly, the server responds with the actual content.
3178 MockRead data_reads[] = {
3179 MockRead("HTTP/1.0 200 OK\r\n"),
3180 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3181 MockRead("Content-Length: 100\r\n\r\n"),
3182 MockRead(false, OK),
3183 };
3184
[email protected]31a2bfe2010-02-09 08:03:393185 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3186 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593187 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423188
3189 TestCompletionCallback callback;
3190
[email protected]5a1d7ca2010-04-28 20:12:273191 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423192 EXPECT_EQ(ERR_IO_PENDING, rv);
3193
3194 rv = callback.WaitForResult();
3195 EXPECT_EQ(OK, rv);
3196}
3197
3198TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593199 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403200 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433201 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423202
3203 HttpRequestInfo request;
3204 request.method = "GET";
3205 request.url = GURL("http://www.google.com/");
3206 request.load_flags = 0;
3207 request.referrer = GURL("http://the.previous.site.com/");
3208
3209 MockWrite data_writes[] = {
3210 MockWrite("GET / HTTP/1.1\r\n"
3211 "Host: www.google.com\r\n"
3212 "Connection: keep-alive\r\n"
3213 "Referer: http://the.previous.site.com/\r\n\r\n"),
3214 };
3215
3216 // Lastly, the server responds with the actual content.
3217 MockRead data_reads[] = {
3218 MockRead("HTTP/1.0 200 OK\r\n"),
3219 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3220 MockRead("Content-Length: 100\r\n\r\n"),
3221 MockRead(false, OK),
3222 };
3223
[email protected]31a2bfe2010-02-09 08:03:393224 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3225 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593226 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423227
3228 TestCompletionCallback callback;
3229
[email protected]5a1d7ca2010-04-28 20:12:273230 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423231 EXPECT_EQ(ERR_IO_PENDING, rv);
3232
3233 rv = callback.WaitForResult();
3234 EXPECT_EQ(OK, rv);
3235}
3236
3237TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593238 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403239 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433240 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423241
3242 HttpRequestInfo request;
3243 request.method = "POST";
3244 request.url = GURL("http://www.google.com/");
3245
3246 MockWrite data_writes[] = {
3247 MockWrite("POST / HTTP/1.1\r\n"
3248 "Host: www.google.com\r\n"
3249 "Connection: keep-alive\r\n"
3250 "Content-Length: 0\r\n\r\n"),
3251 };
3252
3253 // Lastly, the server responds with the actual content.
3254 MockRead data_reads[] = {
3255 MockRead("HTTP/1.0 200 OK\r\n"),
3256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3257 MockRead("Content-Length: 100\r\n\r\n"),
3258 MockRead(false, OK),
3259 };
3260
[email protected]31a2bfe2010-02-09 08:03:393261 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3262 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593263 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423264
3265 TestCompletionCallback callback;
3266
[email protected]5a1d7ca2010-04-28 20:12:273267 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423268 EXPECT_EQ(ERR_IO_PENDING, rv);
3269
3270 rv = callback.WaitForResult();
3271 EXPECT_EQ(OK, rv);
3272}
3273
3274TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593275 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403276 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433277 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423278
3279 HttpRequestInfo request;
3280 request.method = "PUT";
3281 request.url = GURL("http://www.google.com/");
3282
3283 MockWrite data_writes[] = {
3284 MockWrite("PUT / HTTP/1.1\r\n"
3285 "Host: www.google.com\r\n"
3286 "Connection: keep-alive\r\n"
3287 "Content-Length: 0\r\n\r\n"),
3288 };
3289
3290 // Lastly, the server responds with the actual content.
3291 MockRead data_reads[] = {
3292 MockRead("HTTP/1.0 200 OK\r\n"),
3293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3294 MockRead("Content-Length: 100\r\n\r\n"),
3295 MockRead(false, OK),
3296 };
3297
[email protected]31a2bfe2010-02-09 08:03:393298 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3299 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593300 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423301
3302 TestCompletionCallback callback;
3303
[email protected]5a1d7ca2010-04-28 20:12:273304 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423305 EXPECT_EQ(ERR_IO_PENDING, rv);
3306
3307 rv = callback.WaitForResult();
3308 EXPECT_EQ(OK, rv);
3309}
3310
3311TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593312 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403313 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433314 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423315
3316 HttpRequestInfo request;
3317 request.method = "HEAD";
3318 request.url = GURL("http://www.google.com/");
3319
3320 MockWrite data_writes[] = {
3321 MockWrite("HEAD / HTTP/1.1\r\n"
3322 "Host: www.google.com\r\n"
3323 "Connection: keep-alive\r\n"
3324 "Content-Length: 0\r\n\r\n"),
3325 };
3326
3327 // Lastly, the server responds with the actual content.
3328 MockRead data_reads[] = {
3329 MockRead("HTTP/1.0 200 OK\r\n"),
3330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3331 MockRead("Content-Length: 100\r\n\r\n"),
3332 MockRead(false, OK),
3333 };
3334
[email protected]31a2bfe2010-02-09 08:03:393335 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3336 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593337 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423338
3339 TestCompletionCallback callback;
3340
[email protected]5a1d7ca2010-04-28 20:12:273341 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423342 EXPECT_EQ(ERR_IO_PENDING, rv);
3343
3344 rv = callback.WaitForResult();
3345 EXPECT_EQ(OK, rv);
3346}
3347
3348TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593349 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403350 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433351 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423352
3353 HttpRequestInfo request;
3354 request.method = "GET";
3355 request.url = GURL("http://www.google.com/");
3356 request.load_flags = LOAD_BYPASS_CACHE;
3357
3358 MockWrite data_writes[] = {
3359 MockWrite("GET / HTTP/1.1\r\n"
3360 "Host: www.google.com\r\n"
3361 "Connection: keep-alive\r\n"
3362 "Pragma: no-cache\r\n"
3363 "Cache-Control: no-cache\r\n\r\n"),
3364 };
3365
3366 // Lastly, the server responds with the actual content.
3367 MockRead data_reads[] = {
3368 MockRead("HTTP/1.0 200 OK\r\n"),
3369 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3370 MockRead("Content-Length: 100\r\n\r\n"),
3371 MockRead(false, OK),
3372 };
3373
[email protected]31a2bfe2010-02-09 08:03:393374 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3375 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593376 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423377
3378 TestCompletionCallback callback;
3379
[email protected]5a1d7ca2010-04-28 20:12:273380 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423381 EXPECT_EQ(ERR_IO_PENDING, rv);
3382
3383 rv = callback.WaitForResult();
3384 EXPECT_EQ(OK, rv);
3385}
3386
3387TEST_F(HttpNetworkTransactionTest,
3388 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593389 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403390 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433391 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423392
3393 HttpRequestInfo request;
3394 request.method = "GET";
3395 request.url = GURL("http://www.google.com/");
3396 request.load_flags = LOAD_VALIDATE_CACHE;
3397
3398 MockWrite data_writes[] = {
3399 MockWrite("GET / HTTP/1.1\r\n"
3400 "Host: www.google.com\r\n"
3401 "Connection: keep-alive\r\n"
3402 "Cache-Control: max-age=0\r\n\r\n"),
3403 };
3404
3405 // Lastly, the server responds with the actual content.
3406 MockRead data_reads[] = {
3407 MockRead("HTTP/1.0 200 OK\r\n"),
3408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3409 MockRead("Content-Length: 100\r\n\r\n"),
3410 MockRead(false, OK),
3411 };
3412
[email protected]31a2bfe2010-02-09 08:03:393413 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3414 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593415 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423416
3417 TestCompletionCallback callback;
3418
[email protected]5a1d7ca2010-04-28 20:12:273419 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423420 EXPECT_EQ(ERR_IO_PENDING, rv);
3421
3422 rv = callback.WaitForResult();
3423 EXPECT_EQ(OK, rv);
3424}
3425
3426TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593427 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403428 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433429 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423430
3431 HttpRequestInfo request;
3432 request.method = "GET";
3433 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433434 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423435
3436 MockWrite data_writes[] = {
3437 MockWrite("GET / HTTP/1.1\r\n"
3438 "Host: www.google.com\r\n"
3439 "Connection: keep-alive\r\n"
3440 "FooHeader: Bar\r\n\r\n"),
3441 };
3442
3443 // Lastly, the server responds with the actual content.
3444 MockRead data_reads[] = {
3445 MockRead("HTTP/1.0 200 OK\r\n"),
3446 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3447 MockRead("Content-Length: 100\r\n\r\n"),
3448 MockRead(false, OK),
3449 };
3450
[email protected]31a2bfe2010-02-09 08:03:393451 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3452 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593453 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423454
3455 TestCompletionCallback callback;
3456
[email protected]5a1d7ca2010-04-28 20:12:273457 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423458 EXPECT_EQ(ERR_IO_PENDING, rv);
3459
3460 rv = callback.WaitForResult();
3461 EXPECT_EQ(OK, rv);
3462}
3463
[email protected]270c6412010-03-29 22:02:473464TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3465 SessionDependencies session_deps;
3466 scoped_ptr<HttpTransaction> trans(
3467 new HttpNetworkTransaction(CreateSession(&session_deps)));
3468
3469 HttpRequestInfo request;
3470 request.method = "GET";
3471 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433472 request.extra_headers.SetHeader("referer", "www.foo.com");
3473 request.extra_headers.SetHeader("hEllo", "Kitty");
3474 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473475
3476 MockWrite data_writes[] = {
3477 MockWrite("GET / HTTP/1.1\r\n"
3478 "Host: www.google.com\r\n"
3479 "Connection: keep-alive\r\n"
3480 "hEllo: Kitty\r\n"
3481 "FoO: bar\r\n\r\n"),
3482 };
3483
3484 // Lastly, the server responds with the actual content.
3485 MockRead data_reads[] = {
3486 MockRead("HTTP/1.0 200 OK\r\n"),
3487 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3488 MockRead("Content-Length: 100\r\n\r\n"),
3489 MockRead(false, OK),
3490 };
3491
3492 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3493 data_writes, arraysize(data_writes));
3494 session_deps.socket_factory.AddSocketDataProvider(&data);
3495
3496 TestCompletionCallback callback;
3497
[email protected]5a1d7ca2010-04-28 20:12:273498 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473499 EXPECT_EQ(ERR_IO_PENDING, rv);
3500
3501 rv = callback.WaitForResult();
3502 EXPECT_EQ(OK, rv);
3503}
3504
[email protected]3cd17242009-06-23 02:59:023505TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093506 SessionDependencies session_deps(
3507 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023508
3509 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433510 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023511
3512 HttpRequestInfo request;
3513 request.method = "GET";
3514 request.url = GURL("http://www.google.com/");
3515 request.load_flags = 0;
3516
3517 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3518 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3519
3520 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353521 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023522 MockWrite("GET / HTTP/1.1\r\n"
3523 "Host: www.google.com\r\n"
3524 "Connection: keep-alive\r\n\r\n")
3525 };
3526
3527 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593528 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023529 MockRead("HTTP/1.0 200 OK\r\n"),
3530 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3531 MockRead("Payload"),
3532 MockRead(false, OK)
3533 };
3534
[email protected]31a2bfe2010-02-09 08:03:393535 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3536 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593537 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023538
3539 TestCompletionCallback callback;
3540
[email protected]5a1d7ca2010-04-28 20:12:273541 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023542 EXPECT_EQ(ERR_IO_PENDING, rv);
3543
3544 rv = callback.WaitForResult();
3545 EXPECT_EQ(OK, rv);
3546
3547 const HttpResponseInfo* response = trans->GetResponseInfo();
3548 EXPECT_FALSE(response == NULL);
3549
3550 std::string response_text;
3551 rv = ReadTransaction(trans.get(), &response_text);
3552 EXPECT_EQ(OK, rv);
3553 EXPECT_EQ("Payload", response_text);
3554}
3555
3556TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093557 SessionDependencies session_deps(
3558 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023559
3560 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433561 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023562
3563 HttpRequestInfo request;
3564 request.method = "GET";
3565 request.url = GURL("https://www.google.com/");
3566 request.load_flags = 0;
3567
3568 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3569 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3570
3571 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353572 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3573 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023574 MockWrite("GET / HTTP/1.1\r\n"
3575 "Host: www.google.com\r\n"
3576 "Connection: keep-alive\r\n\r\n")
3577 };
3578
3579 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353580 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3581 arraysize(read_buffer)),
3582 MockRead("HTTP/1.0 200 OK\r\n"),
3583 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3584 MockRead("Payload"),
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]e0c27be2009-07-15 13:09:353591
[email protected]5ecc992a42009-11-11 01:41:593592 SSLSocketDataProvider ssl(true, OK);
3593 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353594
3595 TestCompletionCallback callback;
3596
[email protected]5a1d7ca2010-04-28 20:12:273597 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353598 EXPECT_EQ(ERR_IO_PENDING, rv);
3599
3600 rv = callback.WaitForResult();
3601 EXPECT_EQ(OK, rv);
3602
3603 const HttpResponseInfo* response = trans->GetResponseInfo();
3604 EXPECT_FALSE(response == NULL);
3605
3606 std::string response_text;
3607 rv = ReadTransaction(trans.get(), &response_text);
3608 EXPECT_EQ(OK, rv);
3609 EXPECT_EQ("Payload", response_text);
3610}
3611
3612TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093613 SessionDependencies session_deps(
3614 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353615
3616 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433617 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353618
3619 HttpRequestInfo request;
3620 request.method = "GET";
3621 request.url = GURL("http://www.google.com/");
3622 request.load_flags = 0;
3623
3624 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3625 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373626 const char kSOCKS5OkRequest[] = {
3627 0x05, // Version
3628 0x01, // Command (CONNECT)
3629 0x00, // Reserved.
3630 0x03, // Address type (DOMAINNAME).
3631 0x0E, // Length of domain (14)
3632 // Domain string:
3633 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3634 0x00, 0x50, // 16-bit port (80)
3635 };
[email protected]e0c27be2009-07-15 13:09:353636 const char kSOCKS5OkResponse[] =
3637 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3638
3639 MockWrite data_writes[] = {
3640 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3641 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3642 MockWrite("GET / HTTP/1.1\r\n"
3643 "Host: www.google.com\r\n"
3644 "Connection: keep-alive\r\n\r\n")
3645 };
3646
3647 MockRead data_reads[] = {
3648 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3649 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3650 MockRead("HTTP/1.0 200 OK\r\n"),
3651 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3652 MockRead("Payload"),
3653 MockRead(false, OK)
3654 };
3655
[email protected]31a2bfe2010-02-09 08:03:393656 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3657 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593658 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353659
3660 TestCompletionCallback callback;
3661
[email protected]5a1d7ca2010-04-28 20:12:273662 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353663 EXPECT_EQ(ERR_IO_PENDING, rv);
3664
3665 rv = callback.WaitForResult();
3666 EXPECT_EQ(OK, rv);
3667
3668 const HttpResponseInfo* response = trans->GetResponseInfo();
3669 EXPECT_FALSE(response == NULL);
3670
3671 std::string response_text;
3672 rv = ReadTransaction(trans.get(), &response_text);
3673 EXPECT_EQ(OK, rv);
3674 EXPECT_EQ("Payload", response_text);
3675}
3676
3677TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093678 SessionDependencies session_deps(
3679 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353680
3681 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433682 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353683
3684 HttpRequestInfo request;
3685 request.method = "GET";
3686 request.url = GURL("https://www.google.com/");
3687 request.load_flags = 0;
3688
3689 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3690 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373691 const unsigned char kSOCKS5OkRequest[] = {
3692 0x05, // Version
3693 0x01, // Command (CONNECT)
3694 0x00, // Reserved.
3695 0x03, // Address type (DOMAINNAME).
3696 0x0E, // Length of domain (14)
3697 // Domain string:
3698 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3699 0x01, 0xBB, // 16-bit port (443)
3700 };
3701
[email protected]e0c27be2009-07-15 13:09:353702 const char kSOCKS5OkResponse[] =
3703 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3704
3705 MockWrite data_writes[] = {
3706 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3707 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3708 arraysize(kSOCKS5OkRequest)),
3709 MockWrite("GET / HTTP/1.1\r\n"
3710 "Host: www.google.com\r\n"
3711 "Connection: keep-alive\r\n\r\n")
3712 };
3713
3714 MockRead data_reads[] = {
3715 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3716 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023717 MockRead("HTTP/1.0 200 OK\r\n"),
3718 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3719 MockRead("Payload"),
3720 MockRead(false, OK)
3721 };
3722
[email protected]31a2bfe2010-02-09 08:03:393723 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3724 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593725 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023726
[email protected]5ecc992a42009-11-11 01:41:593727 SSLSocketDataProvider ssl(true, OK);
3728 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023729
3730 TestCompletionCallback callback;
3731
[email protected]5a1d7ca2010-04-28 20:12:273732 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023733 EXPECT_EQ(ERR_IO_PENDING, rv);
3734
3735 rv = callback.WaitForResult();
3736 EXPECT_EQ(OK, rv);
3737
3738 const HttpResponseInfo* response = trans->GetResponseInfo();
3739 EXPECT_FALSE(response == NULL);
3740
3741 std::string response_text;
3742 rv = ReadTransaction(trans.get(), &response_text);
3743 EXPECT_EQ(OK, rv);
3744 EXPECT_EQ("Payload", response_text);
3745}
3746
[email protected]04e5be32009-06-26 20:00:313747// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063748
3749struct GroupNameTest {
3750 std::string proxy_server;
3751 std::string url;
3752 std::string expected_group_name;
3753};
3754
3755scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3756 const std::string& proxy_server) {
3757 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3758 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3759
3760 HttpAlternateProtocols* alternate_protocols =
3761 session->mutable_alternate_protocols();
3762 alternate_protocols->SetAlternateProtocolFor(
3763 HostPortPair("host.with.alternate", 80), 443,
3764 HttpAlternateProtocols::NPN_SPDY_1);
3765
3766 return session;
3767}
3768
3769int GroupNameTransactionHelper(
3770 const std::string& url,
3771 const scoped_refptr<HttpNetworkSession>& session) {
3772 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3773
3774 HttpRequestInfo request;
3775 request.method = "GET";
3776 request.url = GURL(url);
3777 request.load_flags = 0;
3778
3779 TestCompletionCallback callback;
3780
3781 // We do not complete this request, the dtor will clean the transaction up.
3782 return trans->Start(&request, &callback, BoundNetLog());
3783}
3784
3785TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
3786 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:313787 {
[email protected]2d731a32010-04-29 01:04:063788 "", // unused
[email protected]04e5be32009-06-26 20:00:313789 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:543790 "www.google.com:80",
3791 },
3792 {
[email protected]2d731a32010-04-29 01:04:063793 "", // unused
[email protected]2ff8b312010-04-26 22:20:543794 "http://[2001:1418:13:1::25]/direct",
3795 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:313796 },
[email protected]04e5be32009-06-26 20:00:313797
3798 // SSL Tests
3799 {
[email protected]2d731a32010-04-29 01:04:063800 "", // unused
[email protected]04e5be32009-06-26 20:00:313801 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:023802 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313803 },
3804 {
[email protected]2d731a32010-04-29 01:04:063805 "", // unused
3806 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:023807 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:313808 },
3809 {
[email protected]2d731a32010-04-29 01:04:063810 "", // unused
[email protected]2ff8b312010-04-26 22:20:543811 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:023812 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:543813 },
[email protected]2d731a32010-04-29 01:04:063814 };
[email protected]2ff8b312010-04-26 22:20:543815
[email protected]2d731a32010-04-29 01:04:063816 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3817
3818 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3819 scoped_refptr<HttpNetworkSession> session(
3820 SetupSessionForGroupNameTests(tests[i].proxy_server));
3821
3822 HttpNetworkSessionPeer peer(session);
3823 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3824 new CaptureGroupNameTCPSocketPool(session.get()));
3825 peer.SetTCPSocketPool(tcp_conn_pool);
3826
3827 EXPECT_EQ(ERR_IO_PENDING,
3828 GroupNameTransactionHelper(tests[i].url, session));
3829 EXPECT_EQ(tests[i].expected_group_name,
3830 tcp_conn_pool->last_group_name_received());
3831 }
3832
3833 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3834}
3835
3836TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
3837 const GroupNameTest tests[] = {
3838 {
3839 "http_proxy",
3840 "http://www.google.com/http_proxy_normal",
3841 "www.google.com:80",
3842 },
3843
3844 // SSL Tests
3845 {
3846 "http_proxy",
3847 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:023848 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:063849 },
3850
[email protected]9faeded92010-04-29 20:03:053851 {
3852 "http_proxy",
3853 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:023854 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:053855 },
[email protected]2d731a32010-04-29 01:04:063856 };
3857
3858 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3859
3860 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3861 scoped_refptr<HttpNetworkSession> session(
3862 SetupSessionForGroupNameTests(tests[i].proxy_server));
3863
3864 HttpNetworkSessionPeer peer(session);
3865
3866 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
3867 new CaptureGroupNameTCPSocketPool(session.get()));
3868 peer.SetSocketPoolForHTTPProxy(
3869 HostPortPair("http_proxy", 80), http_proxy_pool);
3870
3871 EXPECT_EQ(ERR_IO_PENDING,
3872 GroupNameTransactionHelper(tests[i].url, session));
3873 EXPECT_EQ(tests[i].expected_group_name,
3874 http_proxy_pool->last_group_name_received());
3875 }
3876
3877 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3878}
3879
3880TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
3881 const GroupNameTest tests[] = {
3882 {
3883 "socks4://socks_proxy:1080",
3884 "http://www.google.com/socks4_direct",
3885 "socks4/www.google.com:80",
3886 },
3887 {
3888 "socks5://socks_proxy:1080",
3889 "http://www.google.com/socks5_direct",
3890 "socks5/www.google.com:80",
3891 },
3892
3893 // SSL Tests
3894 {
3895 "socks4://socks_proxy:1080",
3896 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:023897 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:063898 },
3899 {
3900 "socks5://socks_proxy:1080",
3901 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:023902 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:063903 },
3904
[email protected]9faeded92010-04-29 20:03:053905 {
3906 "socks4://socks_proxy:1080",
3907 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:023908 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:053909 },
[email protected]04e5be32009-06-26 20:00:313910 };
3911
[email protected]2ff8b312010-04-26 22:20:543912 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3913
[email protected]04e5be32009-06-26 20:00:313914 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:063915 scoped_refptr<HttpNetworkSession> session(
3916 SetupSessionForGroupNameTests(tests[i].proxy_server));
3917 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:313918
[email protected]a796bcec2010-03-22 17:17:263919 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:063920 new CaptureGroupNameSOCKSSocketPool(session.get()));
3921 peer.SetSocketPoolForSOCKSProxy(
3922 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:313923
[email protected]5695b8c2009-09-30 21:36:433924 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313925
[email protected]2d731a32010-04-29 01:04:063926 EXPECT_EQ(ERR_IO_PENDING,
3927 GroupNameTransactionHelper(tests[i].url, session));
3928 EXPECT_EQ(tests[i].expected_group_name,
3929 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:313930 }
[email protected]2ff8b312010-04-26 22:20:543931
3932 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:313933}
3934
[email protected]9172a982009-06-06 00:30:253935TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543936 SessionDependencies session_deps(
3937 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323938
[email protected]69719062010-01-05 20:09:213939 // This simulates failure resolving all hostnames; that means we will fail
3940 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323941 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3942
[email protected]9172a982009-06-06 00:30:253943 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433944 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253945
3946 HttpRequestInfo request;
3947 request.method = "GET";
3948 request.url = GURL("http://www.google.com/");
3949
3950 TestCompletionCallback callback;
3951
[email protected]5a1d7ca2010-04-28 20:12:273952 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:253953 EXPECT_EQ(ERR_IO_PENDING, rv);
3954
[email protected]9172a982009-06-06 00:30:253955 rv = callback.WaitForResult();
3956 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3957}
3958
[email protected]f3e6c1e2009-06-15 20:52:123959// Host resolution observer used by
3960// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3961// resovle requests are issued with a referrer of |expected_referrer|.
3962class ResolutionReferrerObserver : public HostResolver::Observer {
3963 public:
3964 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3965 : expected_referrer_(expected_referrer),
3966 called_start_with_referrer_(false),
3967 called_finish_with_referrer_(false) {
3968 }
3969
3970 virtual void OnStartResolution(int id,
3971 const HostResolver::RequestInfo& info) {
3972 if (info.referrer() == expected_referrer_)
3973 called_start_with_referrer_ = true;
3974 }
3975
3976 virtual void OnFinishResolutionWithStatus(
3977 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3978 if (info.referrer() == expected_referrer_)
3979 called_finish_with_referrer_ = true;
3980 }
3981
[email protected]eb255d32009-06-17 02:11:033982 virtual void OnCancelResolution(int id,
3983 const HostResolver::RequestInfo& info ) {
3984 FAIL() << "Should not be cancelling any requests!";
3985 }
3986
[email protected]f3e6c1e2009-06-15 20:52:123987 bool did_complete_with_expected_referrer() const {
3988 return called_start_with_referrer_ && called_finish_with_referrer_;
3989 }
3990
3991 private:
3992 GURL expected_referrer_;
3993 bool called_start_with_referrer_;
3994 bool called_finish_with_referrer_;
3995
3996 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3997};
3998
3999// Make sure that when HostResolver::Resolve() is invoked, it passes through
4000// the "referrer". This is depended on by the DNS prefetch observer.
4001TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4002 GURL referrer = GURL("http://expected-referrer/");
4003 EXPECT_TRUE(referrer.is_valid());
4004 ResolutionReferrerObserver resolution_observer(referrer);
4005
4006 SessionDependencies session_deps;
4007 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434008 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124009
4010 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144011 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124012
4013 // Connect up a mock socket which will fail when reading.
4014 MockRead data_reads[] = {
4015 MockRead(false, ERR_FAILED),
4016 };
[email protected]31a2bfe2010-02-09 08:03:394017 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594018 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124019
4020 // Issue a request, containing an HTTP referrer.
4021 HttpRequestInfo request;
4022 request.method = "GET";
4023 request.referrer = referrer;
4024 request.url = GURL("http://www.google.com/");
4025
4026 // Run the request until it fails reading from the socket.
4027 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274028 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124029 EXPECT_EQ(ERR_IO_PENDING, rv);
4030 rv = callback.WaitForResult();
4031 EXPECT_EQ(ERR_FAILED, rv);
4032
4033 // Check that the host resolution observer saw |referrer|.
4034 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4035}
4036
[email protected]3b9cca42009-06-16 01:08:284037// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
4038// host cache is bypassed.
4039TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
4040 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324041
[email protected]a2c2fb92009-07-18 07:31:044042 // Select a host resolver that does caching.
4043 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324044
[email protected]3b9cca42009-06-16 01:08:284045 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434046 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284047
4048 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4049 // a synchronous lookup.)
4050 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144051 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464052 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274053 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284054 EXPECT_EQ(OK, rv);
4055
4056 // Verify that it was added to host cache, by doing a subsequent async lookup
4057 // and confirming it completes synchronously.
4058 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464059 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284060 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274061 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324062 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284063
4064 // Inject a failure the next time that "www.google.com" is resolved. This way
4065 // we can tell if the next lookup hit the cache, or the "network".
4066 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324067 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284068
4069 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4070 // first read -- this won't be reached as the host resolution will fail first.
4071 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394072 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594073 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284074
4075 // Issue a request, asking to bypass the cache(s).
4076 HttpRequestInfo request;
4077 request.method = "GET";
4078 request.load_flags = LOAD_BYPASS_CACHE;
4079 request.url = GURL("http://www.google.com/");
4080
4081 // Run the request.
4082 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274083 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284084 ASSERT_EQ(ERR_IO_PENDING, rv);
4085 rv = callback.WaitForResult();
4086
4087 // If we bypassed the cache, we would have gotten a failure while resolving
4088 // "www.google.com".
4089 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4090}
4091
[email protected]0877e3d2009-10-17 22:29:574092// Make sure we can handle an error when writing the request.
4093TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4094 SessionDependencies session_deps;
4095 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4096
4097 HttpRequestInfo request;
4098 request.method = "GET";
4099 request.url = GURL("http://www.foo.com/");
4100 request.load_flags = 0;
4101
4102 MockWrite write_failure[] = {
4103 MockWrite(true, ERR_CONNECTION_RESET),
4104 };
[email protected]31a2bfe2010-02-09 08:03:394105 StaticSocketDataProvider data(NULL, 0,
4106 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594107 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574108
4109 TestCompletionCallback callback;
4110
4111 scoped_ptr<HttpTransaction> trans(
4112 new HttpNetworkTransaction(CreateSession(&session_deps)));
4113
[email protected]5a1d7ca2010-04-28 20:12:274114 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574115 EXPECT_EQ(ERR_IO_PENDING, rv);
4116
4117 rv = callback.WaitForResult();
4118 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4119}
4120
4121// Check that a connection closed after the start of the headers finishes ok.
4122TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4123 SessionDependencies session_deps;
4124 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4125
4126 HttpRequestInfo request;
4127 request.method = "GET";
4128 request.url = GURL("http://www.foo.com/");
4129 request.load_flags = 0;
4130
4131 MockRead data_reads[] = {
4132 MockRead("HTTP/1."),
4133 MockRead(false, OK),
4134 };
4135
[email protected]31a2bfe2010-02-09 08:03:394136 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594137 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574138
4139 TestCompletionCallback callback;
4140
4141 scoped_ptr<HttpTransaction> trans(
4142 new HttpNetworkTransaction(CreateSession(&session_deps)));
4143
[email protected]5a1d7ca2010-04-28 20:12:274144 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574145 EXPECT_EQ(ERR_IO_PENDING, rv);
4146
4147 rv = callback.WaitForResult();
4148 EXPECT_EQ(OK, rv);
4149
4150 const HttpResponseInfo* response = trans->GetResponseInfo();
4151 EXPECT_TRUE(response != NULL);
4152
4153 EXPECT_TRUE(response->headers != NULL);
4154 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4155
4156 std::string response_data;
4157 rv = ReadTransaction(trans.get(), &response_data);
4158 EXPECT_EQ(OK, rv);
4159 EXPECT_EQ("", response_data);
4160}
4161
4162// Make sure that a dropped connection while draining the body for auth
4163// restart does the right thing.
4164TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4165 SessionDependencies session_deps;
4166 scoped_ptr<HttpTransaction> trans(
4167 new HttpNetworkTransaction(CreateSession(&session_deps)));
4168
4169 HttpRequestInfo request;
4170 request.method = "GET";
4171 request.url = GURL("http://www.google.com/");
4172 request.load_flags = 0;
4173
4174 MockWrite data_writes1[] = {
4175 MockWrite("GET / HTTP/1.1\r\n"
4176 "Host: www.google.com\r\n"
4177 "Connection: keep-alive\r\n\r\n"),
4178 };
4179
4180 MockRead data_reads1[] = {
4181 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4182 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4183 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4184 MockRead("Content-Length: 14\r\n\r\n"),
4185 MockRead("Unauth"),
4186 MockRead(true, ERR_CONNECTION_RESET),
4187 };
4188
[email protected]31a2bfe2010-02-09 08:03:394189 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4190 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594191 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574192
4193 // After calling trans->RestartWithAuth(), this is the request we should
4194 // be issuing -- the final header line contains the credentials.
4195 MockWrite data_writes2[] = {
4196 MockWrite("GET / HTTP/1.1\r\n"
4197 "Host: www.google.com\r\n"
4198 "Connection: keep-alive\r\n"
4199 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4200 };
4201
4202 // Lastly, the server responds with the actual content.
4203 MockRead data_reads2[] = {
4204 MockRead("HTTP/1.1 200 OK\r\n"),
4205 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4206 MockRead("Content-Length: 100\r\n\r\n"),
4207 MockRead(false, OK),
4208 };
4209
[email protected]31a2bfe2010-02-09 08:03:394210 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4211 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594212 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574213
4214 TestCompletionCallback callback1;
4215
[email protected]5a1d7ca2010-04-28 20:12:274216 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574217 EXPECT_EQ(ERR_IO_PENDING, rv);
4218
4219 rv = callback1.WaitForResult();
4220 EXPECT_EQ(OK, rv);
4221
4222 const HttpResponseInfo* response = trans->GetResponseInfo();
4223 EXPECT_FALSE(response == NULL);
4224
4225 // The password prompt info should have been set in response->auth_challenge.
4226 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4227
4228 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4229 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4230 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4231
4232 TestCompletionCallback callback2;
4233
4234 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4235 EXPECT_EQ(ERR_IO_PENDING, rv);
4236
4237 rv = callback2.WaitForResult();
4238 EXPECT_EQ(OK, rv);
4239
4240 response = trans->GetResponseInfo();
4241 EXPECT_FALSE(response == NULL);
4242 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4243 EXPECT_EQ(100, response->headers->GetContentLength());
4244}
4245
4246// Test HTTPS connections going through a proxy that sends extra data.
4247TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4248 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4249
4250 HttpRequestInfo request;
4251 request.method = "GET";
4252 request.url = GURL("https://www.google.com/");
4253 request.load_flags = 0;
4254
4255 MockRead proxy_reads[] = {
4256 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4257 MockRead(false, OK)
4258 };
4259
[email protected]31a2bfe2010-02-09 08:03:394260 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594261 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574262
[email protected]5ecc992a42009-11-11 01:41:594263 session_deps.socket_factory.AddSocketDataProvider(&data);
4264 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574265
4266 TestCompletionCallback callback;
4267
4268 session_deps.socket_factory.ResetNextMockIndexes();
4269
4270 scoped_ptr<HttpTransaction> trans(
4271 new HttpNetworkTransaction(CreateSession(&session_deps)));
4272
[email protected]5a1d7ca2010-04-28 20:12:274273 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574274 EXPECT_EQ(ERR_IO_PENDING, rv);
4275
4276 rv = callback.WaitForResult();
4277 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4278}
4279
[email protected]e22e1362009-11-23 21:31:124280TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464281 SessionDependencies session_deps;
4282 scoped_ptr<HttpTransaction> trans(
4283 new HttpNetworkTransaction(CreateSession(&session_deps)));
4284
4285 HttpRequestInfo request;
4286 request.method = "GET";
4287 request.url = GURL("http://www.google.com/");
4288 request.load_flags = 0;
4289
[email protected]e22e1362009-11-23 21:31:124290 MockRead data_reads[] = {
4291 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4292 MockRead(false, OK),
4293 };
[email protected]9492e4a2010-02-24 00:58:464294
4295 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4296 session_deps.socket_factory.AddSocketDataProvider(&data);
4297
4298 TestCompletionCallback callback;
4299
[email protected]5a1d7ca2010-04-28 20:12:274300 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464301 EXPECT_EQ(ERR_IO_PENDING, rv);
4302
4303 EXPECT_EQ(OK, callback.WaitForResult());
4304
4305 const HttpResponseInfo* response = trans->GetResponseInfo();
4306 EXPECT_TRUE(response != NULL);
4307
4308 EXPECT_TRUE(response->headers != NULL);
4309 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4310
4311 std::string response_data;
4312 rv = ReadTransaction(trans.get(), &response_data);
4313 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124314}
4315
[email protected]95d88ffe2010-02-04 21:25:334316TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4317 SessionDependencies session_deps;
4318 scoped_ptr<HttpTransaction> trans(
4319 new HttpNetworkTransaction(CreateSession(&session_deps)));
4320
4321 HttpRequestInfo request;
4322 request.method = "POST";
4323 request.url = GURL("http://www.google.com/upload");
4324 request.upload_data = new UploadData;
4325 request.load_flags = 0;
4326
4327 FilePath temp_file_path;
4328 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4329 const uint64 kFakeSize = 100000; // file is actually blank
4330
4331 std::vector<UploadData::Element> elements;
4332 UploadData::Element element;
4333 element.SetToFilePath(temp_file_path);
4334 element.SetContentLength(kFakeSize);
4335 elements.push_back(element);
4336 request.upload_data->set_elements(elements);
4337 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4338
4339 MockRead data_reads[] = {
4340 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4341 MockRead("hello world"),
4342 MockRead(false, OK),
4343 };
[email protected]31a2bfe2010-02-09 08:03:394344 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334345 session_deps.socket_factory.AddSocketDataProvider(&data);
4346
4347 TestCompletionCallback callback;
4348
[email protected]5a1d7ca2010-04-28 20:12:274349 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334350 EXPECT_EQ(ERR_IO_PENDING, rv);
4351
4352 rv = callback.WaitForResult();
4353 EXPECT_EQ(OK, rv);
4354
4355 const HttpResponseInfo* response = trans->GetResponseInfo();
4356 EXPECT_TRUE(response != NULL);
4357
4358 EXPECT_TRUE(response->headers != NULL);
4359 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4360
4361 std::string response_data;
4362 rv = ReadTransaction(trans.get(), &response_data);
4363 EXPECT_EQ(OK, rv);
4364 EXPECT_EQ("hello world", response_data);
4365
4366 file_util::Delete(temp_file_path, false);
4367}
4368
[email protected]6624b4622010-03-29 19:58:364369TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4370 // If we try to upload an unreadable file, the network stack should report
4371 // the file size as zero and upload zero bytes for that file.
4372 SessionDependencies session_deps;
4373 scoped_ptr<HttpTransaction> trans(
4374 new HttpNetworkTransaction(CreateSession(&session_deps)));
4375
4376 FilePath temp_file;
4377 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4378 std::string temp_file_content("Unreadable file.");
4379 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4380 temp_file_content.length()));
4381 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4382
4383 HttpRequestInfo request;
4384 request.method = "POST";
4385 request.url = GURL("http://www.google.com/upload");
4386 request.upload_data = new UploadData;
4387 request.load_flags = 0;
4388
4389 std::vector<UploadData::Element> elements;
4390 UploadData::Element element;
4391 element.SetToFilePath(temp_file);
4392 elements.push_back(element);
4393 request.upload_data->set_elements(elements);
4394
4395 MockRead data_reads[] = {
4396 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4397 MockRead(false, OK),
4398 };
4399 MockWrite data_writes[] = {
4400 MockWrite("POST /upload HTTP/1.1\r\n"
4401 "Host: www.google.com\r\n"
4402 "Connection: keep-alive\r\n"
4403 "Content-Length: 0\r\n\r\n"),
4404 MockWrite(false, OK),
4405 };
4406 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4407 arraysize(data_writes));
4408 session_deps.socket_factory.AddSocketDataProvider(&data);
4409
4410 TestCompletionCallback callback;
4411
[email protected]5a1d7ca2010-04-28 20:12:274412 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364413 EXPECT_EQ(ERR_IO_PENDING, rv);
4414
4415 rv = callback.WaitForResult();
4416 EXPECT_EQ(OK, rv);
4417
4418 const HttpResponseInfo* response = trans->GetResponseInfo();
4419 EXPECT_TRUE(response != NULL);
4420 EXPECT_TRUE(response->headers != NULL);
4421 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4422
4423 file_util::Delete(temp_file, false);
4424}
4425
4426TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4427 SessionDependencies session_deps;
4428 scoped_ptr<HttpTransaction> trans(
4429 new HttpNetworkTransaction(CreateSession(&session_deps)));
4430
4431 FilePath temp_file;
4432 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4433 std::string temp_file_contents("Unreadable file.");
4434 std::string unreadable_contents(temp_file_contents.length(), '\0');
4435 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4436 temp_file_contents.length()));
4437
4438 HttpRequestInfo request;
4439 request.method = "POST";
4440 request.url = GURL("http://www.google.com/upload");
4441 request.upload_data = new UploadData;
4442 request.load_flags = 0;
4443
4444 std::vector<UploadData::Element> elements;
4445 UploadData::Element element;
4446 element.SetToFilePath(temp_file);
4447 elements.push_back(element);
4448 request.upload_data->set_elements(elements);
4449
4450 MockRead data_reads[] = {
4451 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4452 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4453 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4454
4455 MockRead("HTTP/1.1 200 OK\r\n"),
4456 MockRead("Content-Length: 0\r\n\r\n"),
4457 MockRead(false, OK),
4458 };
4459 MockWrite data_writes[] = {
4460 MockWrite("POST /upload HTTP/1.1\r\n"
4461 "Host: www.google.com\r\n"
4462 "Connection: keep-alive\r\n"
4463 "Content-Length: 16\r\n\r\n"),
4464 MockWrite(false, temp_file_contents.c_str()),
4465
4466 MockWrite("POST /upload HTTP/1.1\r\n"
4467 "Host: www.google.com\r\n"
4468 "Connection: keep-alive\r\n"
4469 "Content-Length: 16\r\n"
4470 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4471 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4472 MockWrite(false, OK),
4473 };
4474 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4475 arraysize(data_writes));
4476 session_deps.socket_factory.AddSocketDataProvider(&data);
4477
4478 TestCompletionCallback callback1;
4479
[email protected]5a1d7ca2010-04-28 20:12:274480 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364481 EXPECT_EQ(ERR_IO_PENDING, rv);
4482
4483 rv = callback1.WaitForResult();
4484 EXPECT_EQ(OK, rv);
4485
4486 const HttpResponseInfo* response = trans->GetResponseInfo();
4487 EXPECT_TRUE(response != NULL);
4488 EXPECT_TRUE(response->headers != NULL);
4489 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4490
4491 // The password prompt info should have been set in response->auth_challenge.
4492 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4493 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4494 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4495 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4496
4497 // Now make the file unreadable and try again.
4498 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4499
4500 TestCompletionCallback callback2;
4501
4502 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4503 EXPECT_EQ(ERR_IO_PENDING, rv);
4504
4505 rv = callback2.WaitForResult();
4506 EXPECT_EQ(OK, rv);
4507
4508 response = trans->GetResponseInfo();
4509 EXPECT_TRUE(response != NULL);
4510 EXPECT_TRUE(response->headers != NULL);
4511 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4512 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4513
4514 file_util::Delete(temp_file, false);
4515}
4516
[email protected]aeefc9e82010-02-19 16:18:274517// Tests that changes to Auth realms are treated like auth rejections.
4518TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4519 SessionDependencies session_deps;
4520 scoped_ptr<HttpTransaction> trans(
4521 new HttpNetworkTransaction(CreateSession(&session_deps)));
4522
4523 HttpRequestInfo request;
4524 request.method = "GET";
4525 request.url = GURL("http://www.google.com/");
4526 request.load_flags = 0;
4527
4528 // First transaction will request a resource and receive a Basic challenge
4529 // with realm="first_realm".
4530 MockWrite data_writes1[] = {
4531 MockWrite("GET / HTTP/1.1\r\n"
4532 "Host: www.google.com\r\n"
4533 "Connection: keep-alive\r\n"
4534 "\r\n"),
4535 };
4536 MockRead data_reads1[] = {
4537 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4538 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4539 "\r\n"),
4540 };
4541
4542 // After calling trans->RestartWithAuth(), provide an Authentication header
4543 // for first_realm. The server will reject and provide a challenge with
4544 // second_realm.
4545 MockWrite data_writes2[] = {
4546 MockWrite("GET / HTTP/1.1\r\n"
4547 "Host: www.google.com\r\n"
4548 "Connection: keep-alive\r\n"
4549 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4550 "\r\n"),
4551 };
4552 MockRead data_reads2[] = {
4553 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4554 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4555 "\r\n"),
4556 };
4557
4558 // This again fails, and goes back to first_realm. Make sure that the
4559 // entry is removed from cache.
4560 MockWrite data_writes3[] = {
4561 MockWrite("GET / HTTP/1.1\r\n"
4562 "Host: www.google.com\r\n"
4563 "Connection: keep-alive\r\n"
4564 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4565 "\r\n"),
4566 };
4567 MockRead data_reads3[] = {
4568 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4569 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4570 "\r\n"),
4571 };
4572
4573 // Try one last time (with the correct password) and get the resource.
4574 MockWrite data_writes4[] = {
4575 MockWrite("GET / HTTP/1.1\r\n"
4576 "Host: www.google.com\r\n"
4577 "Connection: keep-alive\r\n"
4578 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4579 "\r\n"),
4580 };
4581 MockRead data_reads4[] = {
4582 MockRead("HTTP/1.1 200 OK\r\n"
4583 "Content-Type: text/html; charset=iso-8859-1\r\n"
4584 "Content-Length: 100\r\n"
4585 "\r\n"),
4586 };
4587
4588 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4589 data_writes1, arraysize(data_writes1));
4590 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4591 data_writes2, arraysize(data_writes2));
4592 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4593 data_writes3, arraysize(data_writes3));
4594 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4595 data_writes4, arraysize(data_writes4));
4596 session_deps.socket_factory.AddSocketDataProvider(&data1);
4597 session_deps.socket_factory.AddSocketDataProvider(&data2);
4598 session_deps.socket_factory.AddSocketDataProvider(&data3);
4599 session_deps.socket_factory.AddSocketDataProvider(&data4);
4600
4601 TestCompletionCallback callback1;
4602
4603 // Issue the first request with Authorize headers. There should be a
4604 // password prompt for first_realm waiting to be filled in after the
4605 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274606 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274607 EXPECT_EQ(ERR_IO_PENDING, rv);
4608 rv = callback1.WaitForResult();
4609 EXPECT_EQ(OK, rv);
4610 const HttpResponseInfo* response = trans->GetResponseInfo();
4611 ASSERT_FALSE(response == NULL);
4612 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4613 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4614 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4615 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4616
4617 // Issue the second request with an incorrect password. There should be a
4618 // password prompt for second_realm waiting to be filled in after the
4619 // transaction completes.
4620 TestCompletionCallback callback2;
4621 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4622 EXPECT_EQ(ERR_IO_PENDING, rv);
4623 rv = callback2.WaitForResult();
4624 EXPECT_EQ(OK, rv);
4625 response = trans->GetResponseInfo();
4626 ASSERT_FALSE(response == NULL);
4627 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4628 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4629 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4630 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4631
4632 // Issue the third request with another incorrect password. There should be
4633 // a password prompt for first_realm waiting to be filled in. If the password
4634 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4635 // first_realm was not correctly removed.
4636 TestCompletionCallback callback3;
4637 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4638 EXPECT_EQ(ERR_IO_PENDING, rv);
4639 rv = callback3.WaitForResult();
4640 EXPECT_EQ(OK, rv);
4641 response = trans->GetResponseInfo();
4642 ASSERT_FALSE(response == NULL);
4643 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4644 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4645 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4646 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4647
4648 // Issue the fourth request with the correct password and username.
4649 TestCompletionCallback callback4;
4650 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4651 EXPECT_EQ(ERR_IO_PENDING, rv);
4652 rv = callback4.WaitForResult();
4653 EXPECT_EQ(OK, rv);
4654 response = trans->GetResponseInfo();
4655 ASSERT_FALSE(response == NULL);
4656 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4657}
4658
[email protected]564b4912010-03-09 16:30:424659TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424660 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064661 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424662
[email protected]564b4912010-03-09 16:30:424663 SessionDependencies session_deps;
4664
4665 MockRead data_reads[] = {
4666 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064667 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424668 MockRead("hello world"),
4669 MockRead(false, OK),
4670 };
4671
4672 HttpRequestInfo request;
4673 request.method = "GET";
4674 request.url = GURL("http://www.google.com/");
4675 request.load_flags = 0;
4676
4677 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4678
4679 session_deps.socket_factory.AddSocketDataProvider(&data);
4680
4681 TestCompletionCallback callback;
4682
4683 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4684 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4685
[email protected]5a1d7ca2010-04-28 20:12:274686 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424687 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534688
[email protected]564b4912010-03-09 16:30:424689 HostPortPair http_host_port_pair;
4690 http_host_port_pair.host = "www.google.com";
4691 http_host_port_pair.port = 80;
4692 const HttpAlternateProtocols& alternate_protocols =
4693 session->alternate_protocols();
4694 EXPECT_FALSE(
4695 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4696
4697 EXPECT_EQ(OK, callback.WaitForResult());
4698
4699 const HttpResponseInfo* response = trans->GetResponseInfo();
4700 ASSERT_TRUE(response != NULL);
4701 ASSERT_TRUE(response->headers != NULL);
4702 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4703
4704 std::string response_data;
4705 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4706 EXPECT_EQ("hello world", response_data);
4707
4708 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4709 const HttpAlternateProtocols::PortProtocolPair alternate =
4710 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4711 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4712 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064713 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424714 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424715
[email protected]31e2c69e2010-04-15 18:06:064716 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424717 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424718}
4719
4720TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064721 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424722 SessionDependencies session_deps;
4723
4724 HttpRequestInfo request;
4725 request.method = "GET";
4726 request.url = GURL("http://www.google.com/");
4727 request.load_flags = 0;
4728
4729 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4730 StaticSocketDataProvider first_data;
4731 first_data.set_connect_data(mock_connect);
4732 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4733
4734 MockRead data_reads[] = {
4735 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4736 MockRead("hello world"),
4737 MockRead(true, OK),
4738 };
4739 StaticSocketDataProvider second_data(
4740 data_reads, arraysize(data_reads), NULL, 0);
4741 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4742
4743 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4744 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4745 // http://crbug.com/37454.
4746 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4747
4748 TestCompletionCallback callback;
4749
4750 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4751
4752 HostPortPair http_host_port_pair;
4753 http_host_port_pair.host = "www.google.com";
4754 http_host_port_pair.port = 80;
4755 HttpAlternateProtocols* alternate_protocols =
4756 session->mutable_alternate_protocols();
4757 alternate_protocols->SetAlternateProtocolFor(
4758 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064759 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424760
4761 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4762
[email protected]5a1d7ca2010-04-28 20:12:274763 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424764 EXPECT_EQ(ERR_IO_PENDING, rv);
4765 EXPECT_EQ(OK, callback.WaitForResult());
4766
4767 const HttpResponseInfo* response = trans->GetResponseInfo();
4768 ASSERT_TRUE(response != NULL);
4769 ASSERT_TRUE(response->headers != NULL);
4770 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4771
4772 std::string response_data;
4773 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4774 EXPECT_EQ("hello world", response_data);
4775
4776 ASSERT_TRUE(
4777 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4778 const HttpAlternateProtocols::PortProtocolPair alternate =
4779 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4780 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064781 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424782}
4783
4784// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4785// says that it does SPDY, but it just does the TLS handshake, but the NPN
4786// response does not indicate SPDY, so we just do standard HTTPS over the port.
4787// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4788// on the original port.
[email protected]a2cb8122010-03-10 17:22:424789// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4790// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534791//
[email protected]a2cb8122010-03-10 17:22:424792// HttpRequestInfo request;
4793// request.method = "GET";
4794// request.url = GURL("http://www.google.com/");
4795// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534796//
[email protected]a2cb8122010-03-10 17:22:424797// MockRead data_reads[] = {
4798// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4799// MockRead("hello world"),
4800// MockRead(true, OK),
4801// };
4802// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4803// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534804//
[email protected]a2cb8122010-03-10 17:22:424805// SSLSocketDataProvider ssl(true, OK);
4806// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534807//
[email protected]a2cb8122010-03-10 17:22:424808// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534809//
[email protected]a2cb8122010-03-10 17:22:424810// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534811//
[email protected]a2cb8122010-03-10 17:22:424812// HostPortPair http_host_port_pair;
4813// http_host_port_pair.host = "www.google.com";
4814// http_host_port_pair.port = 80;
4815// HttpAlternateProtocols* alternate_protocols =
4816// session->mutable_alternate_protocols();
4817// alternate_protocols->SetAlternateProtocolFor(
4818// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064819// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534820//
[email protected]a2cb8122010-03-10 17:22:424821// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534822//
[email protected]5a1d7ca2010-04-28 20:12:274823// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:424824// EXPECT_EQ(ERR_IO_PENDING, rv);
4825// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534826//
[email protected]a2cb8122010-03-10 17:22:424827// const HttpResponseInfo* response = trans->GetResponseInfo();
4828// ASSERT_TRUE(response != NULL);
4829// ASSERT_TRUE(response->headers != NULL);
4830// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534831//
[email protected]a2cb8122010-03-10 17:22:424832// std::string response_data;
4833// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4834// EXPECT_EQ("hello world", response_data);
4835// }
4836
4837TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:064838 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:544839 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:114840 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:424841 SessionDependencies session_deps;
4842
4843 HttpRequestInfo request;
4844 request.method = "GET";
4845 request.url = GURL("http://www.google.com/");
4846 request.load_flags = 0;
4847
[email protected]a2cb8122010-03-10 17:22:424848 StaticSocketDataProvider first_tcp_connect;
4849 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4850
4851 SSLSocketDataProvider ssl(true, OK);
4852 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4853
[email protected]564b4912010-03-09 16:30:424854 MockRead data_reads[] = {
4855 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4856 MockRead("hello world"),
4857 MockRead(true, OK),
4858 };
[email protected]a2cb8122010-03-10 17:22:424859 StaticSocketDataProvider fallback_data(
4860 data_reads, arraysize(data_reads), NULL, 0);
4861 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424862
4863 TestCompletionCallback callback;
4864
4865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4866
4867 HostPortPair http_host_port_pair;
4868 http_host_port_pair.host = "www.google.com";
4869 http_host_port_pair.port = 80;
4870 HttpAlternateProtocols* alternate_protocols =
4871 session->mutable_alternate_protocols();
4872 alternate_protocols->SetAlternateProtocolFor(
4873 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064874 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424875
4876 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4877
[email protected]5a1d7ca2010-04-28 20:12:274878 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424879 EXPECT_EQ(ERR_IO_PENDING, rv);
4880 EXPECT_EQ(OK, callback.WaitForResult());
4881
4882 const HttpResponseInfo* response = trans->GetResponseInfo();
4883 ASSERT_TRUE(response != NULL);
4884 ASSERT_TRUE(response->headers != NULL);
4885 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4886
4887 std::string response_data;
4888 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4889 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:544890 HttpNetworkTransaction::SetNextProtos("");
4891 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4892}
4893
4894TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
4895 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4896 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:114897 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:544898 SessionDependencies session_deps;
4899
4900 HttpRequestInfo request;
4901 request.method = "GET";
4902 request.url = GURL("http://www.google.com/");
4903 request.load_flags = 0;
4904
4905 MockRead data_reads[] = {
4906 MockRead("HTTP/1.1 200 OK\r\n"),
4907 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
4908 MockRead("hello world"),
4909 MockRead(true, OK),
4910 };
4911
4912 StaticSocketDataProvider first_transaction(
4913 data_reads, arraysize(data_reads), NULL, 0);
4914 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
4915
4916 SSLSocketDataProvider ssl(true, OK);
4917 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4918 ssl.next_proto = "spdy/1";
4919 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4920
4921 MockWrite spdy_writes[] = {
4922 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
4923 arraysize(kGetSyn)),
4924 };
4925
4926 MockRead spdy_reads[] = {
4927 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
4928 arraysize(kGetSynReply)),
4929 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
4930 arraysize(kGetBodyFrame)),
4931 MockRead(true, 0, 0),
4932 };
4933
4934 scoped_refptr<DelayedSocketData> spdy_data(
4935 new DelayedSocketData(
4936 1, // wait for one write to finish before reading.
4937 spdy_reads, arraysize(spdy_reads),
4938 spdy_writes, arraysize(spdy_writes)));
4939 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
4940
4941 TestCompletionCallback callback;
4942
4943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4944 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
4945
[email protected]5a1d7ca2010-04-28 20:12:274946 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:544947 EXPECT_EQ(ERR_IO_PENDING, rv);
4948 EXPECT_EQ(OK, callback.WaitForResult());
4949
4950 const HttpResponseInfo* response = trans->GetResponseInfo();
4951 ASSERT_TRUE(response != NULL);
4952 ASSERT_TRUE(response->headers != NULL);
4953 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4954
4955 std::string response_data;
4956 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4957 EXPECT_EQ("hello world", response_data);
4958
4959 trans.reset(new HttpNetworkTransaction(session));
4960
[email protected]5a1d7ca2010-04-28 20:12:274961 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:544962 EXPECT_EQ(ERR_IO_PENDING, rv);
4963 EXPECT_EQ(OK, callback.WaitForResult());
4964
4965 response = trans->GetResponseInfo();
4966 ASSERT_TRUE(response != NULL);
4967 ASSERT_TRUE(response->headers != NULL);
4968 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4969
4970 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4971 EXPECT_EQ("hello!", response_data);
4972
4973 HttpNetworkTransaction::SetNextProtos("");
4974 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4975}
4976
[email protected]631f1322010-04-30 17:59:114977class CapturingProxyResolver : public ProxyResolver {
4978 public:
4979 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
4980 virtual ~CapturingProxyResolver() {}
4981
4982 virtual int GetProxyForURL(const GURL& url,
4983 ProxyInfo* results,
4984 CompletionCallback* callback,
4985 RequestHandle* request,
4986 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:424987 ProxyServer proxy_server(
4988 ProxyServer::SCHEME_HTTP, "myproxy", 80);
4989 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:114990 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:424991 return OK;
[email protected]631f1322010-04-30 17:59:114992 }
4993
4994 virtual void CancelRequest(RequestHandle request) {
4995 NOTREACHED();
4996 }
4997
4998 const std::vector<GURL>& resolved() const { return resolved_; }
4999
5000 private:
5001 virtual int SetPacScript(const GURL& /*pac_url*/,
5002 const std::string& /*pac_bytes*/,
5003 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425004 return OK;
[email protected]631f1322010-04-30 17:59:115005 }
5006
5007 std::vector<GURL> resolved_;
5008
5009 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5010};
5011
[email protected]631f1322010-04-30 17:59:115012TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5013 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5014 HttpNetworkTransaction::SetNextProtos(
5015 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5016
5017 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425018 proxy_config.set_auto_detect(true);
5019 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115020
[email protected]631f1322010-04-30 17:59:115021 CapturingProxyResolver* capturing_proxy_resolver =
5022 new CapturingProxyResolver();
5023 SessionDependencies session_deps(
5024 new ProxyService(new ProxyConfigServiceFixed(proxy_config),
5025 capturing_proxy_resolver,
5026 NULL,
5027 NULL));
5028
5029 HttpRequestInfo request;
5030 request.method = "GET";
5031 request.url = GURL("http://www.google.com/");
5032 request.load_flags = 0;
5033
5034 MockRead data_reads[] = {
5035 MockRead("HTTP/1.1 200 OK\r\n"),
5036 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5037 MockRead("hello world"),
5038 MockRead(true, OK),
5039 };
5040
5041 StaticSocketDataProvider first_transaction(
5042 data_reads, arraysize(data_reads), NULL, 0);
5043 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5044
5045 SSLSocketDataProvider ssl(true, OK);
5046 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5047 ssl.next_proto = "spdy/1";
5048 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5049
5050 MockWrite spdy_writes[] = {
5051 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5052 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425053 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]631f1322010-04-30 17:59:115054 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
[email protected]d911f1b2010-05-05 22:39:425055 arraysize(kGetSyn)), // 3
[email protected]631f1322010-04-30 17:59:115056 };
5057
[email protected]d911f1b2010-05-05 22:39:425058 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5059
[email protected]631f1322010-04-30 17:59:115060 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425061 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
5062 MockRead(true, reinterpret_cast<const char*>(kGetSynReply), // 2, 4
5063 arraysize(kGetSynReply), 4),
5064 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame), // 5
5065 arraysize(kGetBodyFrame), 4),
5066 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115067 };
5068
[email protected]d911f1b2010-05-05 22:39:425069 scoped_refptr<OrderedSocketData> spdy_data(
5070 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115071 spdy_reads, arraysize(spdy_reads),
5072 spdy_writes, arraysize(spdy_writes)));
5073 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5074
5075 TestCompletionCallback callback;
5076
5077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5078 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5079
5080 int rv = trans->Start(&request, &callback, BoundNetLog());
5081 EXPECT_EQ(ERR_IO_PENDING, rv);
5082 EXPECT_EQ(OK, callback.WaitForResult());
5083
5084 const HttpResponseInfo* response = trans->GetResponseInfo();
5085 ASSERT_TRUE(response != NULL);
5086 ASSERT_TRUE(response->headers != NULL);
5087 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5088
5089 std::string response_data;
5090 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5091 EXPECT_EQ("hello world", response_data);
5092
5093 trans.reset(new HttpNetworkTransaction(session));
5094
5095 rv = trans->Start(&request, &callback, BoundNetLog());
5096 EXPECT_EQ(ERR_IO_PENDING, rv);
5097 EXPECT_EQ(OK, callback.WaitForResult());
5098
5099 response = trans->GetResponseInfo();
5100 ASSERT_TRUE(response != NULL);
5101 ASSERT_TRUE(response->headers != NULL);
5102 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5103
5104 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5105 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425106 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5107 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115108 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425109 EXPECT_EQ("https://www.google.com/",
5110 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115111
5112 HttpNetworkTransaction::SetNextProtos("");
5113 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5114}
[email protected]631f1322010-04-30 17:59:115115
[email protected]2ff8b312010-04-26 22:20:545116TEST_F(HttpNetworkTransactionTest,
5117 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5118 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5119 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115120 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545121 SessionDependencies session_deps;
5122
5123 HttpRequestInfo request;
5124 request.method = "GET";
5125 request.url = GURL("http://www.google.com/");
5126 request.load_flags = 0;
5127
5128 MockRead data_reads[] = {
5129 MockRead("HTTP/1.1 200 OK\r\n"),
5130 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5131 MockRead("hello world"),
5132 MockRead(true, OK),
5133 };
5134
5135 StaticSocketDataProvider first_transaction(
5136 data_reads, arraysize(data_reads), NULL, 0);
5137 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5138
5139 SSLSocketDataProvider ssl(true, OK);
5140 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5141 ssl.next_proto = "spdy/1";
5142 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5143
5144 MockWrite spdy_writes[] = {
5145 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5146 arraysize(kGetSyn)),
5147 };
5148
5149 MockRead spdy_reads[] = {
5150 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5151 arraysize(kGetSynReply)),
5152 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5153 arraysize(kGetBodyFrame)),
5154 MockRead(true, 0, 0),
5155 };
5156
5157 scoped_refptr<DelayedSocketData> spdy_data(
5158 new DelayedSocketData(
5159 1, // wait for one write to finish before reading.
5160 spdy_reads, arraysize(spdy_reads),
5161 spdy_writes, arraysize(spdy_writes)));
5162 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5163
5164 TestCompletionCallback callback;
5165
5166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5167
5168 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5169
[email protected]5a1d7ca2010-04-28 20:12:275170 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545171 EXPECT_EQ(ERR_IO_PENDING, rv);
5172 EXPECT_EQ(OK, callback.WaitForResult());
5173
5174 const HttpResponseInfo* response = trans->GetResponseInfo();
5175 ASSERT_TRUE(response != NULL);
5176 ASSERT_TRUE(response->headers != NULL);
5177 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5178
5179 std::string response_data;
5180 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5181 EXPECT_EQ("hello world", response_data);
5182
5183 // Set up an initial SpdySession in the pool to reuse.
5184 scoped_refptr<SpdySession> spdy_session =
5185 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
5186 session);
5187 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
5188 spdy_session->Connect(
5189 "www.google.com:443", tcp_params, MEDIUM, BoundNetLog());
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());
5201
5202 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5203 EXPECT_EQ("hello!", response_data);
5204
5205 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065206 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425207}
5208
[email protected]e5ae96a2010-04-14 20:12:455209// MockAuthHandlerCanonical is used by the ResolveCanonicalName
5210// HttpNetworkTransaction unit test below. Callers set up expectations for
5211// whether the canonical name needs to be resolved.
5212class MockAuthHandlerCanonical : public HttpAuthHandler {
5213 public:
5214 enum Resolve {
5215 RESOLVE_INIT,
5216 RESOLVE_SKIP,
5217 RESOLVE_SYNC,
5218 RESOLVE_ASYNC,
5219 RESOLVE_TESTED,
5220 };
5221
5222 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
5223 virtual ~MockAuthHandlerCanonical() {}
5224
5225 void SetResolveExpectation(Resolve resolve) {
5226 EXPECT_EQ(RESOLVE_INIT, resolve_);
5227 resolve_ = resolve;
5228 }
5229
5230 void ResetResolveExpectation() {
5231 EXPECT_EQ(RESOLVE_TESTED, resolve_);
5232 resolve_ = RESOLVE_INIT;
5233 }
5234
5235 virtual bool NeedsCanonicalName() {
5236 switch (resolve_) {
5237 case RESOLVE_SYNC:
5238 case RESOLVE_ASYNC:
5239 return true;
5240 case RESOLVE_SKIP:
5241 resolve_ = RESOLVE_TESTED;
5242 return false;
5243 default:
5244 NOTREACHED();
5245 return false;
5246 }
5247 }
5248
5249 virtual int ResolveCanonicalName(HostResolver* host_resolver,
5250 CompletionCallback* callback,
5251 const BoundNetLog& net_log) {
5252 EXPECT_NE(RESOLVE_TESTED, resolve_);
5253 int rv = OK;
5254 switch (resolve_) {
5255 case RESOLVE_SYNC:
5256 resolve_ = RESOLVE_TESTED;
5257 break;
5258 case RESOLVE_ASYNC:
5259 EXPECT_TRUE(user_callback_ == NULL);
5260 rv = ERR_IO_PENDING;
5261 user_callback_ = callback;
5262 MessageLoop::current()->PostTask(
5263 FROM_HERE,
5264 NewRunnableMethod(
5265 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
5266 break;
5267 default:
5268 NOTREACHED();
5269 break;
5270 }
5271 return rv;
5272 }
5273
5274 void OnResolveCanonicalName() {
5275 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
5276 EXPECT_TRUE(user_callback_ != NULL);
5277 resolve_ = RESOLVE_TESTED;
5278 CompletionCallback* callback = user_callback_;
5279 user_callback_ = NULL;
5280 callback->Run(OK);
5281 }
5282
5283 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
5284 scheme_ = "mock";
5285 score_ = 1;
5286 properties_ = 0;
5287 return true;
5288 }
5289
5290 virtual int GenerateAuthToken(const std::wstring& username,
5291 const std::wstring& password,
5292 const HttpRequestInfo* request,
5293 const ProxyInfo* proxy,
5294 std::string* auth_token) {
5295 auth_token->assign("Mock AUTH myserver.example.com");
5296 return OK;
5297 }
5298
5299 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
5300 const ProxyInfo* proxy,
5301 std::string* auth_token) {
5302 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
5303 return OK;
5304 }
5305
5306 // The Factory class simply returns the same handler each time
5307 // CreateAuthHandler is called.
5308 class Factory : public HttpAuthHandlerFactory {
5309 public:
5310 Factory() {}
5311 virtual ~Factory() {}
5312
5313 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
5314 mock_handler_ = mock_handler;
5315 }
5316 MockAuthHandlerCanonical* mock_handler() const {
5317 return mock_handler_.get();
5318 }
5319
5320 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
5321 HttpAuth::Target target,
5322 const GURL& origin,
5323 scoped_refptr<HttpAuthHandler>* handler) {
5324 *handler = mock_handler_;
5325 return OK;
5326 }
5327
5328 private:
5329 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
5330 };
5331
5332 private:
5333 Resolve resolve_;
5334 CompletionCallback* user_callback_;
5335};
5336
5337// Tests that ResolveCanonicalName is handled correctly by the
5338// HttpNetworkTransaction.
5339TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5340 SessionDependencies session_deps;
5341 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
5342 new MockAuthHandlerCanonical());
5343 auth_handler->Init(NULL);
5344 MockAuthHandlerCanonical::Factory* auth_factory(
5345 new MockAuthHandlerCanonical::Factory());
5346 auth_factory->set_mock_handler(auth_handler);
5347 session_deps.http_auth_handler_factory.reset(auth_factory);
5348
5349 for (int i = 0; i < 2; ++i) {
5350 scoped_ptr<HttpTransaction> trans(
5351 new HttpNetworkTransaction(CreateSession(&session_deps)));
5352
5353 // Set up expectations for this pass of the test. Many of the EXPECT calls
5354 // are contained inside the MockAuthHandlerCanonical codebase in response to
5355 // the expectations.
[email protected]2227c692010-05-04 15:36:115356 MockAuthHandlerCanonical::Resolve resolve =
5357 (i == 0) ?
[email protected]e5ae96a2010-04-14 20:12:455358 MockAuthHandlerCanonical::RESOLVE_SYNC :
5359 MockAuthHandlerCanonical::RESOLVE_ASYNC;
5360 auth_handler->SetResolveExpectation(resolve);
5361 HttpRequestInfo request;
5362 request.method = "GET";
5363 request.url = GURL("http://myserver/");
5364 request.load_flags = 0;
5365
5366 MockWrite data_writes1[] = {
5367 MockWrite("GET / HTTP/1.1\r\n"
5368 "Host: myserver\r\n"
5369 "Connection: keep-alive\r\n\r\n"),
5370 };
5371
5372 MockRead data_reads1[] = {
5373 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5374 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5375 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5376 MockRead("Content-Length: 14\r\n\r\n"),
5377 MockRead("Unauthorized\r\n"),
5378 };
5379
5380 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5381 data_writes1, arraysize(data_writes1));
5382 session_deps.socket_factory.AddSocketDataProvider(&data1);
5383
5384 TestCompletionCallback callback1;
5385
[email protected]5a1d7ca2010-04-28 20:12:275386 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455387 EXPECT_EQ(ERR_IO_PENDING, rv);
5388
5389 rv = callback1.WaitForResult();
5390 EXPECT_EQ(OK, rv);
5391
5392 const HttpResponseInfo* response = trans->GetResponseInfo();
5393 EXPECT_FALSE(response == NULL);
5394
5395 // The password prompt is set after the canonical name is resolved.
5396 // If it isn't present or is incorrect, it indicates that the scheme
5397 // did not complete correctly.
5398 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5399
5400 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5401 EXPECT_EQ(L"", response->auth_challenge->realm);
5402 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
5403 auth_handler->ResetResolveExpectation();
5404 }
5405}
5406
[email protected]aeaca1f2010-04-20 22:05:215407class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5408 public:
5409 TLSDecompressionFailureSocketDataProvider(bool fail_all)
5410 : fail_all_(fail_all) {
5411 }
5412
5413 virtual MockRead GetNextRead() {
5414 if (fail_all_)
5415 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5416
5417 return MockRead(false /* async */,
5418 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5419 }
5420
5421 virtual MockWriteResult OnWrite(const std::string& data) {
5422 return MockWriteResult(false /* async */, data.size());
5423 }
5424
5425 void Reset() {
5426 }
5427
5428 private:
5429 const bool fail_all_;
5430};
5431
5432// Test that we restart a connection when we see a decompression failure from
5433// the peer during the handshake. (In the real world we'll restart with SSLv3
5434// and we won't offer DEFLATE in that case.)
5435TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5436 HttpRequestInfo request;
5437 request.method = "GET";
5438 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5439 request.load_flags = 0;
5440
5441 SessionDependencies session_deps;
5442 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5443 false /* fail all reads */);
5444 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5445 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115446 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215447 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5448 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5449 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5450 session_deps.socket_factory.AddSSLSocketDataProvider(
5451 &ssl_socket_data_provider1);
5452 session_deps.socket_factory.AddSSLSocketDataProvider(
5453 &ssl_socket_data_provider2);
5454
5455 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5457 TestCompletionCallback callback;
5458
[email protected]5a1d7ca2010-04-28 20:12:275459 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215460 EXPECT_EQ(ERR_IO_PENDING, rv);
5461 EXPECT_EQ(OK, callback.WaitForResult());
5462
5463 const HttpResponseInfo* response = trans->GetResponseInfo();
5464 ASSERT_TRUE(response != NULL);
5465 ASSERT_TRUE(response->headers != NULL);
5466 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5467
5468 std::string response_data;
5469 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5470 EXPECT_EQ("ok.", response_data);
5471}
5472
5473// Test that we restart a connection if we get a decompression failure from the
5474// peer while reading the first bytes from the connection. This occurs when the
5475// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5476// in the handshake.
5477TEST_F(HttpNetworkTransactionTest,
5478 RestartAfterTLSDecompressionFailureWithFalseStart) {
5479 HttpRequestInfo request;
5480 request.method = "GET";
5481 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
5482 request.load_flags = 0;
5483
5484 SessionDependencies session_deps;
5485 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5486 true /* fail all reads */);
5487 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5488 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
5489 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5490 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5491 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5492 session_deps.socket_factory.AddSSLSocketDataProvider(
5493 &ssl_socket_data_provider1);
5494 session_deps.socket_factory.AddSSLSocketDataProvider(
5495 &ssl_socket_data_provider2);
5496
5497 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5498 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5499 TestCompletionCallback callback;
5500
[email protected]5a1d7ca2010-04-28 20:12:275501 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215502 EXPECT_EQ(ERR_IO_PENDING, rv);
5503 EXPECT_EQ(OK, callback.WaitForResult());
5504
5505 const HttpResponseInfo* response = trans->GetResponseInfo();
5506 ASSERT_TRUE(response != NULL);
5507 ASSERT_TRUE(response->headers != NULL);
5508 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5509
5510 std::string response_data;
5511 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5512 EXPECT_EQ("ok.", response_data);
5513}
5514
[email protected]89ceba9a2009-03-21 03:46:065515} // namespace net