blob: e0b1bfcc91990e3ec2641f47b1b40450f7984e3f [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]ff007e162009-05-23 09:13:151382void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081383 const MockRead& status, int expected_status) {
1384 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591385 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081386
[email protected]228ff742009-06-05 01:19:591387 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081388
[email protected]5695b8c2009-09-30 21:36:431389 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081390
[email protected]1c773ea12009-04-28 19:58:421391 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081392 request.method = "GET";
1393 request.url = GURL("https://www.google.com/");
1394 request.load_flags = 0;
1395
1396 // Since we have proxy, should try to establish tunnel.
1397 MockWrite data_writes[] = {
1398 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451399 "Host: www.google.com\r\n"
1400 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081401 };
1402
1403 MockRead data_reads[] = {
1404 status,
1405 MockRead("Content-Length: 10\r\n\r\n"),
1406 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421407 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081408 };
1409
[email protected]31a2bfe2010-02-09 08:03:391410 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1411 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591412 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081413
1414 TestCompletionCallback callback;
1415
[email protected]5a1d7ca2010-04-28 20:12:271416 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421417 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081418
1419 rv = callback.WaitForResult();
1420 EXPECT_EQ(expected_status, rv);
1421}
1422
[email protected]ff007e162009-05-23 09:13:151423void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081424 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421425 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081426}
1427
1428TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1429 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1430}
1431
1432TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1433 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1434}
1435
1436TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1437 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1438}
1439
1440TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1441 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1442}
1443
1444TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1445 ConnectStatusHelper(
1446 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1455}
1456
1457TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1458 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1459}
1460
1461TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1462 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1463}
1464
1465TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1466 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1467}
1468
1469TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1470 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1471}
1472
1473TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1474 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1475}
1476
1477TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1478 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1479}
1480
1481TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1482 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1483}
1484
1485TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1486 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1487}
1488
1489TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1490 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1491}
1492
1493TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1494 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1495}
1496
1497TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1498 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1499}
1500
1501TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1502 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1503}
1504
1505TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1506 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1507}
1508
1509TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1510 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1511}
1512
1513TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1514 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1515}
1516
1517TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1518 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1519}
1520
1521TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1522 ConnectStatusHelperWithExpectedStatus(
1523 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421524 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081525}
1526
1527TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1528 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1529}
1530
1531TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1532 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1533}
1534
1535TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1536 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1537}
1538
1539TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1540 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1541}
1542
1543TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1544 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1545}
1546
1547TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1548 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1549}
1550
1551TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1552 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1553}
1554
1555TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1556 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1557}
1558
1559TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1560 ConnectStatusHelper(
1561 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1562}
1563
1564TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1565 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1566}
1567
1568TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1569 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1570}
1571
1572TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1573 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1574}
1575
1576TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1577 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1578}
1579
1580TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1581 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1582}
1583
1584TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1585 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1586}
1587
1588TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1589 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1590}
1591
[email protected]038e9a32008-10-08 22:40:161592// Test the flow when both the proxy server AND origin server require
1593// authentication. Again, this uses basic auth for both since that is
1594// the simplest to mock.
1595TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591596 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011597
[email protected]038e9a32008-10-08 22:40:161598 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431600 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161601
[email protected]1c773ea12009-04-28 19:58:421602 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161603 request.method = "GET";
1604 request.url = GURL("http://www.google.com/");
1605 request.load_flags = 0;
1606
[email protected]f9ee6b52008-11-08 06:46:231607 MockWrite data_writes1[] = {
1608 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1609 "Host: www.google.com\r\n"
1610 "Proxy-Connection: keep-alive\r\n\r\n"),
1611 };
1612
[email protected]038e9a32008-10-08 22:40:161613 MockRead data_reads1[] = {
1614 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1615 // Give a couple authenticate options (only the middle one is actually
1616 // supported).
[email protected]22927ad2009-09-21 19:56:191617 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161618 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1619 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1620 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1621 // Large content-length -- won't matter, as connection will be reset.
1622 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421623 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161624 };
1625
1626 // After calling trans->RestartWithAuth() the first time, this is the
1627 // request we should be issuing -- the final header line contains the
1628 // proxy's credentials.
1629 MockWrite data_writes2[] = {
1630 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1631 "Host: www.google.com\r\n"
1632 "Proxy-Connection: keep-alive\r\n"
1633 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1634 };
1635
1636 // Now the proxy server lets the request pass through to origin server.
1637 // The origin server responds with a 401.
1638 MockRead data_reads2[] = {
1639 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1640 // Note: We are using the same realm-name as the proxy server. This is
1641 // completely valid, as realms are unique across hosts.
1642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1643 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1644 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421645 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161646 };
1647
1648 // After calling trans->RestartWithAuth() the second time, we should send
1649 // the credentials for both the proxy and origin server.
1650 MockWrite data_writes3[] = {
1651 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1652 "Host: www.google.com\r\n"
1653 "Proxy-Connection: keep-alive\r\n"
1654 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1655 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1656 };
1657
1658 // Lastly we get the desired content.
1659 MockRead data_reads3[] = {
1660 MockRead("HTTP/1.0 200 OK\r\n"),
1661 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1662 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421663 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161664 };
1665
[email protected]31a2bfe2010-02-09 08:03:391666 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1667 data_writes1, arraysize(data_writes1));
1668 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1669 data_writes2, arraysize(data_writes2));
1670 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1671 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591672 session_deps.socket_factory.AddSocketDataProvider(&data1);
1673 session_deps.socket_factory.AddSocketDataProvider(&data2);
1674 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161675
1676 TestCompletionCallback callback1;
1677
[email protected]5a1d7ca2010-04-28 20:12:271678 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421679 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161680
1681 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421682 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161683
[email protected]1c773ea12009-04-28 19:58:421684 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161685 EXPECT_FALSE(response == NULL);
1686
1687 // The password prompt info should have been set in response->auth_challenge.
1688 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1689
[email protected]71e4573a2009-05-21 22:03:001690 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161691 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1692 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1693
1694 TestCompletionCallback callback2;
1695
1696 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161698
1699 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421700 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161701
1702 response = trans->GetResponseInfo();
1703 EXPECT_FALSE(response == NULL);
1704 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1705
[email protected]71e4573a2009-05-21 22:03:001706 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161707 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1708 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1709
1710 TestCompletionCallback callback3;
1711
1712 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421713 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161714
1715 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421716 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161717
1718 response = trans->GetResponseInfo();
1719 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1720 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161721}
[email protected]4ddaf2502008-10-23 18:26:191722
[email protected]ea9dc9a2009-09-05 00:43:321723// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1724// can't hook into its internals to cause it to generate predictable NTLM
1725// authorization headers.
1726#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291727// The NTLM authentication unit tests were generated by capturing the HTTP
1728// requests and responses using Fiddler 2 and inspecting the generated random
1729// bytes in the debugger.
1730
1731// Enter the correct password and authenticate successfully.
1732TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421733 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111734 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591735 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401736 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431737 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241738
[email protected]1c773ea12009-04-28 19:58:421739 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241740 request.method = "GET";
1741 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1742 request.load_flags = 0;
1743
1744 MockWrite data_writes1[] = {
1745 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1746 "Host: 172.22.68.17\r\n"
1747 "Connection: keep-alive\r\n\r\n"),
1748 };
1749
1750 MockRead data_reads1[] = {
1751 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1752 // Negotiate and NTLM are often requested together. We only support NTLM.
1753 MockRead("WWW-Authenticate: Negotiate\r\n"),
1754 MockRead("WWW-Authenticate: NTLM\r\n"),
1755 MockRead("Connection: close\r\n"),
1756 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361757 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241758 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421759 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241760 };
1761
1762 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221763 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241764 // request we should be issuing -- the final header line contains a Type
1765 // 1 message.
1766 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1767 "Host: 172.22.68.17\r\n"
1768 "Connection: keep-alive\r\n"
1769 "Authorization: NTLM "
1770 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1771
1772 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1773 // (the credentials for the origin server). The second request continues
1774 // on the same connection.
1775 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1776 "Host: 172.22.68.17\r\n"
1777 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291778 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1779 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1780 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1781 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1782 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241783 };
1784
1785 MockRead data_reads2[] = {
1786 // The origin server responds with a Type 2 message.
1787 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1788 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291789 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241790 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1791 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1792 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1793 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1794 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1795 "BtAAAAAAA=\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 MockRead("You are not authorized to view this page\r\n"),
1799
1800 // Lastly we get the desired content.
1801 MockRead("HTTP/1.1 200 OK\r\n"),
1802 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1803 MockRead("Content-Length: 13\r\n\r\n"),
1804 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421805 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241806 };
1807
[email protected]31a2bfe2010-02-09 08:03:391808 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1809 data_writes1, arraysize(data_writes1));
1810 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1811 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591812 session_deps.socket_factory.AddSocketDataProvider(&data1);
1813 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241814
1815 TestCompletionCallback callback1;
1816
[email protected]5a1d7ca2010-04-28 20:12:271817 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421818 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241819
1820 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421821 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241822
[email protected]0757e7702009-03-27 04:00:221823 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1824 TestCompletionCallback callback2;
1825 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221827 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421828 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221829 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1830
[email protected]1c773ea12009-04-28 19:58:421831 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241832 EXPECT_FALSE(response == NULL);
1833
1834 // The password prompt info should have been set in response->auth_challenge.
1835 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1836
[email protected]71e4573a2009-05-21 22:03:001837 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241838 EXPECT_EQ(L"", response->auth_challenge->realm);
1839 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1840
[email protected]0757e7702009-03-27 04:00:221841 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241842
[email protected]0757e7702009-03-27 04:00:221843 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421844 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241845
[email protected]0757e7702009-03-27 04:00:221846 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421847 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241848
1849 response = trans->GetResponseInfo();
1850 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1851 EXPECT_EQ(13, response->headers->GetContentLength());
1852}
1853
[email protected]385a4672009-03-11 22:21:291854// Enter a wrong password, and then the correct one.
1855TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421856 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111857 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591858 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401859 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431860 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291861
[email protected]1c773ea12009-04-28 19:58:421862 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291863 request.method = "GET";
1864 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1865 request.load_flags = 0;
1866
1867 MockWrite data_writes1[] = {
1868 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1869 "Host: 172.22.68.17\r\n"
1870 "Connection: keep-alive\r\n\r\n"),
1871 };
1872
1873 MockRead data_reads1[] = {
1874 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1875 // Negotiate and NTLM are often requested together. We only support NTLM.
1876 MockRead("WWW-Authenticate: Negotiate\r\n"),
1877 MockRead("WWW-Authenticate: NTLM\r\n"),
1878 MockRead("Connection: close\r\n"),
1879 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361880 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291881 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421882 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291883 };
1884
1885 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221886 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291887 // request we should be issuing -- the final header line contains a Type
1888 // 1 message.
1889 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1890 "Host: 172.22.68.17\r\n"
1891 "Connection: keep-alive\r\n"
1892 "Authorization: NTLM "
1893 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1894
1895 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1896 // (the credentials for the origin server). The second request continues
1897 // on the same connection.
1898 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1899 "Host: 172.22.68.17\r\n"
1900 "Connection: keep-alive\r\n"
1901 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1902 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1903 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1904 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1905 "4Ww7b7E=\r\n\r\n"),
1906 };
1907
1908 MockRead data_reads2[] = {
1909 // The origin server responds with a Type 2 message.
1910 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1911 MockRead("WWW-Authenticate: NTLM "
1912 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1913 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1914 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1915 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1916 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1917 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1918 "BtAAAAAAA=\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 MockRead("You are not authorized to view this page\r\n"),
1922
1923 // Wrong password.
1924 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1925 MockRead("WWW-Authenticate: Negotiate\r\n"),
1926 MockRead("WWW-Authenticate: NTLM\r\n"),
1927 MockRead("Connection: close\r\n"),
1928 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361929 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291930 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421931 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291932 };
1933
1934 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221935 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291936 // request we should be issuing -- the final header line contains a Type
1937 // 1 message.
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 "
1942 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1943
1944 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1945 // (the credentials for the origin server). The second request continues
1946 // on the same connection.
1947 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1948 "Host: 172.22.68.17\r\n"
1949 "Connection: keep-alive\r\n"
1950 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1951 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1952 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1953 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1954 "+4MUm7c=\r\n\r\n"),
1955 };
1956
1957 MockRead data_reads3[] = {
1958 // The origin server responds with a Type 2 message.
1959 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1960 MockRead("WWW-Authenticate: NTLM "
1961 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1962 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1963 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1964 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1965 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1966 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1967 "BtAAAAAAA=\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 MockRead("You are not authorized to view this page\r\n"),
1971
1972 // Lastly we get the desired content.
1973 MockRead("HTTP/1.1 200 OK\r\n"),
1974 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1975 MockRead("Content-Length: 13\r\n\r\n"),
1976 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421977 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291978 };
1979
[email protected]31a2bfe2010-02-09 08:03:391980 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1981 data_writes1, arraysize(data_writes1));
1982 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1983 data_writes2, arraysize(data_writes2));
1984 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1985 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591986 session_deps.socket_factory.AddSocketDataProvider(&data1);
1987 session_deps.socket_factory.AddSocketDataProvider(&data2);
1988 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291989
1990 TestCompletionCallback callback1;
1991
[email protected]5a1d7ca2010-04-28 20:12:271992 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291994
1995 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421996 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291997
[email protected]0757e7702009-03-27 04:00:221998 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291999 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222000 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422001 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292002 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422003 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222004 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292005
[email protected]1c773ea12009-04-28 19:58:422006 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292007 EXPECT_FALSE(response == NULL);
2008
2009 // The password prompt info should have been set in response->auth_challenge.
2010 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2011
[email protected]71e4573a2009-05-21 22:03:002012 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292013 EXPECT_EQ(L"", response->auth_challenge->realm);
2014 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2015
2016 TestCompletionCallback callback3;
2017
[email protected]0757e7702009-03-27 04:00:222018 // Enter the wrong password.
2019 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422020 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292021
2022 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422023 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292024
[email protected]0757e7702009-03-27 04:00:222025 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2026 TestCompletionCallback callback4;
2027 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422028 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222029 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422030 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222031 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2032
2033 response = trans->GetResponseInfo();
2034 EXPECT_FALSE(response == NULL);
2035
2036 // The password prompt info should have been set in response->auth_challenge.
2037 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2038
[email protected]71e4573a2009-05-21 22:03:002039 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222040 EXPECT_EQ(L"", response->auth_challenge->realm);
2041 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2042
2043 TestCompletionCallback callback5;
2044
2045 // Now enter the right password.
2046 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222048
2049 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422050 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222051
[email protected]385a4672009-03-11 22:21:292052 response = trans->GetResponseInfo();
2053 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2054 EXPECT_EQ(13, response->headers->GetContentLength());
2055}
[email protected]ea9dc9a2009-09-05 00:43:322056#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292057
[email protected]4ddaf2502008-10-23 18:26:192058// Test reading a server response which has only headers, and no body.
2059// After some maximum number of bytes is consumed, the transaction should
2060// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2061TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592062 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402063 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432064 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192065
[email protected]1c773ea12009-04-28 19:58:422066 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192067 request.method = "GET";
2068 request.url = GURL("http://www.google.com/");
2069 request.load_flags = 0;
2070
[email protected]b75b7b2f2009-10-06 00:54:532071 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432072 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532073 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192074
2075 MockRead data_reads[] = {
2076 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432077 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192078 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422079 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192080 };
[email protected]31a2bfe2010-02-09 08:03:392081 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592082 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192083
2084 TestCompletionCallback callback;
2085
[email protected]5a1d7ca2010-04-28 20:12:272086 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422087 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192088
2089 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422090 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192091
[email protected]1c773ea12009-04-28 19:58:422092 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192093 EXPECT_TRUE(response == NULL);
2094}
[email protected]f4e426b2008-11-05 00:24:492095
2096// Make sure that we don't try to reuse a TCPClientSocket when failing to
2097// establish tunnel.
2098// http://code.google.com/p/chromium/issues/detail?id=3772
2099TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2100 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592101 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012102
[email protected]228ff742009-06-05 01:19:592103 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492104
[email protected]5695b8c2009-09-30 21:36:432105 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492106
[email protected]1c773ea12009-04-28 19:58:422107 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492108 request.method = "GET";
2109 request.url = GURL("https://www.google.com/");
2110 request.load_flags = 0;
2111
2112 // Since we have proxy, should try to establish tunnel.
2113 MockWrite data_writes1[] = {
2114 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452115 "Host: www.google.com\r\n"
2116 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492117 };
2118
[email protected]77848d12008-11-14 00:00:222119 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492120 // connection. Usually a proxy would return 501 (not implemented),
2121 // or 200 (tunnel established).
2122 MockRead data_reads1[] = {
2123 MockRead("HTTP/1.1 404 Not Found\r\n"),
2124 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422125 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492126 };
2127
[email protected]31a2bfe2010-02-09 08:03:392128 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2129 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592130 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492131
2132 TestCompletionCallback callback1;
2133
[email protected]5a1d7ca2010-04-28 20:12:272134 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422135 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492136
2137 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422138 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492139
[email protected]1c773ea12009-04-28 19:58:422140 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082141 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492142
[email protected]b4404c02009-04-10 16:38:522143 // Empty the current queue. This is necessary because idle sockets are
2144 // added to the connection pool asynchronously with a PostTask.
2145 MessageLoop::current()->RunAllPending();
2146
[email protected]f4e426b2008-11-05 00:24:492147 // We now check to make sure the TCPClientSocket was not added back to
2148 // the pool.
[email protected]a937a06d2009-08-19 21:19:242149 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492150 trans.reset();
[email protected]b4404c02009-04-10 16:38:522151 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492152 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242153 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492154}
[email protected]372d34a2008-11-05 21:30:512155
[email protected]1b157c02009-04-21 01:55:402156// Make sure that we recycle a socket after reading all of the response body.
2157TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592158 SessionDependencies session_deps;
2159 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402160
[email protected]5695b8c2009-09-30 21:36:432161 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402162
[email protected]1c773ea12009-04-28 19:58:422163 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402164 request.method = "GET";
2165 request.url = GURL("http://www.google.com/");
2166 request.load_flags = 0;
2167
2168 MockRead data_reads[] = {
2169 // A part of the response body is received with the response headers.
2170 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2171 // The rest of the response body is received in two parts.
2172 MockRead("lo"),
2173 MockRead(" world"),
2174 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422175 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402176 };
2177
[email protected]31a2bfe2010-02-09 08:03:392178 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592179 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402180
2181 TestCompletionCallback callback;
2182
[email protected]5a1d7ca2010-04-28 20:12:272183 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422184 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402185
2186 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422187 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402188
[email protected]1c773ea12009-04-28 19:58:422189 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402190 EXPECT_TRUE(response != NULL);
2191
2192 EXPECT_TRUE(response->headers != NULL);
2193 std::string status_line = response->headers->GetStatusLine();
2194 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2195
[email protected]a937a06d2009-08-19 21:19:242196 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402197
2198 std::string response_data;
2199 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422200 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402201 EXPECT_EQ("hello world", response_data);
2202
2203 // Empty the current queue. This is necessary because idle sockets are
2204 // added to the connection pool asynchronously with a PostTask.
2205 MessageLoop::current()->RunAllPending();
2206
2207 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242208 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402209}
2210
[email protected]b4404c02009-04-10 16:38:522211// Make sure that we recycle a socket after a zero-length response.
2212// http://crbug.com/9880
2213TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592214 SessionDependencies session_deps;
2215 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522216
[email protected]5695b8c2009-09-30 21:36:432217 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522218
[email protected]1c773ea12009-04-28 19:58:422219 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522220 request.method = "GET";
2221 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2222 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2223 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2224 "rt=prt.2642,ol.2649,xjs.2951");
2225 request.load_flags = 0;
2226
2227 MockRead data_reads[] = {
2228 MockRead("HTTP/1.1 204 No Content\r\n"
2229 "Content-Length: 0\r\n"
2230 "Content-Type: text/html\r\n\r\n"),
2231 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422232 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522233 };
2234
[email protected]31a2bfe2010-02-09 08:03:392235 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592236 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522237
2238 TestCompletionCallback callback;
2239
[email protected]5a1d7ca2010-04-28 20:12:272240 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422241 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522242
2243 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422244 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522245
[email protected]1c773ea12009-04-28 19:58:422246 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522247 EXPECT_TRUE(response != NULL);
2248
2249 EXPECT_TRUE(response->headers != NULL);
2250 std::string status_line = response->headers->GetStatusLine();
2251 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2252
[email protected]a937a06d2009-08-19 21:19:242253 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522254
2255 std::string response_data;
2256 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422257 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522258 EXPECT_EQ("", response_data);
2259
2260 // Empty the current queue. This is necessary because idle sockets are
2261 // added to the connection pool asynchronously with a PostTask.
2262 MessageLoop::current()->RunAllPending();
2263
2264 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242265 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522266}
2267
[email protected]372d34a2008-11-05 21:30:512268TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422269 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512270 // Transaction 1: a GET request that succeeds. The socket is recycled
2271 // after use.
2272 request[0].method = "GET";
2273 request[0].url = GURL("http://www.google.com/");
2274 request[0].load_flags = 0;
2275 // Transaction 2: a POST request. Reuses the socket kept alive from
2276 // transaction 1. The first attempts fails when writing the POST data.
2277 // This causes the transaction to retry with a new socket. The second
2278 // attempt succeeds.
2279 request[1].method = "POST";
2280 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422281 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512282 request[1].upload_data->AppendBytes("foo", 3);
2283 request[1].load_flags = 0;
2284
[email protected]228ff742009-06-05 01:19:592285 SessionDependencies session_deps;
2286 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512287
2288 // The first socket is used for transaction 1 and the first attempt of
2289 // transaction 2.
2290
2291 // The response of transaction 1.
2292 MockRead data_reads1[] = {
2293 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2294 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422295 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512296 };
2297 // The mock write results of transaction 1 and the first attempt of
2298 // transaction 2.
2299 MockWrite data_writes1[] = {
2300 MockWrite(false, 64), // GET
2301 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422302 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512303 };
[email protected]31a2bfe2010-02-09 08:03:392304 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2305 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512306
2307 // The second socket is used for the second attempt of transaction 2.
2308
2309 // The response of transaction 2.
2310 MockRead data_reads2[] = {
2311 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2312 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422313 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512314 };
2315 // The mock write results of the second attempt of transaction 2.
2316 MockWrite data_writes2[] = {
2317 MockWrite(false, 93), // POST
2318 MockWrite(false, 3), // POST data
2319 };
[email protected]31a2bfe2010-02-09 08:03:392320 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2321 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512322
[email protected]5ecc992a42009-11-11 01:41:592323 session_deps.socket_factory.AddSocketDataProvider(&data1);
2324 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512325
2326 const char* kExpectedResponseData[] = {
2327 "hello world", "welcome"
2328 };
2329
2330 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422331 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432332 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512333
2334 TestCompletionCallback callback;
2335
[email protected]5a1d7ca2010-04-28 20:12:272336 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422337 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512338
2339 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422340 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512341
[email protected]1c773ea12009-04-28 19:58:422342 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512343 EXPECT_TRUE(response != NULL);
2344
2345 EXPECT_TRUE(response->headers != NULL);
2346 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2347
2348 std::string response_data;
2349 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422350 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512351 EXPECT_EQ(kExpectedResponseData[i], response_data);
2352 }
2353}
[email protected]f9ee6b52008-11-08 06:46:232354
2355// Test the request-challenge-retry sequence for basic auth when there is
2356// an identity in the URL. The request should be sent as normal, but when
2357// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322358TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592359 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402360 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432361 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232362
[email protected]1c773ea12009-04-28 19:58:422363 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232364 request.method = "GET";
2365 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292366 request.url = GURL("http://foo:b@[email protected]/");
2367
2368 // The password contains an escaped character -- for this test to pass it
2369 // will need to be unescaped by HttpNetworkTransaction.
2370 EXPECT_EQ("b%40r", request.url.password());
2371
[email protected]ea9dc9a2009-09-05 00:43:322372 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232373
2374 MockWrite data_writes1[] = {
2375 MockWrite("GET / HTTP/1.1\r\n"
2376 "Host: www.google.com\r\n"
2377 "Connection: keep-alive\r\n\r\n"),
2378 };
2379
2380 MockRead data_reads1[] = {
2381 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2382 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2383 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422384 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232385 };
2386
2387 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322388 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232389 MockWrite data_writes2[] = {
2390 MockWrite("GET / HTTP/1.1\r\n"
2391 "Host: www.google.com\r\n"
2392 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292393 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232394 };
2395
2396 MockRead data_reads2[] = {
2397 MockRead("HTTP/1.0 200 OK\r\n"),
2398 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422399 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232400 };
2401
[email protected]31a2bfe2010-02-09 08:03:392402 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2403 data_writes1, arraysize(data_writes1));
2404 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2405 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592406 session_deps.socket_factory.AddSocketDataProvider(&data1);
2407 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232408
2409 TestCompletionCallback callback1;
2410
[email protected]5a1d7ca2010-04-28 20:12:272411 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422412 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232413
2414 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422415 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232416
[email protected]0757e7702009-03-27 04:00:222417 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2418 TestCompletionCallback callback2;
2419 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422420 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222421 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422422 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222423 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2424
[email protected]1c773ea12009-04-28 19:58:422425 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232426 EXPECT_FALSE(response == NULL);
2427
2428 // There is no challenge info, since the identity in URL worked.
2429 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2430
2431 EXPECT_EQ(100, response->headers->GetContentLength());
2432
2433 // Empty the current queue.
2434 MessageLoop::current()->RunAllPending();
2435}
2436
[email protected]ea9dc9a2009-09-05 00:43:322437// Test the request-challenge-retry sequence for basic auth when there is
2438// an incorrect identity in the URL. The identity from the URL should be used
2439// only once.
2440TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2441 SessionDependencies session_deps;
2442 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432443 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322444
2445 HttpRequestInfo request;
2446 request.method = "GET";
2447 // Note: the URL has a username:password in it. The password "baz" is
2448 // wrong (should be "bar").
2449 request.url = GURL("http://foo:[email protected]/");
2450
2451 request.load_flags = LOAD_NORMAL;
2452
2453 MockWrite data_writes1[] = {
2454 MockWrite("GET / HTTP/1.1\r\n"
2455 "Host: www.google.com\r\n"
2456 "Connection: keep-alive\r\n\r\n"),
2457 };
2458
2459 MockRead data_reads1[] = {
2460 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2461 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2462 MockRead("Content-Length: 10\r\n\r\n"),
2463 MockRead(false, ERR_FAILED),
2464 };
2465
2466 // After the challenge above, the transaction will be restarted using the
2467 // identity from the url (foo, baz) to answer the challenge.
2468 MockWrite data_writes2[] = {
2469 MockWrite("GET / HTTP/1.1\r\n"
2470 "Host: www.google.com\r\n"
2471 "Connection: keep-alive\r\n"
2472 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2473 };
2474
2475 MockRead data_reads2[] = {
2476 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2477 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2478 MockRead("Content-Length: 10\r\n\r\n"),
2479 MockRead(false, ERR_FAILED),
2480 };
2481
2482 // After the challenge above, the transaction will be restarted using the
2483 // identity supplied by the user (foo, bar) to answer the challenge.
2484 MockWrite data_writes3[] = {
2485 MockWrite("GET / HTTP/1.1\r\n"
2486 "Host: www.google.com\r\n"
2487 "Connection: keep-alive\r\n"
2488 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2489 };
2490
2491 MockRead data_reads3[] = {
2492 MockRead("HTTP/1.0 200 OK\r\n"),
2493 MockRead("Content-Length: 100\r\n\r\n"),
2494 MockRead(false, OK),
2495 };
2496
[email protected]31a2bfe2010-02-09 08:03:392497 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2498 data_writes1, arraysize(data_writes1));
2499 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2500 data_writes2, arraysize(data_writes2));
2501 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2502 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592503 session_deps.socket_factory.AddSocketDataProvider(&data1);
2504 session_deps.socket_factory.AddSocketDataProvider(&data2);
2505 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322506
2507 TestCompletionCallback callback1;
2508
[email protected]5a1d7ca2010-04-28 20:12:272509 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322510 EXPECT_EQ(ERR_IO_PENDING, rv);
2511
2512 rv = callback1.WaitForResult();
2513 EXPECT_EQ(OK, rv);
2514
2515 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2516 TestCompletionCallback callback2;
2517 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2518 EXPECT_EQ(ERR_IO_PENDING, rv);
2519 rv = callback2.WaitForResult();
2520 EXPECT_EQ(OK, rv);
2521 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2522
2523 const HttpResponseInfo* response = trans->GetResponseInfo();
2524 EXPECT_FALSE(response == NULL);
2525 // The password prompt info should have been set in response->auth_challenge.
2526 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2527
2528 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2529 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2530 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2531
2532 TestCompletionCallback callback3;
2533 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2534 EXPECT_EQ(ERR_IO_PENDING, rv);
2535 rv = callback3.WaitForResult();
2536 EXPECT_EQ(OK, rv);
2537 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2538
2539 response = trans->GetResponseInfo();
2540 EXPECT_FALSE(response == NULL);
2541
2542 // There is no challenge info, since the identity worked.
2543 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2544
2545 EXPECT_EQ(100, response->headers->GetContentLength());
2546
2547 // Empty the current queue.
2548 MessageLoop::current()->RunAllPending();
2549}
2550
[email protected]f9ee6b52008-11-08 06:46:232551// Test that previously tried username/passwords for a realm get re-used.
2552TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592553 SessionDependencies session_deps;
2554 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232555
2556 // Transaction 1: authenticate (foo, bar) on MyRealm1
2557 {
[email protected]5695b8c2009-09-30 21:36:432558 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232559
[email protected]1c773ea12009-04-28 19:58:422560 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232561 request.method = "GET";
2562 request.url = GURL("http://www.google.com/x/y/z");
2563 request.load_flags = 0;
2564
2565 MockWrite data_writes1[] = {
2566 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2567 "Host: www.google.com\r\n"
2568 "Connection: keep-alive\r\n\r\n"),
2569 };
2570
2571 MockRead data_reads1[] = {
2572 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2573 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2574 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422575 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232576 };
2577
2578 // Resend with authorization (username=foo, password=bar)
2579 MockWrite data_writes2[] = {
2580 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2581 "Host: www.google.com\r\n"
2582 "Connection: keep-alive\r\n"
2583 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2584 };
2585
2586 // Sever accepts the authorization.
2587 MockRead data_reads2[] = {
2588 MockRead("HTTP/1.0 200 OK\r\n"),
2589 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422590 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232591 };
2592
[email protected]31a2bfe2010-02-09 08:03:392593 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2594 data_writes1, arraysize(data_writes1));
2595 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2596 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592597 session_deps.socket_factory.AddSocketDataProvider(&data1);
2598 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232599
2600 TestCompletionCallback callback1;
2601
[email protected]5a1d7ca2010-04-28 20:12:272602 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422603 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232604
2605 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422606 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232607
[email protected]1c773ea12009-04-28 19:58:422608 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232609 EXPECT_FALSE(response == NULL);
2610
2611 // The password prompt info should have been set in
2612 // response->auth_challenge.
2613 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2614
[email protected]71e4573a2009-05-21 22:03:002615 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232616 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2617 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2618
2619 TestCompletionCallback callback2;
2620
2621 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422622 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232623
2624 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422625 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232626
2627 response = trans->GetResponseInfo();
2628 EXPECT_FALSE(response == NULL);
2629 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2630 EXPECT_EQ(100, response->headers->GetContentLength());
2631 }
2632
2633 // ------------------------------------------------------------------------
2634
2635 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2636 {
[email protected]5695b8c2009-09-30 21:36:432637 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232638
[email protected]1c773ea12009-04-28 19:58:422639 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232640 request.method = "GET";
2641 // Note that Transaction 1 was at /x/y/z, so this is in the same
2642 // protection space as MyRealm1.
2643 request.url = GURL("http://www.google.com/x/y/a/b");
2644 request.load_flags = 0;
2645
2646 MockWrite data_writes1[] = {
2647 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2648 "Host: www.google.com\r\n"
2649 "Connection: keep-alive\r\n"
2650 // Send preemptive authorization for MyRealm1
2651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2652 };
2653
2654 // The server didn't like the preemptive authorization, and
2655 // challenges us for a different realm (MyRealm2).
2656 MockRead data_reads1[] = {
2657 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2658 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2659 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422660 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232661 };
2662
2663 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2664 MockWrite data_writes2[] = {
2665 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2666 "Host: www.google.com\r\n"
2667 "Connection: keep-alive\r\n"
2668 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2669 };
2670
2671 // Sever accepts the authorization.
2672 MockRead data_reads2[] = {
2673 MockRead("HTTP/1.0 200 OK\r\n"),
2674 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422675 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232676 };
2677
[email protected]31a2bfe2010-02-09 08:03:392678 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2679 data_writes1, arraysize(data_writes1));
2680 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2681 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592682 session_deps.socket_factory.AddSocketDataProvider(&data1);
2683 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232684
2685 TestCompletionCallback callback1;
2686
[email protected]5a1d7ca2010-04-28 20:12:272687 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422688 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232689
2690 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422691 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232692
[email protected]1c773ea12009-04-28 19:58:422693 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232694 EXPECT_FALSE(response == NULL);
2695
2696 // The password prompt info should have been set in
2697 // response->auth_challenge.
2698 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2699
[email protected]71e4573a2009-05-21 22:03:002700 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232701 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2702 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2703
2704 TestCompletionCallback callback2;
2705
2706 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422707 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232708
2709 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422710 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232711
2712 response = trans->GetResponseInfo();
2713 EXPECT_FALSE(response == NULL);
2714 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2715 EXPECT_EQ(100, response->headers->GetContentLength());
2716 }
2717
2718 // ------------------------------------------------------------------------
2719
2720 // Transaction 3: Resend a request in MyRealm's protection space --
2721 // succeed with preemptive authorization.
2722 {
[email protected]5695b8c2009-09-30 21:36:432723 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232724
[email protected]1c773ea12009-04-28 19:58:422725 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232726 request.method = "GET";
2727 request.url = GURL("http://www.google.com/x/y/z2");
2728 request.load_flags = 0;
2729
2730 MockWrite data_writes1[] = {
2731 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2732 "Host: www.google.com\r\n"
2733 "Connection: keep-alive\r\n"
2734 // The authorization for MyRealm1 gets sent preemptively
2735 // (since the url is in the same protection space)
2736 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2737 };
2738
2739 // Sever accepts the preemptive authorization
2740 MockRead data_reads1[] = {
2741 MockRead("HTTP/1.0 200 OK\r\n"),
2742 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422743 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232744 };
2745
[email protected]31a2bfe2010-02-09 08:03:392746 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2747 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592748 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232749
2750 TestCompletionCallback callback1;
2751
[email protected]5a1d7ca2010-04-28 20:12:272752 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422753 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232754
2755 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422756 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232757
[email protected]1c773ea12009-04-28 19:58:422758 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232759 EXPECT_FALSE(response == NULL);
2760
2761 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2762 EXPECT_EQ(100, response->headers->GetContentLength());
2763 }
2764
2765 // ------------------------------------------------------------------------
2766
2767 // Transaction 4: request another URL in MyRealm (however the
2768 // url is not known to belong to the protection space, so no pre-auth).
2769 {
[email protected]5695b8c2009-09-30 21:36:432770 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232771
[email protected]1c773ea12009-04-28 19:58:422772 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232773 request.method = "GET";
2774 request.url = GURL("http://www.google.com/x/1");
2775 request.load_flags = 0;
2776
2777 MockWrite data_writes1[] = {
2778 MockWrite("GET /x/1 HTTP/1.1\r\n"
2779 "Host: www.google.com\r\n"
2780 "Connection: keep-alive\r\n\r\n"),
2781 };
2782
2783 MockRead data_reads1[] = {
2784 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2785 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2786 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422787 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232788 };
2789
2790 // Resend with authorization from MyRealm's cache.
2791 MockWrite data_writes2[] = {
2792 MockWrite("GET /x/1 HTTP/1.1\r\n"
2793 "Host: www.google.com\r\n"
2794 "Connection: keep-alive\r\n"
2795 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2796 };
2797
2798 // Sever accepts the authorization.
2799 MockRead data_reads2[] = {
2800 MockRead("HTTP/1.0 200 OK\r\n"),
2801 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422802 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232803 };
2804
[email protected]31a2bfe2010-02-09 08:03:392805 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2806 data_writes1, arraysize(data_writes1));
2807 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2808 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592809 session_deps.socket_factory.AddSocketDataProvider(&data1);
2810 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232811
2812 TestCompletionCallback callback1;
2813
[email protected]5a1d7ca2010-04-28 20:12:272814 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422815 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232816
2817 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422818 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232819
[email protected]0757e7702009-03-27 04:00:222820 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2821 TestCompletionCallback callback2;
2822 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422823 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222824 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422825 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222826 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2827
[email protected]1c773ea12009-04-28 19:58:422828 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232829 EXPECT_FALSE(response == NULL);
2830 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2831 EXPECT_EQ(100, response->headers->GetContentLength());
2832 }
2833
2834 // ------------------------------------------------------------------------
2835
2836 // Transaction 5: request a URL in MyRealm, but the server rejects the
2837 // cached identity. Should invalidate and re-prompt.
2838 {
[email protected]5695b8c2009-09-30 21:36:432839 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232840
[email protected]1c773ea12009-04-28 19:58:422841 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232842 request.method = "GET";
2843 request.url = GURL("http://www.google.com/p/q/t");
2844 request.load_flags = 0;
2845
2846 MockWrite data_writes1[] = {
2847 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2848 "Host: www.google.com\r\n"
2849 "Connection: keep-alive\r\n\r\n"),
2850 };
2851
2852 MockRead data_reads1[] = {
2853 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2854 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2855 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422856 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232857 };
2858
2859 // Resend with authorization from cache for MyRealm.
2860 MockWrite data_writes2[] = {
2861 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2862 "Host: www.google.com\r\n"
2863 "Connection: keep-alive\r\n"
2864 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2865 };
2866
2867 // Sever rejects the authorization.
2868 MockRead data_reads2[] = {
2869 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2870 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2871 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422872 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232873 };
2874
2875 // At this point we should prompt for new credentials for MyRealm.
2876 // Restart with username=foo3, password=foo4.
2877 MockWrite data_writes3[] = {
2878 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2879 "Host: www.google.com\r\n"
2880 "Connection: keep-alive\r\n"
2881 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2882 };
2883
2884 // Sever accepts the authorization.
2885 MockRead data_reads3[] = {
2886 MockRead("HTTP/1.0 200 OK\r\n"),
2887 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422888 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232889 };
2890
[email protected]31a2bfe2010-02-09 08:03:392891 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2892 data_writes1, arraysize(data_writes1));
2893 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2894 data_writes2, arraysize(data_writes2));
2895 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2896 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592897 session_deps.socket_factory.AddSocketDataProvider(&data1);
2898 session_deps.socket_factory.AddSocketDataProvider(&data2);
2899 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232900
2901 TestCompletionCallback callback1;
2902
[email protected]5a1d7ca2010-04-28 20:12:272903 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422904 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232905
2906 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422907 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232908
[email protected]0757e7702009-03-27 04:00:222909 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2910 TestCompletionCallback callback2;
2911 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422912 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222913 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422914 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222915 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2916
[email protected]1c773ea12009-04-28 19:58:422917 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232918 EXPECT_FALSE(response == NULL);
2919
2920 // The password prompt info should have been set in
2921 // response->auth_challenge.
2922 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2923
[email protected]71e4573a2009-05-21 22:03:002924 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232925 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2926 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2927
[email protected]0757e7702009-03-27 04:00:222928 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232929
[email protected]0757e7702009-03-27 04:00:222930 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422931 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232932
[email protected]0757e7702009-03-27 04:00:222933 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422934 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232935
2936 response = trans->GetResponseInfo();
2937 EXPECT_FALSE(response == NULL);
2938 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2939 EXPECT_EQ(100, response->headers->GetContentLength());
2940 }
2941}
[email protected]89ceba9a2009-03-21 03:46:062942
2943// Test the ResetStateForRestart() private method.
2944TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2945 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592946 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402947 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432948 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062949
2950 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062951 trans->read_buf_ = new IOBuffer(15);
2952 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572953 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062954
2955 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142956 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572957 response->auth_challenge = new AuthChallengeInfo();
2958 response->ssl_info.cert_status = -15;
2959 response->response_time = base::Time::Now();
2960 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062961
2962 { // Setup state for response_.vary_data
2963 HttpRequestInfo request;
2964 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2965 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572966 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:432967 request.extra_headers.SetHeader("Foo", "1");
2968 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:572969 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062970 }
2971
2972 // Cause the above state to be reset.
2973 trans->ResetStateForRestart();
2974
2975 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072976 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062977 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572978 EXPECT_EQ(0U, trans->request_headers_.size());
2979 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2980 EXPECT_TRUE(response->headers.get() == NULL);
2981 EXPECT_EQ(false, response->was_cached);
2982 EXPECT_EQ(0, response->ssl_info.cert_status);
2983 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062984}
2985
[email protected]bacff652009-03-31 17:50:332986// Test HTTPS connections to a site with a bad certificate
2987TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592988 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402989 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432990 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332991
2992 HttpRequestInfo request;
2993 request.method = "GET";
2994 request.url = GURL("https://www.google.com/");
2995 request.load_flags = 0;
2996
2997 MockWrite data_writes[] = {
2998 MockWrite("GET / HTTP/1.1\r\n"
2999 "Host: www.google.com\r\n"
3000 "Connection: keep-alive\r\n\r\n"),
3001 };
3002
3003 MockRead data_reads[] = {
3004 MockRead("HTTP/1.0 200 OK\r\n"),
3005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3006 MockRead("Content-Length: 100\r\n\r\n"),
3007 MockRead(false, OK),
3008 };
3009
[email protected]5ecc992a42009-11-11 01:41:593010 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393011 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3012 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593013 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3014 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333015
[email protected]5ecc992a42009-11-11 01:41:593016 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3017 session_deps.socket_factory.AddSocketDataProvider(&data);
3018 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3019 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333020
3021 TestCompletionCallback callback;
3022
[email protected]5a1d7ca2010-04-28 20:12:273023 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333024 EXPECT_EQ(ERR_IO_PENDING, rv);
3025
3026 rv = callback.WaitForResult();
3027 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3028
3029 rv = trans->RestartIgnoringLastError(&callback);
3030 EXPECT_EQ(ERR_IO_PENDING, rv);
3031
3032 rv = callback.WaitForResult();
3033 EXPECT_EQ(OK, rv);
3034
3035 const HttpResponseInfo* response = trans->GetResponseInfo();
3036
3037 EXPECT_FALSE(response == NULL);
3038 EXPECT_EQ(100, response->headers->GetContentLength());
3039}
3040
3041// Test HTTPS connections to a site with a bad certificate, going through a
3042// proxy
3043TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593044 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333045
3046 HttpRequestInfo request;
3047 request.method = "GET";
3048 request.url = GURL("https://www.google.com/");
3049 request.load_flags = 0;
3050
3051 MockWrite proxy_writes[] = {
3052 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453053 "Host: www.google.com\r\n"
3054 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333055 };
3056
3057 MockRead proxy_reads[] = {
3058 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423059 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333060 };
3061
3062 MockWrite data_writes[] = {
3063 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453064 "Host: www.google.com\r\n"
3065 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333066 MockWrite("GET / HTTP/1.1\r\n"
3067 "Host: www.google.com\r\n"
3068 "Connection: keep-alive\r\n\r\n"),
3069 };
3070
3071 MockRead data_reads[] = {
3072 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3073 MockRead("HTTP/1.0 200 OK\r\n"),
3074 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3075 MockRead("Content-Length: 100\r\n\r\n"),
3076 MockRead(false, OK),
3077 };
3078
[email protected]31a2bfe2010-02-09 08:03:393079 StaticSocketDataProvider ssl_bad_certificate(
3080 proxy_reads, arraysize(proxy_reads),
3081 proxy_writes, arraysize(proxy_writes));
3082 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3083 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593084 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3085 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333086
[email protected]5ecc992a42009-11-11 01:41:593087 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3088 session_deps.socket_factory.AddSocketDataProvider(&data);
3089 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3090 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333091
3092 TestCompletionCallback callback;
3093
3094 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593095 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333096
[email protected]d207a5f2009-06-04 05:28:403097 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433098 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333099
[email protected]5a1d7ca2010-04-28 20:12:273100 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333101 EXPECT_EQ(ERR_IO_PENDING, rv);
3102
3103 rv = callback.WaitForResult();
3104 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3105
3106 rv = trans->RestartIgnoringLastError(&callback);
3107 EXPECT_EQ(ERR_IO_PENDING, rv);
3108
3109 rv = callback.WaitForResult();
3110 EXPECT_EQ(OK, rv);
3111
3112 const HttpResponseInfo* response = trans->GetResponseInfo();
3113
3114 EXPECT_FALSE(response == NULL);
3115 EXPECT_EQ(100, response->headers->GetContentLength());
3116 }
3117}
3118
[email protected]1c773ea12009-04-28 19:58:423119TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593120 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403121 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433122 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423123
3124 HttpRequestInfo request;
3125 request.method = "GET";
3126 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433127 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3128 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423129
3130 MockWrite data_writes[] = {
3131 MockWrite("GET / HTTP/1.1\r\n"
3132 "Host: www.google.com\r\n"
3133 "Connection: keep-alive\r\n"
3134 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3135 };
3136
3137 // Lastly, the server responds with the actual content.
3138 MockRead data_reads[] = {
3139 MockRead("HTTP/1.0 200 OK\r\n"),
3140 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3141 MockRead("Content-Length: 100\r\n\r\n"),
3142 MockRead(false, OK),
3143 };
3144
[email protected]31a2bfe2010-02-09 08:03:393145 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3146 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593147 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423148
3149 TestCompletionCallback callback;
3150
[email protected]5a1d7ca2010-04-28 20:12:273151 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423152 EXPECT_EQ(ERR_IO_PENDING, rv);
3153
3154 rv = callback.WaitForResult();
3155 EXPECT_EQ(OK, rv);
3156}
3157
3158TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593159 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403160 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433161 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423162
3163 HttpRequestInfo request;
3164 request.method = "GET";
3165 request.url = GURL("http://www.google.com/");
3166 request.load_flags = 0;
3167 request.referrer = GURL("http://the.previous.site.com/");
3168
3169 MockWrite data_writes[] = {
3170 MockWrite("GET / HTTP/1.1\r\n"
3171 "Host: www.google.com\r\n"
3172 "Connection: keep-alive\r\n"
3173 "Referer: http://the.previous.site.com/\r\n\r\n"),
3174 };
3175
3176 // Lastly, the server responds with the actual content.
3177 MockRead data_reads[] = {
3178 MockRead("HTTP/1.0 200 OK\r\n"),
3179 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3180 MockRead("Content-Length: 100\r\n\r\n"),
3181 MockRead(false, OK),
3182 };
3183
[email protected]31a2bfe2010-02-09 08:03:393184 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3185 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593186 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423187
3188 TestCompletionCallback callback;
3189
[email protected]5a1d7ca2010-04-28 20:12:273190 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423191 EXPECT_EQ(ERR_IO_PENDING, rv);
3192
3193 rv = callback.WaitForResult();
3194 EXPECT_EQ(OK, rv);
3195}
3196
3197TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593198 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403199 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433200 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423201
3202 HttpRequestInfo request;
3203 request.method = "POST";
3204 request.url = GURL("http://www.google.com/");
3205
3206 MockWrite data_writes[] = {
3207 MockWrite("POST / HTTP/1.1\r\n"
3208 "Host: www.google.com\r\n"
3209 "Connection: keep-alive\r\n"
3210 "Content-Length: 0\r\n\r\n"),
3211 };
3212
3213 // Lastly, the server responds with the actual content.
3214 MockRead data_reads[] = {
3215 MockRead("HTTP/1.0 200 OK\r\n"),
3216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3217 MockRead("Content-Length: 100\r\n\r\n"),
3218 MockRead(false, OK),
3219 };
3220
[email protected]31a2bfe2010-02-09 08:03:393221 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3222 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593223 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423224
3225 TestCompletionCallback callback;
3226
[email protected]5a1d7ca2010-04-28 20:12:273227 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423228 EXPECT_EQ(ERR_IO_PENDING, rv);
3229
3230 rv = callback.WaitForResult();
3231 EXPECT_EQ(OK, rv);
3232}
3233
3234TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593235 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403236 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433237 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423238
3239 HttpRequestInfo request;
3240 request.method = "PUT";
3241 request.url = GURL("http://www.google.com/");
3242
3243 MockWrite data_writes[] = {
3244 MockWrite("PUT / HTTP/1.1\r\n"
3245 "Host: www.google.com\r\n"
3246 "Connection: keep-alive\r\n"
3247 "Content-Length: 0\r\n\r\n"),
3248 };
3249
3250 // Lastly, the server responds with the actual content.
3251 MockRead data_reads[] = {
3252 MockRead("HTTP/1.0 200 OK\r\n"),
3253 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3254 MockRead("Content-Length: 100\r\n\r\n"),
3255 MockRead(false, OK),
3256 };
3257
[email protected]31a2bfe2010-02-09 08:03:393258 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3259 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593260 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423261
3262 TestCompletionCallback callback;
3263
[email protected]5a1d7ca2010-04-28 20:12:273264 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423265 EXPECT_EQ(ERR_IO_PENDING, rv);
3266
3267 rv = callback.WaitForResult();
3268 EXPECT_EQ(OK, rv);
3269}
3270
3271TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593272 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403273 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433274 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423275
3276 HttpRequestInfo request;
3277 request.method = "HEAD";
3278 request.url = GURL("http://www.google.com/");
3279
3280 MockWrite data_writes[] = {
3281 MockWrite("HEAD / HTTP/1.1\r\n"
3282 "Host: www.google.com\r\n"
3283 "Connection: keep-alive\r\n"
3284 "Content-Length: 0\r\n\r\n"),
3285 };
3286
3287 // Lastly, the server responds with the actual content.
3288 MockRead data_reads[] = {
3289 MockRead("HTTP/1.0 200 OK\r\n"),
3290 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3291 MockRead("Content-Length: 100\r\n\r\n"),
3292 MockRead(false, OK),
3293 };
3294
[email protected]31a2bfe2010-02-09 08:03:393295 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3296 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593297 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423298
3299 TestCompletionCallback callback;
3300
[email protected]5a1d7ca2010-04-28 20:12:273301 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423302 EXPECT_EQ(ERR_IO_PENDING, rv);
3303
3304 rv = callback.WaitForResult();
3305 EXPECT_EQ(OK, rv);
3306}
3307
3308TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593309 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403310 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433311 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423312
3313 HttpRequestInfo request;
3314 request.method = "GET";
3315 request.url = GURL("http://www.google.com/");
3316 request.load_flags = LOAD_BYPASS_CACHE;
3317
3318 MockWrite data_writes[] = {
3319 MockWrite("GET / HTTP/1.1\r\n"
3320 "Host: www.google.com\r\n"
3321 "Connection: keep-alive\r\n"
3322 "Pragma: no-cache\r\n"
3323 "Cache-Control: no-cache\r\n\r\n"),
3324 };
3325
3326 // Lastly, the server responds with the actual content.
3327 MockRead data_reads[] = {
3328 MockRead("HTTP/1.0 200 OK\r\n"),
3329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3330 MockRead("Content-Length: 100\r\n\r\n"),
3331 MockRead(false, OK),
3332 };
3333
[email protected]31a2bfe2010-02-09 08:03:393334 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3335 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593336 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423337
3338 TestCompletionCallback callback;
3339
[email protected]5a1d7ca2010-04-28 20:12:273340 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423341 EXPECT_EQ(ERR_IO_PENDING, rv);
3342
3343 rv = callback.WaitForResult();
3344 EXPECT_EQ(OK, rv);
3345}
3346
3347TEST_F(HttpNetworkTransactionTest,
3348 BuildRequest_CacheControlValidateCache) {
[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_VALIDATE_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 "Cache-Control: max-age=0\r\n\r\n"),
3363 };
3364
3365 // Lastly, the server responds with the actual content.
3366 MockRead data_reads[] = {
3367 MockRead("HTTP/1.0 200 OK\r\n"),
3368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3369 MockRead("Content-Length: 100\r\n\r\n"),
3370 MockRead(false, OK),
3371 };
3372
[email protected]31a2bfe2010-02-09 08:03:393373 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3374 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593375 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423376
3377 TestCompletionCallback callback;
3378
[email protected]5a1d7ca2010-04-28 20:12:273379 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423380 EXPECT_EQ(ERR_IO_PENDING, rv);
3381
3382 rv = callback.WaitForResult();
3383 EXPECT_EQ(OK, rv);
3384}
3385
3386TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593387 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403388 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433389 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423390
3391 HttpRequestInfo request;
3392 request.method = "GET";
3393 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433394 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423395
3396 MockWrite data_writes[] = {
3397 MockWrite("GET / HTTP/1.1\r\n"
3398 "Host: www.google.com\r\n"
3399 "Connection: keep-alive\r\n"
3400 "FooHeader: Bar\r\n\r\n"),
3401 };
3402
3403 // Lastly, the server responds with the actual content.
3404 MockRead data_reads[] = {
3405 MockRead("HTTP/1.0 200 OK\r\n"),
3406 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3407 MockRead("Content-Length: 100\r\n\r\n"),
3408 MockRead(false, OK),
3409 };
3410
[email protected]31a2bfe2010-02-09 08:03:393411 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3412 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593413 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423414
3415 TestCompletionCallback callback;
3416
[email protected]5a1d7ca2010-04-28 20:12:273417 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423418 EXPECT_EQ(ERR_IO_PENDING, rv);
3419
3420 rv = callback.WaitForResult();
3421 EXPECT_EQ(OK, rv);
3422}
3423
[email protected]270c6412010-03-29 22:02:473424TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3425 SessionDependencies session_deps;
3426 scoped_ptr<HttpTransaction> trans(
3427 new HttpNetworkTransaction(CreateSession(&session_deps)));
3428
3429 HttpRequestInfo request;
3430 request.method = "GET";
3431 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433432 request.extra_headers.SetHeader("referer", "www.foo.com");
3433 request.extra_headers.SetHeader("hEllo", "Kitty");
3434 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473435
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 "hEllo: Kitty\r\n"
3441 "FoO: bar\r\n\r\n"),
3442 };
3443
3444 // Lastly, the server responds with the actual content.
3445 MockRead data_reads[] = {
3446 MockRead("HTTP/1.0 200 OK\r\n"),
3447 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3448 MockRead("Content-Length: 100\r\n\r\n"),
3449 MockRead(false, OK),
3450 };
3451
3452 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3453 data_writes, arraysize(data_writes));
3454 session_deps.socket_factory.AddSocketDataProvider(&data);
3455
3456 TestCompletionCallback callback;
3457
[email protected]5a1d7ca2010-04-28 20:12:273458 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473459 EXPECT_EQ(ERR_IO_PENDING, rv);
3460
3461 rv = callback.WaitForResult();
3462 EXPECT_EQ(OK, rv);
3463}
3464
[email protected]3cd17242009-06-23 02:59:023465TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093466 SessionDependencies session_deps(
3467 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023468
3469 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433470 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023471
3472 HttpRequestInfo request;
3473 request.method = "GET";
3474 request.url = GURL("http://www.google.com/");
3475 request.load_flags = 0;
3476
3477 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3478 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3479
3480 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353481 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023482 MockWrite("GET / HTTP/1.1\r\n"
3483 "Host: www.google.com\r\n"
3484 "Connection: keep-alive\r\n\r\n")
3485 };
3486
3487 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593488 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023489 MockRead("HTTP/1.0 200 OK\r\n"),
3490 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3491 MockRead("Payload"),
3492 MockRead(false, OK)
3493 };
3494
[email protected]31a2bfe2010-02-09 08:03:393495 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3496 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593497 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023498
3499 TestCompletionCallback callback;
3500
[email protected]5a1d7ca2010-04-28 20:12:273501 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023502 EXPECT_EQ(ERR_IO_PENDING, rv);
3503
3504 rv = callback.WaitForResult();
3505 EXPECT_EQ(OK, rv);
3506
3507 const HttpResponseInfo* response = trans->GetResponseInfo();
3508 EXPECT_FALSE(response == NULL);
3509
3510 std::string response_text;
3511 rv = ReadTransaction(trans.get(), &response_text);
3512 EXPECT_EQ(OK, rv);
3513 EXPECT_EQ("Payload", response_text);
3514}
3515
3516TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093517 SessionDependencies session_deps(
3518 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023519
3520 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433521 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023522
3523 HttpRequestInfo request;
3524 request.method = "GET";
3525 request.url = GURL("https://www.google.com/");
3526 request.load_flags = 0;
3527
3528 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3529 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3530
3531 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353532 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3533 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023534 MockWrite("GET / HTTP/1.1\r\n"
3535 "Host: www.google.com\r\n"
3536 "Connection: keep-alive\r\n\r\n")
3537 };
3538
3539 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353540 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3541 arraysize(read_buffer)),
3542 MockRead("HTTP/1.0 200 OK\r\n"),
3543 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3544 MockRead("Payload"),
3545 MockRead(false, OK)
3546 };
3547
[email protected]31a2bfe2010-02-09 08:03:393548 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3549 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593550 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353551
[email protected]5ecc992a42009-11-11 01:41:593552 SSLSocketDataProvider ssl(true, OK);
3553 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353554
3555 TestCompletionCallback callback;
3556
[email protected]5a1d7ca2010-04-28 20:12:273557 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353558 EXPECT_EQ(ERR_IO_PENDING, rv);
3559
3560 rv = callback.WaitForResult();
3561 EXPECT_EQ(OK, rv);
3562
3563 const HttpResponseInfo* response = trans->GetResponseInfo();
3564 EXPECT_FALSE(response == NULL);
3565
3566 std::string response_text;
3567 rv = ReadTransaction(trans.get(), &response_text);
3568 EXPECT_EQ(OK, rv);
3569 EXPECT_EQ("Payload", response_text);
3570}
3571
3572TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093573 SessionDependencies session_deps(
3574 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353575
3576 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433577 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353578
3579 HttpRequestInfo request;
3580 request.method = "GET";
3581 request.url = GURL("http://www.google.com/");
3582 request.load_flags = 0;
3583
3584 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3585 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373586 const char kSOCKS5OkRequest[] = {
3587 0x05, // Version
3588 0x01, // Command (CONNECT)
3589 0x00, // Reserved.
3590 0x03, // Address type (DOMAINNAME).
3591 0x0E, // Length of domain (14)
3592 // Domain string:
3593 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3594 0x00, 0x50, // 16-bit port (80)
3595 };
[email protected]e0c27be2009-07-15 13:09:353596 const char kSOCKS5OkResponse[] =
3597 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3598
3599 MockWrite data_writes[] = {
3600 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3601 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3602 MockWrite("GET / HTTP/1.1\r\n"
3603 "Host: www.google.com\r\n"
3604 "Connection: keep-alive\r\n\r\n")
3605 };
3606
3607 MockRead data_reads[] = {
3608 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3609 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3610 MockRead("HTTP/1.0 200 OK\r\n"),
3611 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3612 MockRead("Payload"),
3613 MockRead(false, OK)
3614 };
3615
[email protected]31a2bfe2010-02-09 08:03:393616 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3617 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593618 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353619
3620 TestCompletionCallback callback;
3621
[email protected]5a1d7ca2010-04-28 20:12:273622 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353623 EXPECT_EQ(ERR_IO_PENDING, rv);
3624
3625 rv = callback.WaitForResult();
3626 EXPECT_EQ(OK, rv);
3627
3628 const HttpResponseInfo* response = trans->GetResponseInfo();
3629 EXPECT_FALSE(response == NULL);
3630
3631 std::string response_text;
3632 rv = ReadTransaction(trans.get(), &response_text);
3633 EXPECT_EQ(OK, rv);
3634 EXPECT_EQ("Payload", response_text);
3635}
3636
3637TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093638 SessionDependencies session_deps(
3639 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353640
3641 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433642 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353643
3644 HttpRequestInfo request;
3645 request.method = "GET";
3646 request.url = GURL("https://www.google.com/");
3647 request.load_flags = 0;
3648
3649 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3650 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373651 const unsigned char kSOCKS5OkRequest[] = {
3652 0x05, // Version
3653 0x01, // Command (CONNECT)
3654 0x00, // Reserved.
3655 0x03, // Address type (DOMAINNAME).
3656 0x0E, // Length of domain (14)
3657 // Domain string:
3658 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3659 0x01, 0xBB, // 16-bit port (443)
3660 };
3661
[email protected]e0c27be2009-07-15 13:09:353662 const char kSOCKS5OkResponse[] =
3663 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3664
3665 MockWrite data_writes[] = {
3666 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3667 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3668 arraysize(kSOCKS5OkRequest)),
3669 MockWrite("GET / HTTP/1.1\r\n"
3670 "Host: www.google.com\r\n"
3671 "Connection: keep-alive\r\n\r\n")
3672 };
3673
3674 MockRead data_reads[] = {
3675 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3676 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023677 MockRead("HTTP/1.0 200 OK\r\n"),
3678 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3679 MockRead("Payload"),
3680 MockRead(false, OK)
3681 };
3682
[email protected]31a2bfe2010-02-09 08:03:393683 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3684 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593685 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023686
[email protected]5ecc992a42009-11-11 01:41:593687 SSLSocketDataProvider ssl(true, OK);
3688 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023689
3690 TestCompletionCallback callback;
3691
[email protected]5a1d7ca2010-04-28 20:12:273692 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023693 EXPECT_EQ(ERR_IO_PENDING, rv);
3694
3695 rv = callback.WaitForResult();
3696 EXPECT_EQ(OK, rv);
3697
3698 const HttpResponseInfo* response = trans->GetResponseInfo();
3699 EXPECT_FALSE(response == NULL);
3700
3701 std::string response_text;
3702 rv = ReadTransaction(trans.get(), &response_text);
3703 EXPECT_EQ(OK, rv);
3704 EXPECT_EQ("Payload", response_text);
3705}
3706
[email protected]04e5be32009-06-26 20:00:313707// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063708
3709struct GroupNameTest {
3710 std::string proxy_server;
3711 std::string url;
3712 std::string expected_group_name;
3713};
3714
3715scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3716 const std::string& proxy_server) {
3717 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3718 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3719
3720 HttpAlternateProtocols* alternate_protocols =
3721 session->mutable_alternate_protocols();
3722 alternate_protocols->SetAlternateProtocolFor(
3723 HostPortPair("host.with.alternate", 80), 443,
3724 HttpAlternateProtocols::NPN_SPDY_1);
3725
3726 return session;
3727}
3728
3729int GroupNameTransactionHelper(
3730 const std::string& url,
3731 const scoped_refptr<HttpNetworkSession>& session) {
3732 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3733
3734 HttpRequestInfo request;
3735 request.method = "GET";
3736 request.url = GURL(url);
3737 request.load_flags = 0;
3738
3739 TestCompletionCallback callback;
3740
3741 // We do not complete this request, the dtor will clean the transaction up.
3742 return trans->Start(&request, &callback, BoundNetLog());
3743}
3744
3745TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
3746 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:313747 {
[email protected]2d731a32010-04-29 01:04:063748 "", // unused
[email protected]04e5be32009-06-26 20:00:313749 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:543750 "www.google.com:80",
3751 },
3752 {
[email protected]2d731a32010-04-29 01:04:063753 "", // unused
[email protected]2ff8b312010-04-26 22:20:543754 "http://[2001:1418:13:1::25]/direct",
3755 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:313756 },
[email protected]04e5be32009-06-26 20:00:313757
3758 // SSL Tests
3759 {
[email protected]2d731a32010-04-29 01:04:063760 "", // unused
[email protected]04e5be32009-06-26 20:00:313761 "https://www.google.com/direct_ssl",
[email protected]2ff8b312010-04-26 22:20:543762 "www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313763 },
3764 {
[email protected]2d731a32010-04-29 01:04:063765 "", // unused
3766 "https://[2001:1418:13:1::25]/direct",
3767 "[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:313768 },
3769 {
[email protected]2d731a32010-04-29 01:04:063770 "", // unused
[email protected]2ff8b312010-04-26 22:20:543771 "http://host.with.alternate/direct",
3772 "host.with.alternate:443",
3773 },
[email protected]2d731a32010-04-29 01:04:063774 };
[email protected]2ff8b312010-04-26 22:20:543775
[email protected]2d731a32010-04-29 01:04:063776 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3777
3778 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3779 scoped_refptr<HttpNetworkSession> session(
3780 SetupSessionForGroupNameTests(tests[i].proxy_server));
3781
3782 HttpNetworkSessionPeer peer(session);
3783 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3784 new CaptureGroupNameTCPSocketPool(session.get()));
3785 peer.SetTCPSocketPool(tcp_conn_pool);
3786
3787 EXPECT_EQ(ERR_IO_PENDING,
3788 GroupNameTransactionHelper(tests[i].url, session));
3789 EXPECT_EQ(tests[i].expected_group_name,
3790 tcp_conn_pool->last_group_name_received());
3791 }
3792
3793 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3794}
3795
3796TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
3797 const GroupNameTest tests[] = {
3798 {
3799 "http_proxy",
3800 "http://www.google.com/http_proxy_normal",
3801 "www.google.com:80",
3802 },
3803
3804 // SSL Tests
3805 {
3806 "http_proxy",
3807 "https://www.google.com/http_connect_ssl",
3808 "www.google.com:443",
3809 },
3810
[email protected]9faeded92010-04-29 20:03:053811 {
3812 "http_proxy",
3813 "http://host.with.alternate/direct",
3814 "host.with.alternate:443",
3815 },
[email protected]2d731a32010-04-29 01:04:063816 };
3817
3818 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3819
3820 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3821 scoped_refptr<HttpNetworkSession> session(
3822 SetupSessionForGroupNameTests(tests[i].proxy_server));
3823
3824 HttpNetworkSessionPeer peer(session);
3825
3826 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
3827 new CaptureGroupNameTCPSocketPool(session.get()));
3828 peer.SetSocketPoolForHTTPProxy(
3829 HostPortPair("http_proxy", 80), http_proxy_pool);
3830
3831 EXPECT_EQ(ERR_IO_PENDING,
3832 GroupNameTransactionHelper(tests[i].url, session));
3833 EXPECT_EQ(tests[i].expected_group_name,
3834 http_proxy_pool->last_group_name_received());
3835 }
3836
3837 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3838}
3839
3840TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
3841 const GroupNameTest tests[] = {
3842 {
3843 "socks4://socks_proxy:1080",
3844 "http://www.google.com/socks4_direct",
3845 "socks4/www.google.com:80",
3846 },
3847 {
3848 "socks5://socks_proxy:1080",
3849 "http://www.google.com/socks5_direct",
3850 "socks5/www.google.com:80",
3851 },
3852
3853 // SSL Tests
3854 {
3855 "socks4://socks_proxy:1080",
3856 "https://www.google.com/socks4_ssl",
3857 "socks4/www.google.com:443",
3858 },
3859 {
3860 "socks5://socks_proxy:1080",
3861 "https://www.google.com/socks5_ssl",
3862 "socks5/www.google.com:443",
3863 },
3864
[email protected]9faeded92010-04-29 20:03:053865 {
3866 "socks4://socks_proxy:1080",
3867 "http://host.with.alternate/direct",
3868 "socks4/host.with.alternate:443",
3869 },
[email protected]04e5be32009-06-26 20:00:313870 };
3871
[email protected]2ff8b312010-04-26 22:20:543872 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3873
[email protected]04e5be32009-06-26 20:00:313874 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:063875 scoped_refptr<HttpNetworkSession> session(
3876 SetupSessionForGroupNameTests(tests[i].proxy_server));
3877 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:313878
[email protected]a796bcec2010-03-22 17:17:263879 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:063880 new CaptureGroupNameSOCKSSocketPool(session.get()));
3881 peer.SetSocketPoolForSOCKSProxy(
3882 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:313883
[email protected]5695b8c2009-09-30 21:36:433884 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313885
[email protected]2d731a32010-04-29 01:04:063886 EXPECT_EQ(ERR_IO_PENDING,
3887 GroupNameTransactionHelper(tests[i].url, session));
3888 EXPECT_EQ(tests[i].expected_group_name,
3889 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:313890 }
[email protected]2ff8b312010-04-26 22:20:543891
3892 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:313893}
3894
[email protected]9172a982009-06-06 00:30:253895TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543896 SessionDependencies session_deps(
3897 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323898
[email protected]69719062010-01-05 20:09:213899 // This simulates failure resolving all hostnames; that means we will fail
3900 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323901 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3902
[email protected]9172a982009-06-06 00:30:253903 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433904 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253905
3906 HttpRequestInfo request;
3907 request.method = "GET";
3908 request.url = GURL("http://www.google.com/");
3909
3910 TestCompletionCallback callback;
3911
[email protected]5a1d7ca2010-04-28 20:12:273912 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:253913 EXPECT_EQ(ERR_IO_PENDING, rv);
3914
[email protected]9172a982009-06-06 00:30:253915 rv = callback.WaitForResult();
3916 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3917}
3918
[email protected]f3e6c1e2009-06-15 20:52:123919// Host resolution observer used by
3920// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3921// resovle requests are issued with a referrer of |expected_referrer|.
3922class ResolutionReferrerObserver : public HostResolver::Observer {
3923 public:
3924 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3925 : expected_referrer_(expected_referrer),
3926 called_start_with_referrer_(false),
3927 called_finish_with_referrer_(false) {
3928 }
3929
3930 virtual void OnStartResolution(int id,
3931 const HostResolver::RequestInfo& info) {
3932 if (info.referrer() == expected_referrer_)
3933 called_start_with_referrer_ = true;
3934 }
3935
3936 virtual void OnFinishResolutionWithStatus(
3937 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3938 if (info.referrer() == expected_referrer_)
3939 called_finish_with_referrer_ = true;
3940 }
3941
[email protected]eb255d32009-06-17 02:11:033942 virtual void OnCancelResolution(int id,
3943 const HostResolver::RequestInfo& info ) {
3944 FAIL() << "Should not be cancelling any requests!";
3945 }
3946
[email protected]f3e6c1e2009-06-15 20:52:123947 bool did_complete_with_expected_referrer() const {
3948 return called_start_with_referrer_ && called_finish_with_referrer_;
3949 }
3950
3951 private:
3952 GURL expected_referrer_;
3953 bool called_start_with_referrer_;
3954 bool called_finish_with_referrer_;
3955
3956 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3957};
3958
3959// Make sure that when HostResolver::Resolve() is invoked, it passes through
3960// the "referrer". This is depended on by the DNS prefetch observer.
3961TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3962 GURL referrer = GURL("http://expected-referrer/");
3963 EXPECT_TRUE(referrer.is_valid());
3964 ResolutionReferrerObserver resolution_observer(referrer);
3965
3966 SessionDependencies session_deps;
3967 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433968 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123969
3970 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143971 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123972
3973 // Connect up a mock socket which will fail when reading.
3974 MockRead data_reads[] = {
3975 MockRead(false, ERR_FAILED),
3976 };
[email protected]31a2bfe2010-02-09 08:03:393977 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593978 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123979
3980 // Issue a request, containing an HTTP referrer.
3981 HttpRequestInfo request;
3982 request.method = "GET";
3983 request.referrer = referrer;
3984 request.url = GURL("http://www.google.com/");
3985
3986 // Run the request until it fails reading from the socket.
3987 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:273988 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:123989 EXPECT_EQ(ERR_IO_PENDING, rv);
3990 rv = callback.WaitForResult();
3991 EXPECT_EQ(ERR_FAILED, rv);
3992
3993 // Check that the host resolution observer saw |referrer|.
3994 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3995}
3996
[email protected]3b9cca42009-06-16 01:08:283997// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3998// host cache is bypassed.
3999TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
4000 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324001
[email protected]a2c2fb92009-07-18 07:31:044002 // Select a host resolver that does caching.
4003 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324004
[email protected]3b9cca42009-06-16 01:08:284005 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434006 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284007
4008 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4009 // a synchronous lookup.)
4010 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144011 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464012 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274013 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284014 EXPECT_EQ(OK, rv);
4015
4016 // Verify that it was added to host cache, by doing a subsequent async lookup
4017 // and confirming it completes synchronously.
4018 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464019 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284020 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274021 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324022 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284023
4024 // Inject a failure the next time that "www.google.com" is resolved. This way
4025 // we can tell if the next lookup hit the cache, or the "network".
4026 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324027 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284028
4029 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4030 // first read -- this won't be reached as the host resolution will fail first.
4031 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394032 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594033 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284034
4035 // Issue a request, asking to bypass the cache(s).
4036 HttpRequestInfo request;
4037 request.method = "GET";
4038 request.load_flags = LOAD_BYPASS_CACHE;
4039 request.url = GURL("http://www.google.com/");
4040
4041 // Run the request.
4042 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274043 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284044 ASSERT_EQ(ERR_IO_PENDING, rv);
4045 rv = callback.WaitForResult();
4046
4047 // If we bypassed the cache, we would have gotten a failure while resolving
4048 // "www.google.com".
4049 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4050}
4051
[email protected]0877e3d2009-10-17 22:29:574052// Make sure we can handle an error when writing the request.
4053TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4054 SessionDependencies session_deps;
4055 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4056
4057 HttpRequestInfo request;
4058 request.method = "GET";
4059 request.url = GURL("http://www.foo.com/");
4060 request.load_flags = 0;
4061
4062 MockWrite write_failure[] = {
4063 MockWrite(true, ERR_CONNECTION_RESET),
4064 };
[email protected]31a2bfe2010-02-09 08:03:394065 StaticSocketDataProvider data(NULL, 0,
4066 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594067 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574068
4069 TestCompletionCallback callback;
4070
4071 scoped_ptr<HttpTransaction> trans(
4072 new HttpNetworkTransaction(CreateSession(&session_deps)));
4073
[email protected]5a1d7ca2010-04-28 20:12:274074 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574075 EXPECT_EQ(ERR_IO_PENDING, rv);
4076
4077 rv = callback.WaitForResult();
4078 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4079}
4080
4081// Check that a connection closed after the start of the headers finishes ok.
4082TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4083 SessionDependencies session_deps;
4084 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4085
4086 HttpRequestInfo request;
4087 request.method = "GET";
4088 request.url = GURL("http://www.foo.com/");
4089 request.load_flags = 0;
4090
4091 MockRead data_reads[] = {
4092 MockRead("HTTP/1."),
4093 MockRead(false, OK),
4094 };
4095
[email protected]31a2bfe2010-02-09 08:03:394096 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594097 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574098
4099 TestCompletionCallback callback;
4100
4101 scoped_ptr<HttpTransaction> trans(
4102 new HttpNetworkTransaction(CreateSession(&session_deps)));
4103
[email protected]5a1d7ca2010-04-28 20:12:274104 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574105 EXPECT_EQ(ERR_IO_PENDING, rv);
4106
4107 rv = callback.WaitForResult();
4108 EXPECT_EQ(OK, rv);
4109
4110 const HttpResponseInfo* response = trans->GetResponseInfo();
4111 EXPECT_TRUE(response != NULL);
4112
4113 EXPECT_TRUE(response->headers != NULL);
4114 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4115
4116 std::string response_data;
4117 rv = ReadTransaction(trans.get(), &response_data);
4118 EXPECT_EQ(OK, rv);
4119 EXPECT_EQ("", response_data);
4120}
4121
4122// Make sure that a dropped connection while draining the body for auth
4123// restart does the right thing.
4124TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4125 SessionDependencies session_deps;
4126 scoped_ptr<HttpTransaction> trans(
4127 new HttpNetworkTransaction(CreateSession(&session_deps)));
4128
4129 HttpRequestInfo request;
4130 request.method = "GET";
4131 request.url = GURL("http://www.google.com/");
4132 request.load_flags = 0;
4133
4134 MockWrite data_writes1[] = {
4135 MockWrite("GET / HTTP/1.1\r\n"
4136 "Host: www.google.com\r\n"
4137 "Connection: keep-alive\r\n\r\n"),
4138 };
4139
4140 MockRead data_reads1[] = {
4141 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4142 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4143 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4144 MockRead("Content-Length: 14\r\n\r\n"),
4145 MockRead("Unauth"),
4146 MockRead(true, ERR_CONNECTION_RESET),
4147 };
4148
[email protected]31a2bfe2010-02-09 08:03:394149 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4150 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594151 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574152
4153 // After calling trans->RestartWithAuth(), this is the request we should
4154 // be issuing -- the final header line contains the credentials.
4155 MockWrite data_writes2[] = {
4156 MockWrite("GET / HTTP/1.1\r\n"
4157 "Host: www.google.com\r\n"
4158 "Connection: keep-alive\r\n"
4159 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4160 };
4161
4162 // Lastly, the server responds with the actual content.
4163 MockRead data_reads2[] = {
4164 MockRead("HTTP/1.1 200 OK\r\n"),
4165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4166 MockRead("Content-Length: 100\r\n\r\n"),
4167 MockRead(false, OK),
4168 };
4169
[email protected]31a2bfe2010-02-09 08:03:394170 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4171 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594172 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574173
4174 TestCompletionCallback callback1;
4175
[email protected]5a1d7ca2010-04-28 20:12:274176 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574177 EXPECT_EQ(ERR_IO_PENDING, rv);
4178
4179 rv = callback1.WaitForResult();
4180 EXPECT_EQ(OK, rv);
4181
4182 const HttpResponseInfo* response = trans->GetResponseInfo();
4183 EXPECT_FALSE(response == NULL);
4184
4185 // The password prompt info should have been set in response->auth_challenge.
4186 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4187
4188 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4189 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4190 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4191
4192 TestCompletionCallback callback2;
4193
4194 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4195 EXPECT_EQ(ERR_IO_PENDING, rv);
4196
4197 rv = callback2.WaitForResult();
4198 EXPECT_EQ(OK, rv);
4199
4200 response = trans->GetResponseInfo();
4201 EXPECT_FALSE(response == NULL);
4202 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4203 EXPECT_EQ(100, response->headers->GetContentLength());
4204}
4205
4206// Test HTTPS connections going through a proxy that sends extra data.
4207TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4208 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4209
4210 HttpRequestInfo request;
4211 request.method = "GET";
4212 request.url = GURL("https://www.google.com/");
4213 request.load_flags = 0;
4214
4215 MockRead proxy_reads[] = {
4216 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4217 MockRead(false, OK)
4218 };
4219
[email protected]31a2bfe2010-02-09 08:03:394220 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594221 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574222
[email protected]5ecc992a42009-11-11 01:41:594223 session_deps.socket_factory.AddSocketDataProvider(&data);
4224 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574225
4226 TestCompletionCallback callback;
4227
4228 session_deps.socket_factory.ResetNextMockIndexes();
4229
4230 scoped_ptr<HttpTransaction> trans(
4231 new HttpNetworkTransaction(CreateSession(&session_deps)));
4232
[email protected]5a1d7ca2010-04-28 20:12:274233 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574234 EXPECT_EQ(ERR_IO_PENDING, rv);
4235
4236 rv = callback.WaitForResult();
4237 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4238}
4239
[email protected]e22e1362009-11-23 21:31:124240TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464241 SessionDependencies session_deps;
4242 scoped_ptr<HttpTransaction> trans(
4243 new HttpNetworkTransaction(CreateSession(&session_deps)));
4244
4245 HttpRequestInfo request;
4246 request.method = "GET";
4247 request.url = GURL("http://www.google.com/");
4248 request.load_flags = 0;
4249
[email protected]e22e1362009-11-23 21:31:124250 MockRead data_reads[] = {
4251 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4252 MockRead(false, OK),
4253 };
[email protected]9492e4a2010-02-24 00:58:464254
4255 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4256 session_deps.socket_factory.AddSocketDataProvider(&data);
4257
4258 TestCompletionCallback callback;
4259
[email protected]5a1d7ca2010-04-28 20:12:274260 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464261 EXPECT_EQ(ERR_IO_PENDING, rv);
4262
4263 EXPECT_EQ(OK, callback.WaitForResult());
4264
4265 const HttpResponseInfo* response = trans->GetResponseInfo();
4266 EXPECT_TRUE(response != NULL);
4267
4268 EXPECT_TRUE(response->headers != NULL);
4269 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4270
4271 std::string response_data;
4272 rv = ReadTransaction(trans.get(), &response_data);
4273 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124274}
4275
[email protected]95d88ffe2010-02-04 21:25:334276TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4277 SessionDependencies session_deps;
4278 scoped_ptr<HttpTransaction> trans(
4279 new HttpNetworkTransaction(CreateSession(&session_deps)));
4280
4281 HttpRequestInfo request;
4282 request.method = "POST";
4283 request.url = GURL("http://www.google.com/upload");
4284 request.upload_data = new UploadData;
4285 request.load_flags = 0;
4286
4287 FilePath temp_file_path;
4288 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4289 const uint64 kFakeSize = 100000; // file is actually blank
4290
4291 std::vector<UploadData::Element> elements;
4292 UploadData::Element element;
4293 element.SetToFilePath(temp_file_path);
4294 element.SetContentLength(kFakeSize);
4295 elements.push_back(element);
4296 request.upload_data->set_elements(elements);
4297 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4298
4299 MockRead data_reads[] = {
4300 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4301 MockRead("hello world"),
4302 MockRead(false, OK),
4303 };
[email protected]31a2bfe2010-02-09 08:03:394304 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334305 session_deps.socket_factory.AddSocketDataProvider(&data);
4306
4307 TestCompletionCallback callback;
4308
[email protected]5a1d7ca2010-04-28 20:12:274309 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334310 EXPECT_EQ(ERR_IO_PENDING, rv);
4311
4312 rv = callback.WaitForResult();
4313 EXPECT_EQ(OK, rv);
4314
4315 const HttpResponseInfo* response = trans->GetResponseInfo();
4316 EXPECT_TRUE(response != NULL);
4317
4318 EXPECT_TRUE(response->headers != NULL);
4319 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4320
4321 std::string response_data;
4322 rv = ReadTransaction(trans.get(), &response_data);
4323 EXPECT_EQ(OK, rv);
4324 EXPECT_EQ("hello world", response_data);
4325
4326 file_util::Delete(temp_file_path, false);
4327}
4328
[email protected]6624b4622010-03-29 19:58:364329TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4330 // If we try to upload an unreadable file, the network stack should report
4331 // the file size as zero and upload zero bytes for that file.
4332 SessionDependencies session_deps;
4333 scoped_ptr<HttpTransaction> trans(
4334 new HttpNetworkTransaction(CreateSession(&session_deps)));
4335
4336 FilePath temp_file;
4337 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4338 std::string temp_file_content("Unreadable file.");
4339 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4340 temp_file_content.length()));
4341 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4342
4343 HttpRequestInfo request;
4344 request.method = "POST";
4345 request.url = GURL("http://www.google.com/upload");
4346 request.upload_data = new UploadData;
4347 request.load_flags = 0;
4348
4349 std::vector<UploadData::Element> elements;
4350 UploadData::Element element;
4351 element.SetToFilePath(temp_file);
4352 elements.push_back(element);
4353 request.upload_data->set_elements(elements);
4354
4355 MockRead data_reads[] = {
4356 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4357 MockRead(false, OK),
4358 };
4359 MockWrite data_writes[] = {
4360 MockWrite("POST /upload HTTP/1.1\r\n"
4361 "Host: www.google.com\r\n"
4362 "Connection: keep-alive\r\n"
4363 "Content-Length: 0\r\n\r\n"),
4364 MockWrite(false, OK),
4365 };
4366 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4367 arraysize(data_writes));
4368 session_deps.socket_factory.AddSocketDataProvider(&data);
4369
4370 TestCompletionCallback callback;
4371
[email protected]5a1d7ca2010-04-28 20:12:274372 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364373 EXPECT_EQ(ERR_IO_PENDING, rv);
4374
4375 rv = callback.WaitForResult();
4376 EXPECT_EQ(OK, rv);
4377
4378 const HttpResponseInfo* response = trans->GetResponseInfo();
4379 EXPECT_TRUE(response != NULL);
4380 EXPECT_TRUE(response->headers != NULL);
4381 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4382
4383 file_util::Delete(temp_file, false);
4384}
4385
4386TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4387 SessionDependencies session_deps;
4388 scoped_ptr<HttpTransaction> trans(
4389 new HttpNetworkTransaction(CreateSession(&session_deps)));
4390
4391 FilePath temp_file;
4392 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4393 std::string temp_file_contents("Unreadable file.");
4394 std::string unreadable_contents(temp_file_contents.length(), '\0');
4395 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4396 temp_file_contents.length()));
4397
4398 HttpRequestInfo request;
4399 request.method = "POST";
4400 request.url = GURL("http://www.google.com/upload");
4401 request.upload_data = new UploadData;
4402 request.load_flags = 0;
4403
4404 std::vector<UploadData::Element> elements;
4405 UploadData::Element element;
4406 element.SetToFilePath(temp_file);
4407 elements.push_back(element);
4408 request.upload_data->set_elements(elements);
4409
4410 MockRead data_reads[] = {
4411 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4412 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4413 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4414
4415 MockRead("HTTP/1.1 200 OK\r\n"),
4416 MockRead("Content-Length: 0\r\n\r\n"),
4417 MockRead(false, OK),
4418 };
4419 MockWrite data_writes[] = {
4420 MockWrite("POST /upload HTTP/1.1\r\n"
4421 "Host: www.google.com\r\n"
4422 "Connection: keep-alive\r\n"
4423 "Content-Length: 16\r\n\r\n"),
4424 MockWrite(false, temp_file_contents.c_str()),
4425
4426 MockWrite("POST /upload HTTP/1.1\r\n"
4427 "Host: www.google.com\r\n"
4428 "Connection: keep-alive\r\n"
4429 "Content-Length: 16\r\n"
4430 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4431 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4432 MockWrite(false, OK),
4433 };
4434 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4435 arraysize(data_writes));
4436 session_deps.socket_factory.AddSocketDataProvider(&data);
4437
4438 TestCompletionCallback callback1;
4439
[email protected]5a1d7ca2010-04-28 20:12:274440 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364441 EXPECT_EQ(ERR_IO_PENDING, rv);
4442
4443 rv = callback1.WaitForResult();
4444 EXPECT_EQ(OK, rv);
4445
4446 const HttpResponseInfo* response = trans->GetResponseInfo();
4447 EXPECT_TRUE(response != NULL);
4448 EXPECT_TRUE(response->headers != NULL);
4449 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4450
4451 // The password prompt info should have been set in response->auth_challenge.
4452 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4453 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4454 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4455 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4456
4457 // Now make the file unreadable and try again.
4458 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4459
4460 TestCompletionCallback callback2;
4461
4462 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4463 EXPECT_EQ(ERR_IO_PENDING, rv);
4464
4465 rv = callback2.WaitForResult();
4466 EXPECT_EQ(OK, rv);
4467
4468 response = trans->GetResponseInfo();
4469 EXPECT_TRUE(response != NULL);
4470 EXPECT_TRUE(response->headers != NULL);
4471 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4472 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4473
4474 file_util::Delete(temp_file, false);
4475}
4476
[email protected]aeefc9e82010-02-19 16:18:274477// Tests that changes to Auth realms are treated like auth rejections.
4478TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4479 SessionDependencies session_deps;
4480 scoped_ptr<HttpTransaction> trans(
4481 new HttpNetworkTransaction(CreateSession(&session_deps)));
4482
4483 HttpRequestInfo request;
4484 request.method = "GET";
4485 request.url = GURL("http://www.google.com/");
4486 request.load_flags = 0;
4487
4488 // First transaction will request a resource and receive a Basic challenge
4489 // with realm="first_realm".
4490 MockWrite data_writes1[] = {
4491 MockWrite("GET / HTTP/1.1\r\n"
4492 "Host: www.google.com\r\n"
4493 "Connection: keep-alive\r\n"
4494 "\r\n"),
4495 };
4496 MockRead data_reads1[] = {
4497 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4498 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4499 "\r\n"),
4500 };
4501
4502 // After calling trans->RestartWithAuth(), provide an Authentication header
4503 // for first_realm. The server will reject and provide a challenge with
4504 // second_realm.
4505 MockWrite data_writes2[] = {
4506 MockWrite("GET / HTTP/1.1\r\n"
4507 "Host: www.google.com\r\n"
4508 "Connection: keep-alive\r\n"
4509 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4510 "\r\n"),
4511 };
4512 MockRead data_reads2[] = {
4513 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4514 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4515 "\r\n"),
4516 };
4517
4518 // This again fails, and goes back to first_realm. Make sure that the
4519 // entry is removed from cache.
4520 MockWrite data_writes3[] = {
4521 MockWrite("GET / HTTP/1.1\r\n"
4522 "Host: www.google.com\r\n"
4523 "Connection: keep-alive\r\n"
4524 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4525 "\r\n"),
4526 };
4527 MockRead data_reads3[] = {
4528 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4529 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4530 "\r\n"),
4531 };
4532
4533 // Try one last time (with the correct password) and get the resource.
4534 MockWrite data_writes4[] = {
4535 MockWrite("GET / HTTP/1.1\r\n"
4536 "Host: www.google.com\r\n"
4537 "Connection: keep-alive\r\n"
4538 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4539 "\r\n"),
4540 };
4541 MockRead data_reads4[] = {
4542 MockRead("HTTP/1.1 200 OK\r\n"
4543 "Content-Type: text/html; charset=iso-8859-1\r\n"
4544 "Content-Length: 100\r\n"
4545 "\r\n"),
4546 };
4547
4548 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4549 data_writes1, arraysize(data_writes1));
4550 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4551 data_writes2, arraysize(data_writes2));
4552 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4553 data_writes3, arraysize(data_writes3));
4554 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4555 data_writes4, arraysize(data_writes4));
4556 session_deps.socket_factory.AddSocketDataProvider(&data1);
4557 session_deps.socket_factory.AddSocketDataProvider(&data2);
4558 session_deps.socket_factory.AddSocketDataProvider(&data3);
4559 session_deps.socket_factory.AddSocketDataProvider(&data4);
4560
4561 TestCompletionCallback callback1;
4562
4563 // Issue the first request with Authorize headers. There should be a
4564 // password prompt for first_realm waiting to be filled in after the
4565 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274566 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274567 EXPECT_EQ(ERR_IO_PENDING, rv);
4568 rv = callback1.WaitForResult();
4569 EXPECT_EQ(OK, rv);
4570 const HttpResponseInfo* response = trans->GetResponseInfo();
4571 ASSERT_FALSE(response == NULL);
4572 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4573 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4574 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4575 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4576
4577 // Issue the second request with an incorrect password. There should be a
4578 // password prompt for second_realm waiting to be filled in after the
4579 // transaction completes.
4580 TestCompletionCallback callback2;
4581 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4582 EXPECT_EQ(ERR_IO_PENDING, rv);
4583 rv = callback2.WaitForResult();
4584 EXPECT_EQ(OK, rv);
4585 response = trans->GetResponseInfo();
4586 ASSERT_FALSE(response == NULL);
4587 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4588 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4589 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4590 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4591
4592 // Issue the third request with another incorrect password. There should be
4593 // a password prompt for first_realm waiting to be filled in. If the password
4594 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4595 // first_realm was not correctly removed.
4596 TestCompletionCallback callback3;
4597 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4598 EXPECT_EQ(ERR_IO_PENDING, rv);
4599 rv = callback3.WaitForResult();
4600 EXPECT_EQ(OK, rv);
4601 response = trans->GetResponseInfo();
4602 ASSERT_FALSE(response == NULL);
4603 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4604 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4605 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4606 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4607
4608 // Issue the fourth request with the correct password and username.
4609 TestCompletionCallback callback4;
4610 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4611 EXPECT_EQ(ERR_IO_PENDING, rv);
4612 rv = callback4.WaitForResult();
4613 EXPECT_EQ(OK, rv);
4614 response = trans->GetResponseInfo();
4615 ASSERT_FALSE(response == NULL);
4616 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4617}
4618
[email protected]564b4912010-03-09 16:30:424619TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424620 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064621 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424622
[email protected]564b4912010-03-09 16:30:424623 SessionDependencies session_deps;
4624
4625 MockRead data_reads[] = {
4626 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064627 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424628 MockRead("hello world"),
4629 MockRead(false, OK),
4630 };
4631
4632 HttpRequestInfo request;
4633 request.method = "GET";
4634 request.url = GURL("http://www.google.com/");
4635 request.load_flags = 0;
4636
4637 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4638
4639 session_deps.socket_factory.AddSocketDataProvider(&data);
4640
4641 TestCompletionCallback callback;
4642
4643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4644 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4645
[email protected]5a1d7ca2010-04-28 20:12:274646 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424647 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534648
[email protected]564b4912010-03-09 16:30:424649 HostPortPair http_host_port_pair;
4650 http_host_port_pair.host = "www.google.com";
4651 http_host_port_pair.port = 80;
4652 const HttpAlternateProtocols& alternate_protocols =
4653 session->alternate_protocols();
4654 EXPECT_FALSE(
4655 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4656
4657 EXPECT_EQ(OK, callback.WaitForResult());
4658
4659 const HttpResponseInfo* response = trans->GetResponseInfo();
4660 ASSERT_TRUE(response != NULL);
4661 ASSERT_TRUE(response->headers != NULL);
4662 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4663
4664 std::string response_data;
4665 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4666 EXPECT_EQ("hello world", response_data);
4667
4668 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4669 const HttpAlternateProtocols::PortProtocolPair alternate =
4670 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4671 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4672 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064673 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424674 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424675
[email protected]31e2c69e2010-04-15 18:06:064676 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424677 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424678}
4679
4680TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064681 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424682 SessionDependencies session_deps;
4683
4684 HttpRequestInfo request;
4685 request.method = "GET";
4686 request.url = GURL("http://www.google.com/");
4687 request.load_flags = 0;
4688
4689 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4690 StaticSocketDataProvider first_data;
4691 first_data.set_connect_data(mock_connect);
4692 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4693
4694 MockRead data_reads[] = {
4695 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4696 MockRead("hello world"),
4697 MockRead(true, OK),
4698 };
4699 StaticSocketDataProvider second_data(
4700 data_reads, arraysize(data_reads), NULL, 0);
4701 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4702
4703 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4704 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4705 // http://crbug.com/37454.
4706 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4707
4708 TestCompletionCallback callback;
4709
4710 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4711
4712 HostPortPair http_host_port_pair;
4713 http_host_port_pair.host = "www.google.com";
4714 http_host_port_pair.port = 80;
4715 HttpAlternateProtocols* alternate_protocols =
4716 session->mutable_alternate_protocols();
4717 alternate_protocols->SetAlternateProtocolFor(
4718 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064719 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424720
4721 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4722
[email protected]5a1d7ca2010-04-28 20:12:274723 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424724 EXPECT_EQ(ERR_IO_PENDING, rv);
4725 EXPECT_EQ(OK, callback.WaitForResult());
4726
4727 const HttpResponseInfo* response = trans->GetResponseInfo();
4728 ASSERT_TRUE(response != NULL);
4729 ASSERT_TRUE(response->headers != NULL);
4730 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4731
4732 std::string response_data;
4733 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4734 EXPECT_EQ("hello world", response_data);
4735
4736 ASSERT_TRUE(
4737 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4738 const HttpAlternateProtocols::PortProtocolPair alternate =
4739 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4740 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064741 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424742}
4743
4744// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4745// says that it does SPDY, but it just does the TLS handshake, but the NPN
4746// response does not indicate SPDY, so we just do standard HTTPS over the port.
4747// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4748// on the original port.
[email protected]a2cb8122010-03-10 17:22:424749// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4750// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534751//
[email protected]a2cb8122010-03-10 17:22:424752// HttpRequestInfo request;
4753// request.method = "GET";
4754// request.url = GURL("http://www.google.com/");
4755// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534756//
[email protected]a2cb8122010-03-10 17:22:424757// MockRead data_reads[] = {
4758// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4759// MockRead("hello world"),
4760// MockRead(true, OK),
4761// };
4762// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4763// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534764//
[email protected]a2cb8122010-03-10 17:22:424765// SSLSocketDataProvider ssl(true, OK);
4766// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534767//
[email protected]a2cb8122010-03-10 17:22:424768// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534769//
[email protected]a2cb8122010-03-10 17:22:424770// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534771//
[email protected]a2cb8122010-03-10 17:22:424772// HostPortPair http_host_port_pair;
4773// http_host_port_pair.host = "www.google.com";
4774// http_host_port_pair.port = 80;
4775// HttpAlternateProtocols* alternate_protocols =
4776// session->mutable_alternate_protocols();
4777// alternate_protocols->SetAlternateProtocolFor(
4778// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064779// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534780//
[email protected]a2cb8122010-03-10 17:22:424781// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534782//
[email protected]5a1d7ca2010-04-28 20:12:274783// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:424784// EXPECT_EQ(ERR_IO_PENDING, rv);
4785// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534786//
[email protected]a2cb8122010-03-10 17:22:424787// const HttpResponseInfo* response = trans->GetResponseInfo();
4788// ASSERT_TRUE(response != NULL);
4789// ASSERT_TRUE(response->headers != NULL);
4790// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534791//
[email protected]a2cb8122010-03-10 17:22:424792// std::string response_data;
4793// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4794// EXPECT_EQ("hello world", response_data);
4795// }
4796
4797TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:064798 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:544799 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:114800 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:424801 SessionDependencies session_deps;
4802
4803 HttpRequestInfo request;
4804 request.method = "GET";
4805 request.url = GURL("http://www.google.com/");
4806 request.load_flags = 0;
4807
[email protected]a2cb8122010-03-10 17:22:424808 StaticSocketDataProvider first_tcp_connect;
4809 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4810
4811 SSLSocketDataProvider ssl(true, OK);
4812 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4813
[email protected]564b4912010-03-09 16:30:424814 MockRead data_reads[] = {
4815 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4816 MockRead("hello world"),
4817 MockRead(true, OK),
4818 };
[email protected]a2cb8122010-03-10 17:22:424819 StaticSocketDataProvider fallback_data(
4820 data_reads, arraysize(data_reads), NULL, 0);
4821 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424822
4823 TestCompletionCallback callback;
4824
4825 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4826
4827 HostPortPair http_host_port_pair;
4828 http_host_port_pair.host = "www.google.com";
4829 http_host_port_pair.port = 80;
4830 HttpAlternateProtocols* alternate_protocols =
4831 session->mutable_alternate_protocols();
4832 alternate_protocols->SetAlternateProtocolFor(
4833 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064834 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424835
4836 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4837
[email protected]5a1d7ca2010-04-28 20:12:274838 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424839 EXPECT_EQ(ERR_IO_PENDING, rv);
4840 EXPECT_EQ(OK, callback.WaitForResult());
4841
4842 const HttpResponseInfo* response = trans->GetResponseInfo();
4843 ASSERT_TRUE(response != NULL);
4844 ASSERT_TRUE(response->headers != NULL);
4845 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4846
4847 std::string response_data;
4848 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4849 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:544850 HttpNetworkTransaction::SetNextProtos("");
4851 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4852}
4853
4854TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
4855 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4856 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:114857 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:544858 SessionDependencies session_deps;
4859
4860 HttpRequestInfo request;
4861 request.method = "GET";
4862 request.url = GURL("http://www.google.com/");
4863 request.load_flags = 0;
4864
4865 MockRead data_reads[] = {
4866 MockRead("HTTP/1.1 200 OK\r\n"),
4867 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
4868 MockRead("hello world"),
4869 MockRead(true, OK),
4870 };
4871
4872 StaticSocketDataProvider first_transaction(
4873 data_reads, arraysize(data_reads), NULL, 0);
4874 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
4875
4876 SSLSocketDataProvider ssl(true, OK);
4877 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4878 ssl.next_proto = "spdy/1";
4879 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4880
4881 MockWrite spdy_writes[] = {
4882 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
4883 arraysize(kGetSyn)),
4884 };
4885
4886 MockRead spdy_reads[] = {
4887 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
4888 arraysize(kGetSynReply)),
4889 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
4890 arraysize(kGetBodyFrame)),
4891 MockRead(true, 0, 0),
4892 };
4893
4894 scoped_refptr<DelayedSocketData> spdy_data(
4895 new DelayedSocketData(
4896 1, // wait for one write to finish before reading.
4897 spdy_reads, arraysize(spdy_reads),
4898 spdy_writes, arraysize(spdy_writes)));
4899 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
4900
4901 TestCompletionCallback callback;
4902
4903 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4904 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
4905
[email protected]5a1d7ca2010-04-28 20:12:274906 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:544907 EXPECT_EQ(ERR_IO_PENDING, rv);
4908 EXPECT_EQ(OK, callback.WaitForResult());
4909
4910 const HttpResponseInfo* response = trans->GetResponseInfo();
4911 ASSERT_TRUE(response != NULL);
4912 ASSERT_TRUE(response->headers != NULL);
4913 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4914
4915 std::string response_data;
4916 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4917 EXPECT_EQ("hello world", response_data);
4918
4919 trans.reset(new HttpNetworkTransaction(session));
4920
[email protected]5a1d7ca2010-04-28 20:12:274921 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:544922 EXPECT_EQ(ERR_IO_PENDING, rv);
4923 EXPECT_EQ(OK, callback.WaitForResult());
4924
4925 response = trans->GetResponseInfo();
4926 ASSERT_TRUE(response != NULL);
4927 ASSERT_TRUE(response->headers != NULL);
4928 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4929
4930 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4931 EXPECT_EQ("hello!", response_data);
4932
4933 HttpNetworkTransaction::SetNextProtos("");
4934 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4935}
4936
[email protected]631f1322010-04-30 17:59:114937class CapturingProxyResolver : public ProxyResolver {
4938 public:
4939 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
4940 virtual ~CapturingProxyResolver() {}
4941
4942 virtual int GetProxyForURL(const GURL& url,
4943 ProxyInfo* results,
4944 CompletionCallback* callback,
4945 RequestHandle* request,
4946 const BoundNetLog& net_log) {
4947 resolved_.push_back(url);
4948 return ERR_NOT_IMPLEMENTED;
4949 }
4950
4951 virtual void CancelRequest(RequestHandle request) {
4952 NOTREACHED();
4953 }
4954
4955 const std::vector<GURL>& resolved() const { return resolved_; }
4956
4957 private:
4958 virtual int SetPacScript(const GURL& /*pac_url*/,
4959 const std::string& /*pac_bytes*/,
4960 CompletionCallback* /*callback*/) {
4961 return ERR_NOT_IMPLEMENTED;
4962 }
4963
4964 std::vector<GURL> resolved_;
4965
4966 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
4967};
4968
4969// TODO(willchan): Enable this test after I refactor the OrderedSocketData out
4970// of SpdyNetworkTransaction. Currently, I need to the CONNECT, read the
4971// response, and then send the request, and then read the response.
4972// DelayedSocketDataProvider doesn't permit this yet.
4973#if 0
4974TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
4975 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4976 HttpNetworkTransaction::SetNextProtos(
4977 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
4978
4979 ProxyConfig proxy_config;
4980 proxy_config.proxy_rules().ParseFromString("myproxy:80");
[email protected]2227c692010-05-04 15:36:114981
[email protected]631f1322010-04-30 17:59:114982 CapturingProxyResolver* capturing_proxy_resolver =
4983 new CapturingProxyResolver();
4984 SessionDependencies session_deps(
4985 new ProxyService(new ProxyConfigServiceFixed(proxy_config),
4986 capturing_proxy_resolver,
4987 NULL,
4988 NULL));
4989
4990 HttpRequestInfo request;
4991 request.method = "GET";
4992 request.url = GURL("http://www.google.com/");
4993 request.load_flags = 0;
4994
4995 MockRead data_reads[] = {
4996 MockRead("HTTP/1.1 200 OK\r\n"),
4997 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
4998 MockRead("hello world"),
4999 MockRead(true, OK),
5000 };
5001
5002 StaticSocketDataProvider first_transaction(
5003 data_reads, arraysize(data_reads), NULL, 0);
5004 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5005
5006 SSLSocketDataProvider ssl(true, OK);
5007 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5008 ssl.next_proto = "spdy/1";
5009 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5010
5011 MockWrite spdy_writes[] = {
5012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5013 "Host: www.google.com\r\n"
5014 "Proxy-Connection: keep-alive\r\n\r\n"),
5015 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5016 arraysize(kGetSyn)),
5017 };
5018
5019 MockRead spdy_reads[] = {
5020 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
5021 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5022 arraysize(kGetSynReply)),
5023 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5024 arraysize(kGetBodyFrame)),
5025 MockRead(true, 0, 0),
5026 };
5027
5028 scoped_refptr<DelayedSocketData> spdy_data(
5029 new DelayedSocketData(
5030 1, // wait for one write to finish before reading.
5031 spdy_reads, arraysize(spdy_reads),
5032 spdy_writes, arraysize(spdy_writes)));
5033 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5034
5035 TestCompletionCallback callback;
5036
5037 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5038 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5039
5040 int rv = trans->Start(&request, &callback, BoundNetLog());
5041 EXPECT_EQ(ERR_IO_PENDING, rv);
5042 EXPECT_EQ(OK, callback.WaitForResult());
5043
5044 const HttpResponseInfo* response = trans->GetResponseInfo();
5045 ASSERT_TRUE(response != NULL);
5046 ASSERT_TRUE(response->headers != NULL);
5047 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5048
5049 std::string response_data;
5050 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5051 EXPECT_EQ("hello world", response_data);
5052
5053 trans.reset(new HttpNetworkTransaction(session));
5054
5055 rv = trans->Start(&request, &callback, BoundNetLog());
5056 EXPECT_EQ(ERR_IO_PENDING, rv);
5057 EXPECT_EQ(OK, callback.WaitForResult());
5058
5059 response = trans->GetResponseInfo();
5060 ASSERT_TRUE(response != NULL);
5061 ASSERT_TRUE(response->headers != NULL);
5062 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5063
5064 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5065 EXPECT_EQ("hello!", response_data);
5066 ASSERT_EQ(1u, capturing_proxy_resolver->resolved().size());
5067 EXPECT_EQ("https://www.google.com:443/",
5068 capturing_proxy_resolver->resolved()[0].spec());
5069
5070 HttpNetworkTransaction::SetNextProtos("");
5071 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5072}
5073#endif
5074
[email protected]2ff8b312010-04-26 22:20:545075TEST_F(HttpNetworkTransactionTest,
5076 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5077 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5078 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115079 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545080 SessionDependencies session_deps;
5081
5082 HttpRequestInfo request;
5083 request.method = "GET";
5084 request.url = GURL("http://www.google.com/");
5085 request.load_flags = 0;
5086
5087 MockRead data_reads[] = {
5088 MockRead("HTTP/1.1 200 OK\r\n"),
5089 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5090 MockRead("hello world"),
5091 MockRead(true, OK),
5092 };
5093
5094 StaticSocketDataProvider first_transaction(
5095 data_reads, arraysize(data_reads), NULL, 0);
5096 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5097
5098 SSLSocketDataProvider ssl(true, OK);
5099 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5100 ssl.next_proto = "spdy/1";
5101 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5102
5103 MockWrite spdy_writes[] = {
5104 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5105 arraysize(kGetSyn)),
5106 };
5107
5108 MockRead spdy_reads[] = {
5109 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5110 arraysize(kGetSynReply)),
5111 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5112 arraysize(kGetBodyFrame)),
5113 MockRead(true, 0, 0),
5114 };
5115
5116 scoped_refptr<DelayedSocketData> spdy_data(
5117 new DelayedSocketData(
5118 1, // wait for one write to finish before reading.
5119 spdy_reads, arraysize(spdy_reads),
5120 spdy_writes, arraysize(spdy_writes)));
5121 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5122
5123 TestCompletionCallback callback;
5124
5125 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5126
5127 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5128
[email protected]5a1d7ca2010-04-28 20:12:275129 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545130 EXPECT_EQ(ERR_IO_PENDING, rv);
5131 EXPECT_EQ(OK, callback.WaitForResult());
5132
5133 const HttpResponseInfo* response = trans->GetResponseInfo();
5134 ASSERT_TRUE(response != NULL);
5135 ASSERT_TRUE(response->headers != NULL);
5136 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5137
5138 std::string response_data;
5139 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5140 EXPECT_EQ("hello world", response_data);
5141
5142 // Set up an initial SpdySession in the pool to reuse.
5143 scoped_refptr<SpdySession> spdy_session =
5144 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
5145 session);
5146 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
5147 spdy_session->Connect(
5148 "www.google.com:443", tcp_params, MEDIUM, BoundNetLog());
5149
5150 trans.reset(new HttpNetworkTransaction(session));
5151
[email protected]5a1d7ca2010-04-28 20:12:275152 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545153 EXPECT_EQ(ERR_IO_PENDING, rv);
5154 EXPECT_EQ(OK, callback.WaitForResult());
5155
5156 response = trans->GetResponseInfo();
5157 ASSERT_TRUE(response != NULL);
5158 ASSERT_TRUE(response->headers != NULL);
5159 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5160
5161 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5162 EXPECT_EQ("hello!", response_data);
5163
5164 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065165 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425166}
5167
[email protected]e5ae96a2010-04-14 20:12:455168// MockAuthHandlerCanonical is used by the ResolveCanonicalName
5169// HttpNetworkTransaction unit test below. Callers set up expectations for
5170// whether the canonical name needs to be resolved.
5171class MockAuthHandlerCanonical : public HttpAuthHandler {
5172 public:
5173 enum Resolve {
5174 RESOLVE_INIT,
5175 RESOLVE_SKIP,
5176 RESOLVE_SYNC,
5177 RESOLVE_ASYNC,
5178 RESOLVE_TESTED,
5179 };
5180
5181 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
5182 virtual ~MockAuthHandlerCanonical() {}
5183
5184 void SetResolveExpectation(Resolve resolve) {
5185 EXPECT_EQ(RESOLVE_INIT, resolve_);
5186 resolve_ = resolve;
5187 }
5188
5189 void ResetResolveExpectation() {
5190 EXPECT_EQ(RESOLVE_TESTED, resolve_);
5191 resolve_ = RESOLVE_INIT;
5192 }
5193
5194 virtual bool NeedsCanonicalName() {
5195 switch (resolve_) {
5196 case RESOLVE_SYNC:
5197 case RESOLVE_ASYNC:
5198 return true;
5199 case RESOLVE_SKIP:
5200 resolve_ = RESOLVE_TESTED;
5201 return false;
5202 default:
5203 NOTREACHED();
5204 return false;
5205 }
5206 }
5207
5208 virtual int ResolveCanonicalName(HostResolver* host_resolver,
5209 CompletionCallback* callback,
5210 const BoundNetLog& net_log) {
5211 EXPECT_NE(RESOLVE_TESTED, resolve_);
5212 int rv = OK;
5213 switch (resolve_) {
5214 case RESOLVE_SYNC:
5215 resolve_ = RESOLVE_TESTED;
5216 break;
5217 case RESOLVE_ASYNC:
5218 EXPECT_TRUE(user_callback_ == NULL);
5219 rv = ERR_IO_PENDING;
5220 user_callback_ = callback;
5221 MessageLoop::current()->PostTask(
5222 FROM_HERE,
5223 NewRunnableMethod(
5224 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
5225 break;
5226 default:
5227 NOTREACHED();
5228 break;
5229 }
5230 return rv;
5231 }
5232
5233 void OnResolveCanonicalName() {
5234 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
5235 EXPECT_TRUE(user_callback_ != NULL);
5236 resolve_ = RESOLVE_TESTED;
5237 CompletionCallback* callback = user_callback_;
5238 user_callback_ = NULL;
5239 callback->Run(OK);
5240 }
5241
5242 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
5243 scheme_ = "mock";
5244 score_ = 1;
5245 properties_ = 0;
5246 return true;
5247 }
5248
5249 virtual int GenerateAuthToken(const std::wstring& username,
5250 const std::wstring& password,
5251 const HttpRequestInfo* request,
5252 const ProxyInfo* proxy,
5253 std::string* auth_token) {
5254 auth_token->assign("Mock AUTH myserver.example.com");
5255 return OK;
5256 }
5257
5258 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
5259 const ProxyInfo* proxy,
5260 std::string* auth_token) {
5261 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
5262 return OK;
5263 }
5264
5265 // The Factory class simply returns the same handler each time
5266 // CreateAuthHandler is called.
5267 class Factory : public HttpAuthHandlerFactory {
5268 public:
5269 Factory() {}
5270 virtual ~Factory() {}
5271
5272 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
5273 mock_handler_ = mock_handler;
5274 }
5275 MockAuthHandlerCanonical* mock_handler() const {
5276 return mock_handler_.get();
5277 }
5278
5279 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
5280 HttpAuth::Target target,
5281 const GURL& origin,
5282 scoped_refptr<HttpAuthHandler>* handler) {
5283 *handler = mock_handler_;
5284 return OK;
5285 }
5286
5287 private:
5288 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
5289 };
5290
5291 private:
5292 Resolve resolve_;
5293 CompletionCallback* user_callback_;
5294};
5295
5296// Tests that ResolveCanonicalName is handled correctly by the
5297// HttpNetworkTransaction.
5298TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5299 SessionDependencies session_deps;
5300 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
5301 new MockAuthHandlerCanonical());
5302 auth_handler->Init(NULL);
5303 MockAuthHandlerCanonical::Factory* auth_factory(
5304 new MockAuthHandlerCanonical::Factory());
5305 auth_factory->set_mock_handler(auth_handler);
5306 session_deps.http_auth_handler_factory.reset(auth_factory);
5307
5308 for (int i = 0; i < 2; ++i) {
5309 scoped_ptr<HttpTransaction> trans(
5310 new HttpNetworkTransaction(CreateSession(&session_deps)));
5311
5312 // Set up expectations for this pass of the test. Many of the EXPECT calls
5313 // are contained inside the MockAuthHandlerCanonical codebase in response to
5314 // the expectations.
[email protected]2227c692010-05-04 15:36:115315 MockAuthHandlerCanonical::Resolve resolve =
5316 (i == 0) ?
[email protected]e5ae96a2010-04-14 20:12:455317 MockAuthHandlerCanonical::RESOLVE_SYNC :
5318 MockAuthHandlerCanonical::RESOLVE_ASYNC;
5319 auth_handler->SetResolveExpectation(resolve);
5320 HttpRequestInfo request;
5321 request.method = "GET";
5322 request.url = GURL("http://myserver/");
5323 request.load_flags = 0;
5324
5325 MockWrite data_writes1[] = {
5326 MockWrite("GET / HTTP/1.1\r\n"
5327 "Host: myserver\r\n"
5328 "Connection: keep-alive\r\n\r\n"),
5329 };
5330
5331 MockRead data_reads1[] = {
5332 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5333 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5335 MockRead("Content-Length: 14\r\n\r\n"),
5336 MockRead("Unauthorized\r\n"),
5337 };
5338
5339 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5340 data_writes1, arraysize(data_writes1));
5341 session_deps.socket_factory.AddSocketDataProvider(&data1);
5342
5343 TestCompletionCallback callback1;
5344
[email protected]5a1d7ca2010-04-28 20:12:275345 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455346 EXPECT_EQ(ERR_IO_PENDING, rv);
5347
5348 rv = callback1.WaitForResult();
5349 EXPECT_EQ(OK, rv);
5350
5351 const HttpResponseInfo* response = trans->GetResponseInfo();
5352 EXPECT_FALSE(response == NULL);
5353
5354 // The password prompt is set after the canonical name is resolved.
5355 // If it isn't present or is incorrect, it indicates that the scheme
5356 // did not complete correctly.
5357 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5358
5359 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5360 EXPECT_EQ(L"", response->auth_challenge->realm);
5361 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
5362 auth_handler->ResetResolveExpectation();
5363 }
5364}
5365
[email protected]aeaca1f2010-04-20 22:05:215366class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5367 public:
5368 TLSDecompressionFailureSocketDataProvider(bool fail_all)
5369 : fail_all_(fail_all) {
5370 }
5371
5372 virtual MockRead GetNextRead() {
5373 if (fail_all_)
5374 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5375
5376 return MockRead(false /* async */,
5377 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5378 }
5379
5380 virtual MockWriteResult OnWrite(const std::string& data) {
5381 return MockWriteResult(false /* async */, data.size());
5382 }
5383
5384 void Reset() {
5385 }
5386
5387 private:
5388 const bool fail_all_;
5389};
5390
5391// Test that we restart a connection when we see a decompression failure from
5392// the peer during the handshake. (In the real world we'll restart with SSLv3
5393// and we won't offer DEFLATE in that case.)
5394TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5395 HttpRequestInfo request;
5396 request.method = "GET";
5397 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5398 request.load_flags = 0;
5399
5400 SessionDependencies session_deps;
5401 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5402 false /* fail all reads */);
5403 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5404 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115405 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215406 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5407 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5408 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5409 session_deps.socket_factory.AddSSLSocketDataProvider(
5410 &ssl_socket_data_provider1);
5411 session_deps.socket_factory.AddSSLSocketDataProvider(
5412 &ssl_socket_data_provider2);
5413
5414 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5415 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5416 TestCompletionCallback callback;
5417
[email protected]5a1d7ca2010-04-28 20:12:275418 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215419 EXPECT_EQ(ERR_IO_PENDING, rv);
5420 EXPECT_EQ(OK, callback.WaitForResult());
5421
5422 const HttpResponseInfo* response = trans->GetResponseInfo();
5423 ASSERT_TRUE(response != NULL);
5424 ASSERT_TRUE(response->headers != NULL);
5425 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5426
5427 std::string response_data;
5428 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5429 EXPECT_EQ("ok.", response_data);
5430}
5431
5432// Test that we restart a connection if we get a decompression failure from the
5433// peer while reading the first bytes from the connection. This occurs when the
5434// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5435// in the handshake.
5436TEST_F(HttpNetworkTransactionTest,
5437 RestartAfterTLSDecompressionFailureWithFalseStart) {
5438 HttpRequestInfo request;
5439 request.method = "GET";
5440 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
5441 request.load_flags = 0;
5442
5443 SessionDependencies session_deps;
5444 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5445 true /* fail all reads */);
5446 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5447 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
5448 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5449 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5450 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5451 session_deps.socket_factory.AddSSLSocketDataProvider(
5452 &ssl_socket_data_provider1);
5453 session_deps.socket_factory.AddSSLSocketDataProvider(
5454 &ssl_socket_data_provider2);
5455
5456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5457 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5458 TestCompletionCallback callback;
5459
[email protected]5a1d7ca2010-04-28 20:12:275460 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215461 EXPECT_EQ(ERR_IO_PENDING, rv);
5462 EXPECT_EQ(OK, callback.WaitForResult());
5463
5464 const HttpResponseInfo* response = trans->GetResponseInfo();
5465 ASSERT_TRUE(response != NULL);
5466 ASSERT_TRUE(response->headers != NULL);
5467 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5468
5469 std::string response_data;
5470 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5471 EXPECT_EQ("ok.", response_data);
5472}
5473
[email protected]89ceba9a2009-03-21 03:46:065474} // namespace net