blob: 19eac1780ae8894fd805ead7c9f84f629e95e472 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]169d0012010-05-10 23:20:1215#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3217#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/net_log.h"
19#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3120#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4221#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "net/base/test_completion_callback.h"
24#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1225#include "net/http/http_auth_handler_digest.h"
[email protected]385a4672009-03-11 22:21:2926#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5727#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5228#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5729#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5331#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1132#include "net/proxy/proxy_resolver.h"
33#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4434#include "net/socket/client_socket_factory.h"
35#include "net/socket/socket_test_util.h"
36#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5437#include "net/spdy/spdy_framer.h"
38#include "net/spdy/spdy_session.h"
39#include "net/spdy/spdy_session_pool.h"
40#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5241#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1542#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5243
44//-----------------------------------------------------------------------------
45
[email protected]89ceba9a2009-03-21 03:46:0646namespace net {
47
[email protected]2d731a32010-04-29 01:04:0648class HttpNetworkSessionPeer {
49 public:
50 explicit HttpNetworkSessionPeer(
51 const scoped_refptr<HttpNetworkSession>& session)
52 : session_(session) {}
53
54 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
55 session_->tcp_socket_pool_ = pool;
56 }
57
58 void SetSocketPoolForSOCKSProxy(
59 const HostPortPair& socks_proxy,
60 const scoped_refptr<SOCKSClientSocketPool>& pool) {
61 session_->socks_socket_pool_[socks_proxy] = pool;
62 }
63
64 void SetSocketPoolForHTTPProxy(
65 const HostPortPair& http_proxy,
66 const scoped_refptr<TCPClientSocketPool>& pool) {
67 session_->http_proxy_socket_pool_[http_proxy] = pool;
68 }
69
70 private:
71 const scoped_refptr<HttpNetworkSession> session_;
72
73 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
74};
75
[email protected]e44de5d2009-06-05 20:12:4576// Helper to manage the lifetimes of the dependencies for a
77// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4478struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5979 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4280 SessionDependencies()
81 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3782 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1083 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5284 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]b846acd2010-06-07 18:13:1085 spdy_session_pool(new SpdySessionPool(NULL)) {}
[email protected]228ff742009-06-05 01:19:5986
87 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4588 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4289 : host_resolver(new MockHostResolver),
90 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1091 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5292 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]b846acd2010-06-07 18:13:1093 spdy_session_pool(new SpdySessionPool(NULL)) {}
[email protected]228ff742009-06-05 01:19:5994
[email protected]a2c2fb92009-07-18 07:31:0495 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0996 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4297 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5998 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5099 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52100 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:59101};
102
[email protected]1c773ea12009-04-28 19:58:42103ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50104 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48105 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39106 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53107}
108
[email protected]228ff742009-06-05 01:19:59109HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:51110 return new HttpNetworkSession(NULL,
111 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09112 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42113 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10114 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52115 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17116 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44117 NULL,
[email protected]06650c52010-06-03 00:49:17118 NULL);
[email protected]e8d536192008-10-17 22:21:14119}
120
[email protected]89836e22008-09-25 20:33:42121class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52122 public:
[email protected]2ff8b312010-04-26 22:20:54123 virtual void SetUp() {
124 spdy::SpdyFramer::set_enable_compression_default(false);
125 }
126
[email protected]0e75a732008-10-16 20:36:09127 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54128 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09129 // Empty the current queue.
130 MessageLoop::current()->RunAllPending();
131 PlatformTest::TearDown();
132 }
133
[email protected]3d2a59b2008-09-26 19:44:25134 protected:
135 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52136
[email protected]ff007e162009-05-23 09:13:15137 struct SimpleGetHelperResult {
138 int rv;
139 std::string status_line;
140 std::string response_data;
141 };
initial.commit586acc5fe2008-07-26 22:42:52142
[email protected]31a2bfe2010-02-09 08:03:39143 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
144 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15145 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52146
[email protected]228ff742009-06-05 01:19:59147 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40148 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43149 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]ff007e162009-05-23 09:13:15151 HttpRequestInfo request;
152 request.method = "GET";
153 request.url = GURL("http://www.google.com/");
154 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]31a2bfe2010-02-09 08:03:39156 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59157 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]ff007e162009-05-23 09:13:15159 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52160
[email protected]169d0012010-05-10 23:20:12161 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
162 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15163 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52164
[email protected]ff007e162009-05-23 09:13:15165 out.rv = callback.WaitForResult();
166 if (out.rv != OK)
167 return out;
168
169 const HttpResponseInfo* response = trans->GetResponseInfo();
170 EXPECT_TRUE(response != NULL);
171
172 EXPECT_TRUE(response->headers != NULL);
173 out.status_line = response->headers->GetStatusLine();
174
175 rv = ReadTransaction(trans.get(), &out.response_data);
176 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39177 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12178 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
179 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39180 ExpectLogContainsSomewhere(
181 log.entries(), pos,
182 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
183 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15184
[email protected]aecfbf22008-10-16 02:02:47185 return out;
[email protected]ff007e162009-05-23 09:13:15186 }
initial.commit586acc5fe2008-07-26 22:42:52187
[email protected]ff007e162009-05-23 09:13:15188 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
189 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52190
[email protected]ff007e162009-05-23 09:13:15191 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15192};
[email protected]231d5a32008-09-13 00:45:27193
[email protected]15a5ccf82008-10-23 19:57:43194// Fill |str| with a long header list that consumes >= |size| bytes.
195void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19196 const char* row =
197 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
198 const int sizeof_row = strlen(row);
199 const int num_rows = static_cast<int>(
200 ceil(static_cast<float>(size) / sizeof_row));
201 const int sizeof_data = num_rows * sizeof_row;
202 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43203 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51204
[email protected]4ddaf2502008-10-23 18:26:19205 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43206 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19207}
208
[email protected]385a4672009-03-11 22:21:29209// Alternative functions that eliminate randomness and dependency on the local
210// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20211void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29212 static const uint8 bytes[] = {
213 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
214 };
215 static size_t current_byte = 0;
216 for (size_t i = 0; i < n; ++i) {
217 output[i] = bytes[current_byte++];
218 current_byte %= arraysize(bytes);
219 }
220}
221
[email protected]fe2bc6a2009-03-23 16:52:20222void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29223 static const uint8 bytes[] = {
224 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
225 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
226 };
227 static size_t current_byte = 0;
228 for (size_t i = 0; i < n; ++i) {
229 output[i] = bytes[current_byte++];
230 current_byte %= arraysize(bytes);
231 }
232}
233
[email protected]fe2bc6a2009-03-23 16:52:20234std::string MockGetHostName() {
235 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29236}
237
[email protected]2d731a32010-04-29 01:04:06238template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26239class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31240 public:
[email protected]06650c52010-06-03 00:49:17241 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]b89f7e42010-05-20 20:37:00242 : EmulatedClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
[email protected]06650c52010-06-03 00:49:17243 NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49244 const std::string last_group_name_received() const {
245 return last_group_name_;
246 }
247
[email protected]684970b2009-08-14 04:54:46248 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49249 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31250 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31251 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46252 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53253 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31254 last_group_name_ = group_name;
255 return ERR_IO_PENDING;
256 }
[email protected]04e5be32009-06-26 20:00:31257 virtual void CancelRequest(const std::string& group_name,
258 const ClientSocketHandle* handle) { }
259 virtual void ReleaseSocket(const std::string& group_name,
260 ClientSocket* socket) {}
261 virtual void CloseIdleSockets() {}
262 virtual HostResolver* GetHostResolver() const {
263 return NULL;
264 }
265 virtual int IdleSocketCount() const {
266 return 0;
267 }
268 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
269 return 0;
270 }
271 virtual LoadState GetLoadState(const std::string& group_name,
272 const ClientSocketHandle* handle) const {
273 return LOAD_STATE_IDLE;
274 }
[email protected]a796bcec2010-03-22 17:17:26275 virtual base::TimeDelta ConnectionTimeout() const {
276 return base::TimeDelta();
277 }
[email protected]d80a4322009-08-14 07:07:49278
279 private:
[email protected]04e5be32009-06-26 20:00:31280 std::string last_group_name_;
281};
282
[email protected]2d731a32010-04-29 01:04:06283typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11284CaptureGroupNameTCPSocketPool;
[email protected]2d731a32010-04-29 01:04:06285typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11286CaptureGroupNameSOCKSSocketPool;
287
[email protected]231d5a32008-09-13 00:45:27288//-----------------------------------------------------------------------------
289
290TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59291 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40292 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43293 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27294}
295
296TEST_F(HttpNetworkTransactionTest, SimpleGET) {
297 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35298 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
299 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42300 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27301 };
[email protected]31a2bfe2010-02-09 08:03:39302 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
303 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42304 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27305 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
306 EXPECT_EQ("hello world", out.response_data);
307}
308
309// Response with no status line.
310TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
311 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35312 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42313 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27314 };
[email protected]31a2bfe2010-02-09 08:03:39315 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
316 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42317 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27318 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
319 EXPECT_EQ("hello world", out.response_data);
320}
321
322// Allow up to 4 bytes of junk to precede status line.
323TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
324 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35325 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42326 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27327 };
[email protected]31a2bfe2010-02-09 08:03:39328 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
329 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42330 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27331 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
332 EXPECT_EQ("DATA", out.response_data);
333}
334
335// Allow up to 4 bytes of junk to precede status line.
336TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
337 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35338 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42339 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27340 };
[email protected]31a2bfe2010-02-09 08:03:39341 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
342 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42343 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27344 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
345 EXPECT_EQ("DATA", out.response_data);
346}
347
348// Beyond 4 bytes of slop and it should fail to find a status line.
349TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
350 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35351 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42352 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27353 };
[email protected]31a2bfe2010-02-09 08:03:39354 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
355 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42356 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25357 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
358 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27359}
360
361// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
362TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
363 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35364 MockRead("\n"),
365 MockRead("\n"),
366 MockRead("Q"),
367 MockRead("J"),
368 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42369 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27370 };
[email protected]31a2bfe2010-02-09 08:03:39371 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
372 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42373 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27374 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
375 EXPECT_EQ("DATA", out.response_data);
376}
377
378// Close the connection before enough bytes to have a status line.
379TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
380 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35381 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42382 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27383 };
[email protected]31a2bfe2010-02-09 08:03:39384 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
385 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42386 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27387 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
388 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52389}
390
[email protected]f9d44aa2008-09-23 23:57:17391// Simulate a 204 response, lacking a Content-Length header, sent over a
392// persistent connection. The response should still terminate since a 204
393// cannot have a response body.
394TEST_F(HttpNetworkTransactionTest, StopsReading204) {
395 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35396 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
397 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42398 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17399 };
[email protected]31a2bfe2010-02-09 08:03:39400 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
401 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42402 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17403 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
404 EXPECT_EQ("", out.response_data);
405}
406
[email protected]0877e3d2009-10-17 22:29:57407// A simple request using chunked encoding with some extra data after.
408// (Like might be seen in a pipelined response.)
409TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
410 MockRead data_reads[] = {
411 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
412 MockRead("5\r\nHello\r\n"),
413 MockRead("1\r\n"),
414 MockRead(" \r\n"),
415 MockRead("5\r\nworld\r\n"),
416 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
417 MockRead(false, OK),
418 };
[email protected]31a2bfe2010-02-09 08:03:39419 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
420 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57421 EXPECT_EQ(OK, out.rv);
422 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
423 EXPECT_EQ("Hello world", out.response_data);
424}
425
[email protected]ef0faf2e72009-03-05 23:27:23426// Do a request using the HEAD method. Verify that we don't try to read the
427// message body (since HEAD has none).
428TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59429 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40430 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43431 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23432
[email protected]1c773ea12009-04-28 19:58:42433 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23434 request.method = "HEAD";
435 request.url = GURL("http://www.google.com/");
436 request.load_flags = 0;
437
438 MockWrite data_writes1[] = {
439 MockWrite("HEAD / HTTP/1.1\r\n"
440 "Host: www.google.com\r\n"
441 "Connection: keep-alive\r\n"
442 "Content-Length: 0\r\n\r\n"),
443 };
444 MockRead data_reads1[] = {
445 MockRead("HTTP/1.1 404 Not Found\r\n"),
446 MockRead("Server: Blah\r\n"),
447 MockRead("Content-Length: 1234\r\n\r\n"),
448
449 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42450 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23451 };
452
[email protected]31a2bfe2010-02-09 08:03:39453 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
454 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59455 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23456
457 TestCompletionCallback callback1;
458
[email protected]5a1d7ca2010-04-28 20:12:27459 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42460 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23461
462 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42463 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23464
[email protected]1c773ea12009-04-28 19:58:42465 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23466 EXPECT_FALSE(response == NULL);
467
468 // Check that the headers got parsed.
469 EXPECT_TRUE(response->headers != NULL);
470 EXPECT_EQ(1234, response->headers->GetContentLength());
471 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
472
473 std::string server_header;
474 void* iter = NULL;
475 bool has_server_header = response->headers->EnumerateHeader(
476 &iter, "Server", &server_header);
477 EXPECT_TRUE(has_server_header);
478 EXPECT_EQ("Blah", server_header);
479
480 // Reading should give EOF right away, since there is no message body
481 // (despite non-zero content-length).
482 std::string response_data;
483 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42484 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23485 EXPECT_EQ("", response_data);
486}
487
initial.commit586acc5fe2008-07-26 22:42:52488TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59489 SessionDependencies session_deps;
490 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52491
492 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35493 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
494 MockRead("hello"),
495 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
496 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42497 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52498 };
[email protected]31a2bfe2010-02-09 08:03:39499 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59500 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52501
502 const char* kExpectedResponseData[] = {
503 "hello", "world"
504 };
505
506 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43507 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52508
[email protected]1c773ea12009-04-28 19:58:42509 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52510 request.method = "GET";
511 request.url = GURL("http://www.google.com/");
512 request.load_flags = 0;
513
514 TestCompletionCallback callback;
515
[email protected]5a1d7ca2010-04-28 20:12:27516 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42517 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52518
519 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42520 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52521
[email protected]1c773ea12009-04-28 19:58:42522 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52523 EXPECT_TRUE(response != NULL);
524
525 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25526 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52527
528 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57529 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42530 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25531 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52532 }
533}
534
535TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59536 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40537 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43538 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52539
[email protected]1c773ea12009-04-28 19:58:42540 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52541 request.method = "POST";
542 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42543 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52544 request.upload_data->AppendBytes("foo", 3);
545 request.load_flags = 0;
546
547 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35548 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
549 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
550 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42551 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52552 };
[email protected]31a2bfe2010-02-09 08:03:39553 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59554 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52555
556 TestCompletionCallback callback;
557
[email protected]5a1d7ca2010-04-28 20:12:27558 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42559 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52560
561 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42562 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52563
[email protected]1c773ea12009-04-28 19:58:42564 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52565 EXPECT_TRUE(response != NULL);
566
567 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25568 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52569
570 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57571 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42572 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25573 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52574}
575
[email protected]3a2d3662009-03-27 03:49:14576// This test is almost the same as Ignores100 above, but the response contains
577// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57578// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14579TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59580 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40581 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43582 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14583
[email protected]1c773ea12009-04-28 19:58:42584 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14585 request.method = "GET";
586 request.url = GURL("http://www.foo.com/");
587 request.load_flags = 0;
588
589 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57590 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
591 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14592 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42593 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14594 };
[email protected]31a2bfe2010-02-09 08:03:39595 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59596 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14597
598 TestCompletionCallback callback;
599
[email protected]5a1d7ca2010-04-28 20:12:27600 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42601 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14602
603 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42604 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14605
[email protected]1c773ea12009-04-28 19:58:42606 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14607 EXPECT_TRUE(response != NULL);
608
609 EXPECT_TRUE(response->headers != NULL);
610 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
611
612 std::string response_data;
613 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42614 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14615 EXPECT_EQ("hello world", response_data);
616}
617
[email protected]ee9410e72010-01-07 01:42:38618TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
619 SessionDependencies session_deps;
620 scoped_ptr<HttpTransaction> trans(
621 new HttpNetworkTransaction(CreateSession(&session_deps)));
622
623 HttpRequestInfo request;
624 request.method = "POST";
625 request.url = GURL("http://www.foo.com/");
626 request.load_flags = 0;
627
628 MockRead data_reads[] = {
629 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
630 MockRead(true, 0),
631 };
[email protected]31a2bfe2010-02-09 08:03:39632 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38633 session_deps.socket_factory.AddSocketDataProvider(&data);
634
635 TestCompletionCallback callback;
636
[email protected]5a1d7ca2010-04-28 20:12:27637 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38638 EXPECT_EQ(ERR_IO_PENDING, rv);
639
640 rv = callback.WaitForResult();
641 EXPECT_EQ(OK, rv);
642
643 std::string response_data;
644 rv = ReadTransaction(trans.get(), &response_data);
645 EXPECT_EQ(OK, rv);
646 EXPECT_EQ("", response_data);
647}
648
649TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
650 SessionDependencies session_deps;
651 scoped_ptr<HttpTransaction> trans(
652 new HttpNetworkTransaction(CreateSession(&session_deps)));
653
654 HttpRequestInfo request;
655 request.method = "POST";
656 request.url = GURL("http://www.foo.com/");
657 request.load_flags = 0;
658
659 MockRead data_reads[] = {
660 MockRead(true, 0),
661 };
[email protected]31a2bfe2010-02-09 08:03:39662 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38663 session_deps.socket_factory.AddSocketDataProvider(&data);
664
665 TestCompletionCallback callback;
666
[email protected]5a1d7ca2010-04-28 20:12:27667 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38668 EXPECT_EQ(ERR_IO_PENDING, rv);
669
670 rv = callback.WaitForResult();
671 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
672}
673
[email protected]3d2a59b2008-09-26 19:44:25674// read_failure specifies a read failure that should cause the network
675// transaction to resend the request.
676void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
677 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59678 SessionDependencies session_deps;
679 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52680
[email protected]1c773ea12009-04-28 19:58:42681 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52682 request.method = "GET";
683 request.url = GURL("http://www.foo.com/");
684 request.load_flags = 0;
685
686 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35687 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
688 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25689 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52690 };
[email protected]31a2bfe2010-02-09 08:03:39691 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59692 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52693
694 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35695 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
696 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42697 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52698 };
[email protected]31a2bfe2010-02-09 08:03:39699 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59700 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52701
702 const char* kExpectedResponseData[] = {
703 "hello", "world"
704 };
705
706 for (int i = 0; i < 2; ++i) {
707 TestCompletionCallback callback;
708
[email protected]5695b8c2009-09-30 21:36:43709 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52710
[email protected]5a1d7ca2010-04-28 20:12:27711 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42712 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52713
714 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42715 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52716
[email protected]1c773ea12009-04-28 19:58:42717 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52718 EXPECT_TRUE(response != NULL);
719
720 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25721 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52722
723 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57724 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42725 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25726 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52727 }
728}
[email protected]3d2a59b2008-09-26 19:44:25729
730TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42731 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25732 KeepAliveConnectionResendRequestTest(read_failure);
733}
734
735TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42736 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25737 KeepAliveConnectionResendRequestTest(read_failure);
738}
739
740TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59741 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40742 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43743 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25744
[email protected]1c773ea12009-04-28 19:58:42745 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25746 request.method = "GET";
747 request.url = GURL("http://www.google.com/");
748 request.load_flags = 0;
749
750 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42751 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35752 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
753 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42754 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25755 };
[email protected]31a2bfe2010-02-09 08:03:39756 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59757 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25758
759 TestCompletionCallback callback;
760
[email protected]5a1d7ca2010-04-28 20:12:27761 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42762 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25763
764 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42765 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25766
[email protected]1c773ea12009-04-28 19:58:42767 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25768 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25769}
770
771// What do various browsers do when the server closes a non-keepalive
772// connection without sending any response header or body?
773//
774// IE7: error page
775// Safari 3.1.2 (Windows): error page
776// Firefox 3.0.1: blank page
777// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42778// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
779// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25780TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
781 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42782 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35783 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
784 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42785 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25786 };
[email protected]31a2bfe2010-02-09 08:03:39787 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
788 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42789 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25790}
[email protected]038e9a32008-10-08 22:40:16791
792// Test the request-challenge-retry sequence for basic auth.
793// (basic auth is the easiest to mock, because it has no randomness).
794TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59795 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40796 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43797 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16798
[email protected]1c773ea12009-04-28 19:58:42799 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16800 request.method = "GET";
801 request.url = GURL("http://www.google.com/");
802 request.load_flags = 0;
803
[email protected]f9ee6b52008-11-08 06:46:23804 MockWrite data_writes1[] = {
805 MockWrite("GET / HTTP/1.1\r\n"
806 "Host: www.google.com\r\n"
807 "Connection: keep-alive\r\n\r\n"),
808 };
809
[email protected]038e9a32008-10-08 22:40:16810 MockRead data_reads1[] = {
811 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
812 // Give a couple authenticate options (only the middle one is actually
813 // supported).
[email protected]22927ad2009-09-21 19:56:19814 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16815 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
816 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
817 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
818 // Large content-length -- won't matter, as connection will be reset.
819 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42820 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16821 };
822
823 // After calling trans->RestartWithAuth(), this is the request we should
824 // be issuing -- the final header line contains the credentials.
825 MockWrite data_writes2[] = {
826 MockWrite("GET / HTTP/1.1\r\n"
827 "Host: www.google.com\r\n"
828 "Connection: keep-alive\r\n"
829 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
830 };
831
832 // Lastly, the server responds with the actual content.
833 MockRead data_reads2[] = {
834 MockRead("HTTP/1.0 200 OK\r\n"),
835 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
836 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42837 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16838 };
839
[email protected]31a2bfe2010-02-09 08:03:39840 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
841 data_writes1, arraysize(data_writes1));
842 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
843 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59844 session_deps.socket_factory.AddSocketDataProvider(&data1);
845 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16846
847 TestCompletionCallback callback1;
848
[email protected]5a1d7ca2010-04-28 20:12:27849 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42850 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16851
852 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42853 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16854
[email protected]1c773ea12009-04-28 19:58:42855 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16856 EXPECT_FALSE(response == NULL);
857
858 // The password prompt info should have been set in response->auth_challenge.
859 EXPECT_FALSE(response->auth_challenge.get() == NULL);
860
[email protected]71e4573a2009-05-21 22:03:00861 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16862 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
863 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
864
865 TestCompletionCallback callback2;
866
867 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42868 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16869
870 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42871 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16872
873 response = trans->GetResponseInfo();
874 EXPECT_FALSE(response == NULL);
875 EXPECT_TRUE(response->auth_challenge.get() == NULL);
876 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16877}
878
[email protected]861fcd52009-08-26 02:33:46879TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
880 SessionDependencies session_deps;
881 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43882 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46883
884 HttpRequestInfo request;
885 request.method = "GET";
886 request.url = GURL("http://www.google.com/");
887 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
888
889 MockWrite data_writes[] = {
890 MockWrite("GET / HTTP/1.1\r\n"
891 "Host: www.google.com\r\n"
892 "Connection: keep-alive\r\n\r\n"),
893 };
894
895 MockRead data_reads[] = {
896 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
897 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
898 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
899 // Large content-length -- won't matter, as connection will be reset.
900 MockRead("Content-Length: 10000\r\n\r\n"),
901 MockRead(false, ERR_FAILED),
902 };
903
[email protected]31a2bfe2010-02-09 08:03:39904 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
905 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59906 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46907 TestCompletionCallback callback;
908
[email protected]5a1d7ca2010-04-28 20:12:27909 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46910 EXPECT_EQ(ERR_IO_PENDING, rv);
911
912 rv = callback.WaitForResult();
913 EXPECT_EQ(0, rv);
914
915 const HttpResponseInfo* response = trans->GetResponseInfo();
916 ASSERT_FALSE(response == NULL);
917 EXPECT_TRUE(response->auth_challenge.get() == NULL);
918}
919
[email protected]2d2697f92009-02-18 21:00:32920// Test the request-challenge-retry sequence for basic auth, over a keep-alive
921// connection.
922TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59923 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40924 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43925 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32926
[email protected]1c773ea12009-04-28 19:58:42927 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32928 request.method = "GET";
929 request.url = GURL("http://www.google.com/");
930 request.load_flags = 0;
931
932 MockWrite data_writes1[] = {
933 MockWrite("GET / HTTP/1.1\r\n"
934 "Host: www.google.com\r\n"
935 "Connection: keep-alive\r\n\r\n"),
936
937 // After calling trans->RestartWithAuth(), this is the request we should
938 // be issuing -- the final header line contains the credentials.
939 MockWrite("GET / HTTP/1.1\r\n"
940 "Host: www.google.com\r\n"
941 "Connection: keep-alive\r\n"
942 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
943 };
944
945 MockRead data_reads1[] = {
946 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
947 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
948 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
949 MockRead("Content-Length: 14\r\n\r\n"),
950 MockRead("Unauthorized\r\n"),
951
952 // Lastly, the server responds with the actual content.
953 MockRead("HTTP/1.1 200 OK\r\n"),
954 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
955 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42956 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32957 };
958
[email protected]31a2bfe2010-02-09 08:03:39959 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
960 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59961 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32962
963 TestCompletionCallback callback1;
964
[email protected]5a1d7ca2010-04-28 20:12:27965 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42966 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32967
968 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42969 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32970
[email protected]1c773ea12009-04-28 19:58:42971 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32972 EXPECT_FALSE(response == NULL);
973
974 // The password prompt info should have been set in response->auth_challenge.
975 EXPECT_FALSE(response->auth_challenge.get() == NULL);
976
[email protected]71e4573a2009-05-21 22:03:00977 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32978 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
979 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
980
981 TestCompletionCallback callback2;
982
983 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42984 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32985
986 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42987 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32988
989 response = trans->GetResponseInfo();
990 EXPECT_FALSE(response == NULL);
991 EXPECT_TRUE(response->auth_challenge.get() == NULL);
992 EXPECT_EQ(100, response->headers->GetContentLength());
993}
994
995// Test the request-challenge-retry sequence for basic auth, over a keep-alive
996// connection and with no response body to drain.
997TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59998 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40999 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431000 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321001
[email protected]1c773ea12009-04-28 19:58:421002 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321003 request.method = "GET";
1004 request.url = GURL("http://www.google.com/");
1005 request.load_flags = 0;
1006
1007 MockWrite data_writes1[] = {
1008 MockWrite("GET / HTTP/1.1\r\n"
1009 "Host: www.google.com\r\n"
1010 "Connection: keep-alive\r\n\r\n"),
1011
1012 // After calling trans->RestartWithAuth(), this is the request we should
1013 // be issuing -- the final header line contains the credentials.
1014 MockWrite("GET / HTTP/1.1\r\n"
1015 "Host: www.google.com\r\n"
1016 "Connection: keep-alive\r\n"
1017 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1018 };
1019
[email protected]2d2697f92009-02-18 21:00:321020 MockRead data_reads1[] = {
1021 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1022 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311023 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321024
1025 // Lastly, the server responds with the actual content.
1026 MockRead("HTTP/1.1 200 OK\r\n"),
1027 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1028 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421029 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321030 };
1031
[email protected]31a2bfe2010-02-09 08:03:391032 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1033 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591034 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321035
1036 TestCompletionCallback callback1;
1037
[email protected]5a1d7ca2010-04-28 20:12:271038 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421039 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321040
1041 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421042 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321043
[email protected]1c773ea12009-04-28 19:58:421044 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321045 EXPECT_FALSE(response == NULL);
1046
1047 // The password prompt info should have been set in response->auth_challenge.
1048 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1049
[email protected]71e4573a2009-05-21 22:03:001050 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321051 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1052 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1053
1054 TestCompletionCallback callback2;
1055
1056 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421057 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321058
1059 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421060 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321061
1062 response = trans->GetResponseInfo();
1063 EXPECT_FALSE(response == NULL);
1064 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1065 EXPECT_EQ(100, response->headers->GetContentLength());
1066}
1067
1068// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1069// connection and with a large response body to drain.
1070TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591071 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401072 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431073 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321074
[email protected]1c773ea12009-04-28 19:58:421075 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321076 request.method = "GET";
1077 request.url = GURL("http://www.google.com/");
1078 request.load_flags = 0;
1079
1080 MockWrite data_writes1[] = {
1081 MockWrite("GET / HTTP/1.1\r\n"
1082 "Host: www.google.com\r\n"
1083 "Connection: keep-alive\r\n\r\n"),
1084
1085 // After calling trans->RestartWithAuth(), this is the request we should
1086 // be issuing -- the final header line contains the credentials.
1087 MockWrite("GET / HTTP/1.1\r\n"
1088 "Host: www.google.com\r\n"
1089 "Connection: keep-alive\r\n"
1090 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1091 };
1092
1093 // Respond with 5 kb of response body.
1094 std::string large_body_string("Unauthorized");
1095 large_body_string.append(5 * 1024, ' ');
1096 large_body_string.append("\r\n");
1097
1098 MockRead data_reads1[] = {
1099 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1100 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1101 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1102 // 5134 = 12 + 5 * 1024 + 2
1103 MockRead("Content-Length: 5134\r\n\r\n"),
1104 MockRead(true, large_body_string.data(), large_body_string.size()),
1105
1106 // Lastly, the server responds with the actual content.
1107 MockRead("HTTP/1.1 200 OK\r\n"),
1108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1109 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421110 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321111 };
1112
[email protected]31a2bfe2010-02-09 08:03:391113 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1114 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591115 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321116
1117 TestCompletionCallback callback1;
1118
[email protected]5a1d7ca2010-04-28 20:12:271119 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421120 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321121
1122 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421123 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321124
[email protected]1c773ea12009-04-28 19:58:421125 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321126 EXPECT_FALSE(response == NULL);
1127
1128 // The password prompt info should have been set in response->auth_challenge.
1129 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1130
[email protected]71e4573a2009-05-21 22:03:001131 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321132 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1133 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1134
1135 TestCompletionCallback callback2;
1136
1137 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421138 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321139
1140 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421141 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321142
1143 response = trans->GetResponseInfo();
1144 EXPECT_FALSE(response == NULL);
1145 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1146 EXPECT_EQ(100, response->headers->GetContentLength());
1147}
1148
1149// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311150// connection, but the server gets impatient and closes the connection.
1151TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1152 SessionDependencies session_deps;
1153 scoped_ptr<HttpTransaction> trans(
1154 new HttpNetworkTransaction(CreateSession(&session_deps)));
1155
1156 HttpRequestInfo request;
1157 request.method = "GET";
1158 request.url = GURL("http://www.google.com/");
1159 request.load_flags = 0;
1160
1161 MockWrite data_writes1[] = {
1162 MockWrite("GET / HTTP/1.1\r\n"
1163 "Host: www.google.com\r\n"
1164 "Connection: keep-alive\r\n\r\n"),
1165 // This simulates the seemingly successful write to a closed connection
1166 // if the bug is not fixed.
1167 MockWrite("GET / HTTP/1.1\r\n"
1168 "Host: www.google.com\r\n"
1169 "Connection: keep-alive\r\n"
1170 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1171 };
1172
1173 MockRead data_reads1[] = {
1174 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1175 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1176 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1177 MockRead("Content-Length: 14\r\n\r\n"),
1178 // Tell MockTCPClientSocket to simulate the server closing the connection.
1179 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1180 MockRead("Unauthorized\r\n"),
1181 MockRead(false, OK), // The server closes the connection.
1182 };
1183
1184 // After calling trans->RestartWithAuth(), this is the request we should
1185 // be issuing -- the final header line contains the credentials.
1186 MockWrite data_writes2[] = {
1187 MockWrite("GET / HTTP/1.1\r\n"
1188 "Host: www.google.com\r\n"
1189 "Connection: keep-alive\r\n"
1190 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1191 };
1192
1193 // Lastly, the server responds with the actual content.
1194 MockRead data_reads2[] = {
1195 MockRead("HTTP/1.1 200 OK\r\n"),
1196 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1197 MockRead("Content-Length: 100\r\n\r\n"),
1198 MockRead(false, OK),
1199 };
1200
[email protected]31a2bfe2010-02-09 08:03:391201 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1202 data_writes1, arraysize(data_writes1));
1203 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1204 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311205 session_deps.socket_factory.AddSocketDataProvider(&data1);
1206 session_deps.socket_factory.AddSocketDataProvider(&data2);
1207
1208 TestCompletionCallback callback1;
1209
[email protected]5a1d7ca2010-04-28 20:12:271210 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311211 EXPECT_EQ(ERR_IO_PENDING, rv);
1212
1213 rv = callback1.WaitForResult();
1214 EXPECT_EQ(OK, rv);
1215
1216 const HttpResponseInfo* response = trans->GetResponseInfo();
1217 EXPECT_FALSE(response == NULL);
1218
1219 // The password prompt info should have been set in response->auth_challenge.
1220 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1221
1222 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1223 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1224 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1225
1226 TestCompletionCallback callback2;
1227
1228 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1229 EXPECT_EQ(ERR_IO_PENDING, rv);
1230
1231 rv = callback2.WaitForResult();
1232 EXPECT_EQ(OK, rv);
1233
1234 response = trans->GetResponseInfo();
1235 ASSERT_FALSE(response == NULL);
1236 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1237 EXPECT_EQ(100, response->headers->GetContentLength());
1238}
1239
1240// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321241// proxy connection, when setting up an SSL tunnel.
1242TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1243 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591244 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321246
[email protected]5695b8c2009-09-30 21:36:431247 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321248
[email protected]1c773ea12009-04-28 19:58:421249 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321250 request.method = "GET";
1251 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461252 // Ensure that proxy authentication is attempted even
1253 // when the no authentication data flag is set.
1254 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321255
1256 // Since we have proxy, should try to establish tunnel.
1257 MockWrite data_writes1[] = {
1258 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451259 "Host: www.google.com\r\n"
1260 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321261
1262 // After calling trans->RestartWithAuth(), this is the request we should
1263 // be issuing -- the final header line contains the credentials.
1264 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1265 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451266 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321267 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1268 };
1269
1270 // The proxy responds to the connect with a 407, using a persistent
1271 // connection.
1272 MockRead data_reads1[] = {
1273 // No credentials.
1274 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1275 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1276 MockRead("Content-Length: 10\r\n\r\n"),
1277 MockRead("0123456789"),
1278
1279 // Wrong credentials (wrong password).
1280 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1281 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1282 MockRead("Content-Length: 10\r\n\r\n"),
1283 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421284 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321285 };
1286
[email protected]31a2bfe2010-02-09 08:03:391287 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1288 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591289 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321290
1291 TestCompletionCallback callback1;
1292
[email protected]dbb83db2010-05-11 18:13:391293 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1294 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421295 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321296
1297 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421298 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391299 size_t pos = ExpectLogContainsSomewhere(
1300 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1301 NetLog::PHASE_NONE);
1302 ExpectLogContainsSomewhere(
1303 log.entries(), pos,
1304 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1305 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321306
[email protected]1c773ea12009-04-28 19:58:421307 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321308 EXPECT_FALSE(response == NULL);
1309
1310 EXPECT_TRUE(response->headers->IsKeepAlive());
1311 EXPECT_EQ(407, response->headers->response_code());
1312 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421313 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321314
1315 // The password prompt info should have been set in response->auth_challenge.
1316 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1317
[email protected]71e4573a2009-05-21 22:03:001318 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321319 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1320 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1321
1322 TestCompletionCallback callback2;
1323
1324 // Wrong password (should be "bar").
1325 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421326 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321327
1328 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421329 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321330
1331 response = trans->GetResponseInfo();
1332 EXPECT_FALSE(response == NULL);
1333
1334 EXPECT_TRUE(response->headers->IsKeepAlive());
1335 EXPECT_EQ(407, response->headers->response_code());
1336 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421337 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321338
1339 // The password prompt info should have been set in response->auth_challenge.
1340 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1341
[email protected]71e4573a2009-05-21 22:03:001342 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321343 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1344 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1345}
1346
[email protected]a8e9b162009-03-12 00:06:441347// Test that we don't read the response body when we fail to establish a tunnel,
1348// even if the user cancels the proxy's auth attempt.
1349TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1350 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591351 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441352
[email protected]e44de5d2009-06-05 20:12:451353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441354
[email protected]5695b8c2009-09-30 21:36:431355 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441356
[email protected]1c773ea12009-04-28 19:58:421357 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441358 request.method = "GET";
1359 request.url = GURL("https://www.google.com/");
1360 request.load_flags = 0;
1361
1362 // Since we have proxy, should try to establish tunnel.
1363 MockWrite data_writes[] = {
1364 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451365 "Host: www.google.com\r\n"
1366 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441367 };
1368
1369 // The proxy responds to the connect with a 407.
1370 MockRead data_reads[] = {
1371 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1372 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1373 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421374 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441375 };
1376
[email protected]31a2bfe2010-02-09 08:03:391377 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1378 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591379 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441380
1381 TestCompletionCallback callback;
1382
[email protected]5a1d7ca2010-04-28 20:12:271383 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421384 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441385
1386 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421387 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441388
[email protected]1c773ea12009-04-28 19:58:421389 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441390 EXPECT_FALSE(response == NULL);
1391
1392 EXPECT_TRUE(response->headers->IsKeepAlive());
1393 EXPECT_EQ(407, response->headers->response_code());
1394 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421395 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441396
1397 std::string response_data;
1398 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421399 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441400}
1401
[email protected]8fdbcd22010-05-05 02:54:521402// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1403// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1404TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1405 // We are using a DIRECT connection (i.e. no proxy) for this session.
1406 SessionDependencies session_deps;
1407 scoped_ptr<HttpTransaction> trans(
1408 new HttpNetworkTransaction(CreateSession(&session_deps)));
1409
1410 HttpRequestInfo request;
1411 request.method = "GET";
1412 request.url = GURL("http://www.google.com/");
1413 request.load_flags = 0;
1414
1415 MockWrite data_writes1[] = {
1416 MockWrite("GET / HTTP/1.1\r\n"
1417 "Host: www.google.com\r\n"
1418 "Connection: keep-alive\r\n\r\n"),
1419 };
1420
1421 MockRead data_reads1[] = {
1422 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1423 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1424 // Large content-length -- won't matter, as connection will be reset.
1425 MockRead("Content-Length: 10000\r\n\r\n"),
1426 MockRead(false, ERR_FAILED),
1427 };
1428
1429 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1430 data_writes1, arraysize(data_writes1));
1431 session_deps.socket_factory.AddSocketDataProvider(&data1);
1432
1433 TestCompletionCallback callback;
1434
1435 int rv = trans->Start(&request, &callback, BoundNetLog());
1436 EXPECT_EQ(ERR_IO_PENDING, rv);
1437
1438 rv = callback.WaitForResult();
1439 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1440}
1441
[email protected]ff007e162009-05-23 09:13:151442void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081443 const MockRead& status, int expected_status) {
1444 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591445 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081446
[email protected]228ff742009-06-05 01:19:591447 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081448
[email protected]5695b8c2009-09-30 21:36:431449 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081450
[email protected]1c773ea12009-04-28 19:58:421451 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081452 request.method = "GET";
1453 request.url = GURL("https://www.google.com/");
1454 request.load_flags = 0;
1455
1456 // Since we have proxy, should try to establish tunnel.
1457 MockWrite data_writes[] = {
1458 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451459 "Host: www.google.com\r\n"
1460 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081461 };
1462
1463 MockRead data_reads[] = {
1464 status,
1465 MockRead("Content-Length: 10\r\n\r\n"),
1466 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421467 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081468 };
1469
[email protected]31a2bfe2010-02-09 08:03:391470 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1471 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591472 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081473
1474 TestCompletionCallback callback;
1475
[email protected]5a1d7ca2010-04-28 20:12:271476 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421477 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081478
1479 rv = callback.WaitForResult();
1480 EXPECT_EQ(expected_status, rv);
1481}
1482
[email protected]ff007e162009-05-23 09:13:151483void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081484 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421485 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081486}
1487
1488TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1489 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1490}
1491
1492TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1493 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1494}
1495
1496TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1497 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1498}
1499
1500TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1501 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1502}
1503
1504TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1505 ConnectStatusHelper(
1506 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1507}
1508
1509TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1510 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1511}
1512
1513TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1514 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1515}
1516
1517TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1518 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1519}
1520
1521TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1522 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1523}
1524
1525TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1526 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1527}
1528
1529TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1530 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1531}
1532
1533TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1534 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1535}
1536
1537TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1538 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1539}
1540
1541TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1542 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1543}
1544
1545TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1546 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1547}
1548
1549TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1550 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1551}
1552
1553TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1554 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1555}
1556
1557TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1558 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1559}
1560
1561TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1562 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1563}
1564
1565TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1566 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1567}
1568
1569TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1570 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1571}
1572
1573TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1574 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1575}
1576
1577TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1578 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1579}
1580
1581TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1582 ConnectStatusHelperWithExpectedStatus(
1583 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421584 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081585}
1586
1587TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1588 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1589}
1590
1591TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1592 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1593}
1594
1595TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1596 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1597}
1598
1599TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1600 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1601}
1602
1603TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1604 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1605}
1606
1607TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1608 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1609}
1610
1611TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1612 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1613}
1614
1615TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1616 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1617}
1618
1619TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1620 ConnectStatusHelper(
1621 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1622}
1623
1624TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1625 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1626}
1627
1628TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1629 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1630}
1631
1632TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1633 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1634}
1635
1636TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1637 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1638}
1639
1640TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1641 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1642}
1643
1644TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1645 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1646}
1647
1648TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1649 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1650}
1651
[email protected]038e9a32008-10-08 22:40:161652// Test the flow when both the proxy server AND origin server require
1653// authentication. Again, this uses basic auth for both since that is
1654// the simplest to mock.
1655TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591656 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011657
[email protected]038e9a32008-10-08 22:40:161658 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421659 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431660 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161661
[email protected]1c773ea12009-04-28 19:58:421662 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161663 request.method = "GET";
1664 request.url = GURL("http://www.google.com/");
1665 request.load_flags = 0;
1666
[email protected]f9ee6b52008-11-08 06:46:231667 MockWrite data_writes1[] = {
1668 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1669 "Host: www.google.com\r\n"
1670 "Proxy-Connection: keep-alive\r\n\r\n"),
1671 };
1672
[email protected]038e9a32008-10-08 22:40:161673 MockRead data_reads1[] = {
1674 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1675 // Give a couple authenticate options (only the middle one is actually
1676 // supported).
[email protected]22927ad2009-09-21 19:56:191677 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1679 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1680 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1681 // Large content-length -- won't matter, as connection will be reset.
1682 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421683 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161684 };
1685
1686 // After calling trans->RestartWithAuth() the first time, this is the
1687 // request we should be issuing -- the final header line contains the
1688 // proxy's credentials.
1689 MockWrite data_writes2[] = {
1690 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1691 "Host: www.google.com\r\n"
1692 "Proxy-Connection: keep-alive\r\n"
1693 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1694 };
1695
1696 // Now the proxy server lets the request pass through to origin server.
1697 // The origin server responds with a 401.
1698 MockRead data_reads2[] = {
1699 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1700 // Note: We are using the same realm-name as the proxy server. This is
1701 // completely valid, as realms are unique across hosts.
1702 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1703 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1704 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421705 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161706 };
1707
1708 // After calling trans->RestartWithAuth() the second time, we should send
1709 // the credentials for both the proxy and origin server.
1710 MockWrite data_writes3[] = {
1711 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1712 "Host: www.google.com\r\n"
1713 "Proxy-Connection: keep-alive\r\n"
1714 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1715 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1716 };
1717
1718 // Lastly we get the desired content.
1719 MockRead data_reads3[] = {
1720 MockRead("HTTP/1.0 200 OK\r\n"),
1721 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1722 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421723 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161724 };
1725
[email protected]31a2bfe2010-02-09 08:03:391726 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1727 data_writes1, arraysize(data_writes1));
1728 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1729 data_writes2, arraysize(data_writes2));
1730 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1731 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591732 session_deps.socket_factory.AddSocketDataProvider(&data1);
1733 session_deps.socket_factory.AddSocketDataProvider(&data2);
1734 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161735
1736 TestCompletionCallback callback1;
1737
[email protected]5a1d7ca2010-04-28 20:12:271738 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421739 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161740
1741 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421742 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161743
[email protected]1c773ea12009-04-28 19:58:421744 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161745 EXPECT_FALSE(response == NULL);
1746
1747 // The password prompt info should have been set in response->auth_challenge.
1748 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1749
[email protected]71e4573a2009-05-21 22:03:001750 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161751 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1752 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1753
1754 TestCompletionCallback callback2;
1755
1756 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421757 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161758
1759 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421760 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161761
1762 response = trans->GetResponseInfo();
1763 EXPECT_FALSE(response == NULL);
1764 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1765
[email protected]71e4573a2009-05-21 22:03:001766 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161767 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1768 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1769
1770 TestCompletionCallback callback3;
1771
1772 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421773 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161774
1775 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421776 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161777
1778 response = trans->GetResponseInfo();
1779 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1780 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161781}
[email protected]4ddaf2502008-10-23 18:26:191782
[email protected]ea9dc9a2009-09-05 00:43:321783// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1784// can't hook into its internals to cause it to generate predictable NTLM
1785// authorization headers.
1786#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291787// The NTLM authentication unit tests were generated by capturing the HTTP
1788// requests and responses using Fiddler 2 and inspecting the generated random
1789// bytes in the debugger.
1790
1791// Enter the correct password and authenticate successfully.
1792TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421793 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111794 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591795 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401796 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431797 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241798
[email protected]1c773ea12009-04-28 19:58:421799 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241800 request.method = "GET";
1801 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1802 request.load_flags = 0;
1803
1804 MockWrite data_writes1[] = {
1805 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1806 "Host: 172.22.68.17\r\n"
1807 "Connection: keep-alive\r\n\r\n"),
1808 };
1809
1810 MockRead data_reads1[] = {
1811 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1812 // Negotiate and NTLM are often requested together. We only support NTLM.
1813 MockRead("WWW-Authenticate: Negotiate\r\n"),
1814 MockRead("WWW-Authenticate: NTLM\r\n"),
1815 MockRead("Connection: close\r\n"),
1816 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361817 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241818 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421819 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241820 };
1821
1822 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221823 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241824 // request we should be issuing -- the final header line contains a Type
1825 // 1 message.
1826 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1827 "Host: 172.22.68.17\r\n"
1828 "Connection: keep-alive\r\n"
1829 "Authorization: NTLM "
1830 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1831
1832 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1833 // (the credentials for the origin server). The second request continues
1834 // on the same connection.
1835 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1836 "Host: 172.22.68.17\r\n"
1837 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291838 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1839 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1840 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1841 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1842 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241843 };
1844
1845 MockRead data_reads2[] = {
1846 // The origin server responds with a Type 2 message.
1847 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1848 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291849 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241850 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1851 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1852 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1853 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1854 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1855 "BtAAAAAAA=\r\n"),
1856 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361857 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241858 MockRead("You are not authorized to view this page\r\n"),
1859
1860 // Lastly we get the desired content.
1861 MockRead("HTTP/1.1 200 OK\r\n"),
1862 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1863 MockRead("Content-Length: 13\r\n\r\n"),
1864 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421865 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241866 };
1867
[email protected]31a2bfe2010-02-09 08:03:391868 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1869 data_writes1, arraysize(data_writes1));
1870 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1871 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591872 session_deps.socket_factory.AddSocketDataProvider(&data1);
1873 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241874
1875 TestCompletionCallback callback1;
1876
[email protected]5a1d7ca2010-04-28 20:12:271877 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421878 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241879
1880 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421881 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241882
[email protected]0757e7702009-03-27 04:00:221883 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1884 TestCompletionCallback callback2;
1885 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421886 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221887 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421888 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221889 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1890
[email protected]1c773ea12009-04-28 19:58:421891 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241892 EXPECT_FALSE(response == NULL);
1893
1894 // The password prompt info should have been set in response->auth_challenge.
1895 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1896
[email protected]71e4573a2009-05-21 22:03:001897 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241898 EXPECT_EQ(L"", response->auth_challenge->realm);
1899 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1900
[email protected]0757e7702009-03-27 04:00:221901 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241902
[email protected]0757e7702009-03-27 04:00:221903 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421904 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241905
[email protected]0757e7702009-03-27 04:00:221906 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421907 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241908
1909 response = trans->GetResponseInfo();
1910 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1911 EXPECT_EQ(13, response->headers->GetContentLength());
1912}
1913
[email protected]385a4672009-03-11 22:21:291914// Enter a wrong password, and then the correct one.
1915TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421916 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111917 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591918 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401919 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431920 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291921
[email protected]1c773ea12009-04-28 19:58:421922 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291923 request.method = "GET";
1924 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1925 request.load_flags = 0;
1926
1927 MockWrite data_writes1[] = {
1928 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1929 "Host: 172.22.68.17\r\n"
1930 "Connection: keep-alive\r\n\r\n"),
1931 };
1932
1933 MockRead data_reads1[] = {
1934 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1935 // Negotiate and NTLM are often requested together. We only support NTLM.
1936 MockRead("WWW-Authenticate: Negotiate\r\n"),
1937 MockRead("WWW-Authenticate: NTLM\r\n"),
1938 MockRead("Connection: close\r\n"),
1939 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361940 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291941 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421942 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291943 };
1944
1945 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221946 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291947 // request we should be issuing -- the final header line contains a Type
1948 // 1 message.
1949 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1950 "Host: 172.22.68.17\r\n"
1951 "Connection: keep-alive\r\n"
1952 "Authorization: NTLM "
1953 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1954
1955 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1956 // (the credentials for the origin server). The second request continues
1957 // on the same connection.
1958 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1959 "Host: 172.22.68.17\r\n"
1960 "Connection: keep-alive\r\n"
1961 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1962 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1963 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1964 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1965 "4Ww7b7E=\r\n\r\n"),
1966 };
1967
1968 MockRead data_reads2[] = {
1969 // The origin server responds with a Type 2 message.
1970 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1971 MockRead("WWW-Authenticate: NTLM "
1972 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1973 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1974 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1975 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1976 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1977 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1978 "BtAAAAAAA=\r\n"),
1979 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361980 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291981 MockRead("You are not authorized to view this page\r\n"),
1982
1983 // Wrong password.
1984 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1985 MockRead("WWW-Authenticate: Negotiate\r\n"),
1986 MockRead("WWW-Authenticate: NTLM\r\n"),
1987 MockRead("Connection: close\r\n"),
1988 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361989 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291990 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421991 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291992 };
1993
1994 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221995 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291996 // request we should be issuing -- the final header line contains a Type
1997 // 1 message.
1998 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1999 "Host: 172.22.68.17\r\n"
2000 "Connection: keep-alive\r\n"
2001 "Authorization: NTLM "
2002 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2003
2004 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2005 // (the credentials for the origin server). The second request continues
2006 // on the same connection.
2007 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2008 "Host: 172.22.68.17\r\n"
2009 "Connection: keep-alive\r\n"
2010 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2011 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2012 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2013 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2014 "+4MUm7c=\r\n\r\n"),
2015 };
2016
2017 MockRead data_reads3[] = {
2018 // The origin server responds with a Type 2 message.
2019 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2020 MockRead("WWW-Authenticate: NTLM "
2021 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2022 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2023 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2024 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2025 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2026 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2027 "BtAAAAAAA=\r\n"),
2028 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362029 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292030 MockRead("You are not authorized to view this page\r\n"),
2031
2032 // Lastly we get the desired content.
2033 MockRead("HTTP/1.1 200 OK\r\n"),
2034 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2035 MockRead("Content-Length: 13\r\n\r\n"),
2036 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422037 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292038 };
2039
[email protected]31a2bfe2010-02-09 08:03:392040 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2041 data_writes1, arraysize(data_writes1));
2042 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2043 data_writes2, arraysize(data_writes2));
2044 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2045 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592046 session_deps.socket_factory.AddSocketDataProvider(&data1);
2047 session_deps.socket_factory.AddSocketDataProvider(&data2);
2048 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292049
2050 TestCompletionCallback callback1;
2051
[email protected]5a1d7ca2010-04-28 20:12:272052 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422053 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292054
2055 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422056 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292057
[email protected]0757e7702009-03-27 04:00:222058 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292059 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222060 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422061 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292062 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422063 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222064 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292065
[email protected]1c773ea12009-04-28 19:58:422066 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292067 EXPECT_FALSE(response == NULL);
2068
2069 // The password prompt info should have been set in response->auth_challenge.
2070 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2071
[email protected]71e4573a2009-05-21 22:03:002072 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292073 EXPECT_EQ(L"", response->auth_challenge->realm);
2074 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2075
2076 TestCompletionCallback callback3;
2077
[email protected]0757e7702009-03-27 04:00:222078 // Enter the wrong password.
2079 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422080 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292081
2082 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422083 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292084
[email protected]0757e7702009-03-27 04:00:222085 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2086 TestCompletionCallback callback4;
2087 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422088 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222089 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422090 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222091 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2092
2093 response = trans->GetResponseInfo();
2094 EXPECT_FALSE(response == NULL);
2095
2096 // The password prompt info should have been set in response->auth_challenge.
2097 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2098
[email protected]71e4573a2009-05-21 22:03:002099 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222100 EXPECT_EQ(L"", response->auth_challenge->realm);
2101 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2102
2103 TestCompletionCallback callback5;
2104
2105 // Now enter the right password.
2106 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222108
2109 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422110 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222111
[email protected]385a4672009-03-11 22:21:292112 response = trans->GetResponseInfo();
2113 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2114 EXPECT_EQ(13, response->headers->GetContentLength());
2115}
[email protected]ea9dc9a2009-09-05 00:43:322116#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292117
[email protected]4ddaf2502008-10-23 18:26:192118// Test reading a server response which has only headers, and no body.
2119// After some maximum number of bytes is consumed, the transaction should
2120// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2121TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592122 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402123 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432124 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192125
[email protected]1c773ea12009-04-28 19:58:422126 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192127 request.method = "GET";
2128 request.url = GURL("http://www.google.com/");
2129 request.load_flags = 0;
2130
[email protected]b75b7b2f2009-10-06 00:54:532131 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432132 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532133 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192134
2135 MockRead data_reads[] = {
2136 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432137 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192138 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422139 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192140 };
[email protected]31a2bfe2010-02-09 08:03:392141 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592142 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192143
2144 TestCompletionCallback callback;
2145
[email protected]5a1d7ca2010-04-28 20:12:272146 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192148
2149 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422150 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192151
[email protected]1c773ea12009-04-28 19:58:422152 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192153 EXPECT_TRUE(response == NULL);
2154}
[email protected]f4e426b2008-11-05 00:24:492155
2156// Make sure that we don't try to reuse a TCPClientSocket when failing to
2157// establish tunnel.
2158// http://code.google.com/p/chromium/issues/detail?id=3772
2159TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2160 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592161 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012162
[email protected]228ff742009-06-05 01:19:592163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492164
[email protected]5695b8c2009-09-30 21:36:432165 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492166
[email protected]1c773ea12009-04-28 19:58:422167 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492168 request.method = "GET";
2169 request.url = GURL("https://www.google.com/");
2170 request.load_flags = 0;
2171
2172 // Since we have proxy, should try to establish tunnel.
2173 MockWrite data_writes1[] = {
2174 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452175 "Host: www.google.com\r\n"
2176 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492177 };
2178
[email protected]77848d12008-11-14 00:00:222179 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492180 // connection. Usually a proxy would return 501 (not implemented),
2181 // or 200 (tunnel established).
2182 MockRead data_reads1[] = {
2183 MockRead("HTTP/1.1 404 Not Found\r\n"),
2184 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422185 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492186 };
2187
[email protected]31a2bfe2010-02-09 08:03:392188 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2189 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592190 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492191
2192 TestCompletionCallback callback1;
2193
[email protected]5a1d7ca2010-04-28 20:12:272194 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422195 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492196
2197 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422198 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492199
[email protected]1c773ea12009-04-28 19:58:422200 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082201 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492202
[email protected]b4404c02009-04-10 16:38:522203 // 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
[email protected]f4e426b2008-11-05 00:24:492207 // We now check to make sure the TCPClientSocket was not added back to
2208 // the pool.
[email protected]a937a06d2009-08-19 21:19:242209 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492210 trans.reset();
[email protected]b4404c02009-04-10 16:38:522211 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492212 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242213 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492214}
[email protected]372d34a2008-11-05 21:30:512215
[email protected]1b157c02009-04-21 01:55:402216// Make sure that we recycle a socket after reading all of the response body.
2217TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592218 SessionDependencies session_deps;
2219 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402220
[email protected]5695b8c2009-09-30 21:36:432221 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402222
[email protected]1c773ea12009-04-28 19:58:422223 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402224 request.method = "GET";
2225 request.url = GURL("http://www.google.com/");
2226 request.load_flags = 0;
2227
2228 MockRead data_reads[] = {
2229 // A part of the response body is received with the response headers.
2230 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2231 // The rest of the response body is received in two parts.
2232 MockRead("lo"),
2233 MockRead(" world"),
2234 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422235 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402236 };
2237
[email protected]31a2bfe2010-02-09 08:03:392238 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592239 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402240
2241 TestCompletionCallback callback;
2242
[email protected]5a1d7ca2010-04-28 20:12:272243 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422244 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402245
2246 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422247 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402248
[email protected]1c773ea12009-04-28 19:58:422249 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402250 EXPECT_TRUE(response != NULL);
2251
2252 EXPECT_TRUE(response->headers != NULL);
2253 std::string status_line = response->headers->GetStatusLine();
2254 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2255
[email protected]a937a06d2009-08-19 21:19:242256 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402257
2258 std::string response_data;
2259 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422260 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402261 EXPECT_EQ("hello world", response_data);
2262
2263 // Empty the current queue. This is necessary because idle sockets are
2264 // added to the connection pool asynchronously with a PostTask.
2265 MessageLoop::current()->RunAllPending();
2266
2267 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242268 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402269}
2270
[email protected]b4404c02009-04-10 16:38:522271// Make sure that we recycle a socket after a zero-length response.
2272// http://crbug.com/9880
2273TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592274 SessionDependencies session_deps;
2275 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522276
[email protected]5695b8c2009-09-30 21:36:432277 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522278
[email protected]1c773ea12009-04-28 19:58:422279 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522280 request.method = "GET";
2281 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2282 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2283 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2284 "rt=prt.2642,ol.2649,xjs.2951");
2285 request.load_flags = 0;
2286
2287 MockRead data_reads[] = {
2288 MockRead("HTTP/1.1 204 No Content\r\n"
2289 "Content-Length: 0\r\n"
2290 "Content-Type: text/html\r\n\r\n"),
2291 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422292 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522293 };
2294
[email protected]31a2bfe2010-02-09 08:03:392295 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592296 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522297
2298 TestCompletionCallback callback;
2299
[email protected]5a1d7ca2010-04-28 20:12:272300 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422301 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522302
2303 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422304 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522305
[email protected]1c773ea12009-04-28 19:58:422306 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522307 EXPECT_TRUE(response != NULL);
2308
2309 EXPECT_TRUE(response->headers != NULL);
2310 std::string status_line = response->headers->GetStatusLine();
2311 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2312
[email protected]a937a06d2009-08-19 21:19:242313 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522314
2315 std::string response_data;
2316 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422317 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522318 EXPECT_EQ("", response_data);
2319
2320 // Empty the current queue. This is necessary because idle sockets are
2321 // added to the connection pool asynchronously with a PostTask.
2322 MessageLoop::current()->RunAllPending();
2323
2324 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242325 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522326}
2327
[email protected]372d34a2008-11-05 21:30:512328TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422329 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512330 // Transaction 1: a GET request that succeeds. The socket is recycled
2331 // after use.
2332 request[0].method = "GET";
2333 request[0].url = GURL("http://www.google.com/");
2334 request[0].load_flags = 0;
2335 // Transaction 2: a POST request. Reuses the socket kept alive from
2336 // transaction 1. The first attempts fails when writing the POST data.
2337 // This causes the transaction to retry with a new socket. The second
2338 // attempt succeeds.
2339 request[1].method = "POST";
2340 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422341 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512342 request[1].upload_data->AppendBytes("foo", 3);
2343 request[1].load_flags = 0;
2344
[email protected]228ff742009-06-05 01:19:592345 SessionDependencies session_deps;
2346 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512347
2348 // The first socket is used for transaction 1 and the first attempt of
2349 // transaction 2.
2350
2351 // The response of transaction 1.
2352 MockRead data_reads1[] = {
2353 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2354 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422355 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512356 };
2357 // The mock write results of transaction 1 and the first attempt of
2358 // transaction 2.
2359 MockWrite data_writes1[] = {
2360 MockWrite(false, 64), // GET
2361 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422362 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512363 };
[email protected]31a2bfe2010-02-09 08:03:392364 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2365 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512366
2367 // The second socket is used for the second attempt of transaction 2.
2368
2369 // The response of transaction 2.
2370 MockRead data_reads2[] = {
2371 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2372 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422373 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512374 };
2375 // The mock write results of the second attempt of transaction 2.
2376 MockWrite data_writes2[] = {
2377 MockWrite(false, 93), // POST
2378 MockWrite(false, 3), // POST data
2379 };
[email protected]31a2bfe2010-02-09 08:03:392380 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2381 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512382
[email protected]5ecc992a42009-11-11 01:41:592383 session_deps.socket_factory.AddSocketDataProvider(&data1);
2384 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512385
2386 const char* kExpectedResponseData[] = {
2387 "hello world", "welcome"
2388 };
2389
2390 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422391 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432392 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512393
2394 TestCompletionCallback callback;
2395
[email protected]5a1d7ca2010-04-28 20:12:272396 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422397 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512398
2399 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422400 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512401
[email protected]1c773ea12009-04-28 19:58:422402 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512403 EXPECT_TRUE(response != NULL);
2404
2405 EXPECT_TRUE(response->headers != NULL);
2406 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2407
2408 std::string response_data;
2409 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422410 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512411 EXPECT_EQ(kExpectedResponseData[i], response_data);
2412 }
2413}
[email protected]f9ee6b52008-11-08 06:46:232414
2415// Test the request-challenge-retry sequence for basic auth when there is
2416// an identity in the URL. The request should be sent as normal, but when
2417// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322418TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592419 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402420 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432421 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232422
[email protected]1c773ea12009-04-28 19:58:422423 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232424 request.method = "GET";
2425 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292426 request.url = GURL("http://foo:b@[email protected]/");
2427
2428 // The password contains an escaped character -- for this test to pass it
2429 // will need to be unescaped by HttpNetworkTransaction.
2430 EXPECT_EQ("b%40r", request.url.password());
2431
[email protected]ea9dc9a2009-09-05 00:43:322432 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232433
2434 MockWrite data_writes1[] = {
2435 MockWrite("GET / HTTP/1.1\r\n"
2436 "Host: www.google.com\r\n"
2437 "Connection: keep-alive\r\n\r\n"),
2438 };
2439
2440 MockRead data_reads1[] = {
2441 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2442 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2443 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422444 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232445 };
2446
2447 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322448 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232449 MockWrite data_writes2[] = {
2450 MockWrite("GET / HTTP/1.1\r\n"
2451 "Host: www.google.com\r\n"
2452 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292453 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232454 };
2455
2456 MockRead data_reads2[] = {
2457 MockRead("HTTP/1.0 200 OK\r\n"),
2458 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422459 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232460 };
2461
[email protected]31a2bfe2010-02-09 08:03:392462 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2463 data_writes1, arraysize(data_writes1));
2464 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2465 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592466 session_deps.socket_factory.AddSocketDataProvider(&data1);
2467 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232468
2469 TestCompletionCallback callback1;
2470
[email protected]5a1d7ca2010-04-28 20:12:272471 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422472 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232473
2474 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422475 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232476
[email protected]0757e7702009-03-27 04:00:222477 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2478 TestCompletionCallback callback2;
2479 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422480 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222481 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422482 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222483 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2484
[email protected]1c773ea12009-04-28 19:58:422485 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232486 EXPECT_FALSE(response == NULL);
2487
2488 // There is no challenge info, since the identity in URL worked.
2489 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2490
2491 EXPECT_EQ(100, response->headers->GetContentLength());
2492
2493 // Empty the current queue.
2494 MessageLoop::current()->RunAllPending();
2495}
2496
[email protected]ea9dc9a2009-09-05 00:43:322497// Test the request-challenge-retry sequence for basic auth when there is
2498// an incorrect identity in the URL. The identity from the URL should be used
2499// only once.
2500TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2501 SessionDependencies session_deps;
2502 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432503 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322504
2505 HttpRequestInfo request;
2506 request.method = "GET";
2507 // Note: the URL has a username:password in it. The password "baz" is
2508 // wrong (should be "bar").
2509 request.url = GURL("http://foo:[email protected]/");
2510
2511 request.load_flags = LOAD_NORMAL;
2512
2513 MockWrite data_writes1[] = {
2514 MockWrite("GET / HTTP/1.1\r\n"
2515 "Host: www.google.com\r\n"
2516 "Connection: keep-alive\r\n\r\n"),
2517 };
2518
2519 MockRead data_reads1[] = {
2520 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2521 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2522 MockRead("Content-Length: 10\r\n\r\n"),
2523 MockRead(false, ERR_FAILED),
2524 };
2525
2526 // After the challenge above, the transaction will be restarted using the
2527 // identity from the url (foo, baz) to answer the challenge.
2528 MockWrite data_writes2[] = {
2529 MockWrite("GET / HTTP/1.1\r\n"
2530 "Host: www.google.com\r\n"
2531 "Connection: keep-alive\r\n"
2532 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2533 };
2534
2535 MockRead data_reads2[] = {
2536 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2537 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2538 MockRead("Content-Length: 10\r\n\r\n"),
2539 MockRead(false, ERR_FAILED),
2540 };
2541
2542 // After the challenge above, the transaction will be restarted using the
2543 // identity supplied by the user (foo, bar) to answer the challenge.
2544 MockWrite data_writes3[] = {
2545 MockWrite("GET / HTTP/1.1\r\n"
2546 "Host: www.google.com\r\n"
2547 "Connection: keep-alive\r\n"
2548 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2549 };
2550
2551 MockRead data_reads3[] = {
2552 MockRead("HTTP/1.0 200 OK\r\n"),
2553 MockRead("Content-Length: 100\r\n\r\n"),
2554 MockRead(false, OK),
2555 };
2556
[email protected]31a2bfe2010-02-09 08:03:392557 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2558 data_writes1, arraysize(data_writes1));
2559 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2560 data_writes2, arraysize(data_writes2));
2561 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2562 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592563 session_deps.socket_factory.AddSocketDataProvider(&data1);
2564 session_deps.socket_factory.AddSocketDataProvider(&data2);
2565 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322566
2567 TestCompletionCallback callback1;
2568
[email protected]5a1d7ca2010-04-28 20:12:272569 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322570 EXPECT_EQ(ERR_IO_PENDING, rv);
2571
2572 rv = callback1.WaitForResult();
2573 EXPECT_EQ(OK, rv);
2574
2575 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2576 TestCompletionCallback callback2;
2577 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2578 EXPECT_EQ(ERR_IO_PENDING, rv);
2579 rv = callback2.WaitForResult();
2580 EXPECT_EQ(OK, rv);
2581 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2582
2583 const HttpResponseInfo* response = trans->GetResponseInfo();
2584 EXPECT_FALSE(response == NULL);
2585 // The password prompt info should have been set in response->auth_challenge.
2586 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2587
2588 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2589 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2590 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2591
2592 TestCompletionCallback callback3;
2593 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2594 EXPECT_EQ(ERR_IO_PENDING, rv);
2595 rv = callback3.WaitForResult();
2596 EXPECT_EQ(OK, rv);
2597 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2598
2599 response = trans->GetResponseInfo();
2600 EXPECT_FALSE(response == NULL);
2601
2602 // There is no challenge info, since the identity worked.
2603 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2604
2605 EXPECT_EQ(100, response->headers->GetContentLength());
2606
2607 // Empty the current queue.
2608 MessageLoop::current()->RunAllPending();
2609}
2610
[email protected]f9ee6b52008-11-08 06:46:232611// Test that previously tried username/passwords for a realm get re-used.
2612TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592613 SessionDependencies session_deps;
2614 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232615
2616 // Transaction 1: authenticate (foo, bar) on MyRealm1
2617 {
[email protected]5695b8c2009-09-30 21:36:432618 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232619
[email protected]1c773ea12009-04-28 19:58:422620 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232621 request.method = "GET";
2622 request.url = GURL("http://www.google.com/x/y/z");
2623 request.load_flags = 0;
2624
2625 MockWrite data_writes1[] = {
2626 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2627 "Host: www.google.com\r\n"
2628 "Connection: keep-alive\r\n\r\n"),
2629 };
2630
2631 MockRead data_reads1[] = {
2632 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2633 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2634 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422635 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232636 };
2637
2638 // Resend with authorization (username=foo, password=bar)
2639 MockWrite data_writes2[] = {
2640 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2641 "Host: www.google.com\r\n"
2642 "Connection: keep-alive\r\n"
2643 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2644 };
2645
2646 // Sever accepts the authorization.
2647 MockRead data_reads2[] = {
2648 MockRead("HTTP/1.0 200 OK\r\n"),
2649 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422650 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232651 };
2652
[email protected]31a2bfe2010-02-09 08:03:392653 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2654 data_writes1, arraysize(data_writes1));
2655 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2656 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592657 session_deps.socket_factory.AddSocketDataProvider(&data1);
2658 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232659
2660 TestCompletionCallback callback1;
2661
[email protected]5a1d7ca2010-04-28 20:12:272662 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422663 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232664
2665 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422666 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232667
[email protected]1c773ea12009-04-28 19:58:422668 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232669 EXPECT_FALSE(response == NULL);
2670
2671 // The password prompt info should have been set in
2672 // response->auth_challenge.
2673 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2674
[email protected]71e4573a2009-05-21 22:03:002675 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232676 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2677 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2678
2679 TestCompletionCallback callback2;
2680
2681 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422682 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232683
2684 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422685 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232686
2687 response = trans->GetResponseInfo();
2688 EXPECT_FALSE(response == NULL);
2689 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2690 EXPECT_EQ(100, response->headers->GetContentLength());
2691 }
2692
2693 // ------------------------------------------------------------------------
2694
2695 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2696 {
[email protected]5695b8c2009-09-30 21:36:432697 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232698
[email protected]1c773ea12009-04-28 19:58:422699 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232700 request.method = "GET";
2701 // Note that Transaction 1 was at /x/y/z, so this is in the same
2702 // protection space as MyRealm1.
2703 request.url = GURL("http://www.google.com/x/y/a/b");
2704 request.load_flags = 0;
2705
2706 MockWrite data_writes1[] = {
2707 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2708 "Host: www.google.com\r\n"
2709 "Connection: keep-alive\r\n"
2710 // Send preemptive authorization for MyRealm1
2711 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2712 };
2713
2714 // The server didn't like the preemptive authorization, and
2715 // challenges us for a different realm (MyRealm2).
2716 MockRead data_reads1[] = {
2717 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2718 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2719 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422720 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232721 };
2722
2723 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2724 MockWrite data_writes2[] = {
2725 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2726 "Host: www.google.com\r\n"
2727 "Connection: keep-alive\r\n"
2728 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2729 };
2730
2731 // Sever accepts the authorization.
2732 MockRead data_reads2[] = {
2733 MockRead("HTTP/1.0 200 OK\r\n"),
2734 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422735 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232736 };
2737
[email protected]31a2bfe2010-02-09 08:03:392738 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2739 data_writes1, arraysize(data_writes1));
2740 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2741 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592742 session_deps.socket_factory.AddSocketDataProvider(&data1);
2743 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232744
2745 TestCompletionCallback callback1;
2746
[email protected]5a1d7ca2010-04-28 20:12:272747 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422748 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232749
2750 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422751 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232752
[email protected]1c773ea12009-04-28 19:58:422753 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232754 EXPECT_FALSE(response == NULL);
2755
2756 // The password prompt info should have been set in
2757 // response->auth_challenge.
2758 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2759
[email protected]71e4573a2009-05-21 22:03:002760 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232761 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2762 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2763
2764 TestCompletionCallback callback2;
2765
2766 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422767 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232768
2769 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422770 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232771
2772 response = trans->GetResponseInfo();
2773 EXPECT_FALSE(response == NULL);
2774 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2775 EXPECT_EQ(100, response->headers->GetContentLength());
2776 }
2777
2778 // ------------------------------------------------------------------------
2779
2780 // Transaction 3: Resend a request in MyRealm's protection space --
2781 // succeed with preemptive authorization.
2782 {
[email protected]5695b8c2009-09-30 21:36:432783 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232784
[email protected]1c773ea12009-04-28 19:58:422785 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232786 request.method = "GET";
2787 request.url = GURL("http://www.google.com/x/y/z2");
2788 request.load_flags = 0;
2789
2790 MockWrite data_writes1[] = {
2791 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2792 "Host: www.google.com\r\n"
2793 "Connection: keep-alive\r\n"
2794 // The authorization for MyRealm1 gets sent preemptively
2795 // (since the url is in the same protection space)
2796 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2797 };
2798
2799 // Sever accepts the preemptive authorization
2800 MockRead data_reads1[] = {
2801 MockRead("HTTP/1.0 200 OK\r\n"),
2802 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422803 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232804 };
2805
[email protected]31a2bfe2010-02-09 08:03:392806 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2807 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592808 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232809
2810 TestCompletionCallback callback1;
2811
[email protected]5a1d7ca2010-04-28 20:12:272812 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422813 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232814
2815 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422816 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232817
[email protected]1c773ea12009-04-28 19:58:422818 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232819 EXPECT_FALSE(response == NULL);
2820
2821 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2822 EXPECT_EQ(100, response->headers->GetContentLength());
2823 }
2824
2825 // ------------------------------------------------------------------------
2826
2827 // Transaction 4: request another URL in MyRealm (however the
2828 // url is not known to belong to the protection space, so no pre-auth).
2829 {
[email protected]5695b8c2009-09-30 21:36:432830 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232831
[email protected]1c773ea12009-04-28 19:58:422832 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232833 request.method = "GET";
2834 request.url = GURL("http://www.google.com/x/1");
2835 request.load_flags = 0;
2836
2837 MockWrite data_writes1[] = {
2838 MockWrite("GET /x/1 HTTP/1.1\r\n"
2839 "Host: www.google.com\r\n"
2840 "Connection: keep-alive\r\n\r\n"),
2841 };
2842
2843 MockRead data_reads1[] = {
2844 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2845 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2846 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422847 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232848 };
2849
2850 // Resend with authorization from MyRealm's cache.
2851 MockWrite data_writes2[] = {
2852 MockWrite("GET /x/1 HTTP/1.1\r\n"
2853 "Host: www.google.com\r\n"
2854 "Connection: keep-alive\r\n"
2855 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2856 };
2857
2858 // Sever accepts the authorization.
2859 MockRead data_reads2[] = {
2860 MockRead("HTTP/1.0 200 OK\r\n"),
2861 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422862 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232863 };
2864
[email protected]31a2bfe2010-02-09 08:03:392865 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2866 data_writes1, arraysize(data_writes1));
2867 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2868 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592869 session_deps.socket_factory.AddSocketDataProvider(&data1);
2870 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232871
2872 TestCompletionCallback callback1;
2873
[email protected]5a1d7ca2010-04-28 20:12:272874 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422875 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232876
2877 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422878 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232879
[email protected]0757e7702009-03-27 04:00:222880 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2881 TestCompletionCallback callback2;
2882 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422883 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222884 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422885 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222886 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2887
[email protected]1c773ea12009-04-28 19:58:422888 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232889 EXPECT_FALSE(response == NULL);
2890 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2891 EXPECT_EQ(100, response->headers->GetContentLength());
2892 }
2893
2894 // ------------------------------------------------------------------------
2895
2896 // Transaction 5: request a URL in MyRealm, but the server rejects the
2897 // cached identity. Should invalidate and re-prompt.
2898 {
[email protected]5695b8c2009-09-30 21:36:432899 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232900
[email protected]1c773ea12009-04-28 19:58:422901 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232902 request.method = "GET";
2903 request.url = GURL("http://www.google.com/p/q/t");
2904 request.load_flags = 0;
2905
2906 MockWrite data_writes1[] = {
2907 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2908 "Host: www.google.com\r\n"
2909 "Connection: keep-alive\r\n\r\n"),
2910 };
2911
2912 MockRead data_reads1[] = {
2913 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2914 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2915 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422916 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232917 };
2918
2919 // Resend with authorization from cache for MyRealm.
2920 MockWrite data_writes2[] = {
2921 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2922 "Host: www.google.com\r\n"
2923 "Connection: keep-alive\r\n"
2924 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2925 };
2926
2927 // Sever rejects the authorization.
2928 MockRead data_reads2[] = {
2929 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2930 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2931 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422932 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232933 };
2934
2935 // At this point we should prompt for new credentials for MyRealm.
2936 // Restart with username=foo3, password=foo4.
2937 MockWrite data_writes3[] = {
2938 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2939 "Host: www.google.com\r\n"
2940 "Connection: keep-alive\r\n"
2941 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2942 };
2943
2944 // Sever accepts the authorization.
2945 MockRead data_reads3[] = {
2946 MockRead("HTTP/1.0 200 OK\r\n"),
2947 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422948 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232949 };
2950
[email protected]31a2bfe2010-02-09 08:03:392951 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2952 data_writes1, arraysize(data_writes1));
2953 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2954 data_writes2, arraysize(data_writes2));
2955 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2956 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592957 session_deps.socket_factory.AddSocketDataProvider(&data1);
2958 session_deps.socket_factory.AddSocketDataProvider(&data2);
2959 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232960
2961 TestCompletionCallback callback1;
2962
[email protected]5a1d7ca2010-04-28 20:12:272963 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422964 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232965
2966 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422967 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232968
[email protected]0757e7702009-03-27 04:00:222969 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2970 TestCompletionCallback callback2;
2971 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422972 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222973 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422974 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222975 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2976
[email protected]1c773ea12009-04-28 19:58:422977 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232978 EXPECT_FALSE(response == NULL);
2979
2980 // The password prompt info should have been set in
2981 // response->auth_challenge.
2982 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2983
[email protected]71e4573a2009-05-21 22:03:002984 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232985 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2986 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2987
[email protected]0757e7702009-03-27 04:00:222988 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232989
[email protected]0757e7702009-03-27 04:00:222990 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422991 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232992
[email protected]0757e7702009-03-27 04:00:222993 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422994 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232995
2996 response = trans->GetResponseInfo();
2997 EXPECT_FALSE(response == NULL);
2998 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2999 EXPECT_EQ(100, response->headers->GetContentLength());
3000 }
3001}
[email protected]89ceba9a2009-03-21 03:46:063002
[email protected]3c32c5f2010-05-18 15:18:123003// Tests that nonce count increments when multiple auth attempts
3004// are started with the same nonce.
3005TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3006 SessionDependencies session_deps;
3007 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3008 HttpAuthHandlerDigest::SetFixedCnonce(true);
3009
3010 // Transaction 1: authenticate (foo, bar) on MyRealm1
3011 {
3012 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3013
3014 HttpRequestInfo request;
3015 request.method = "GET";
3016 request.url = GURL("http://www.google.com/x/y/z");
3017 request.load_flags = 0;
3018
3019 MockWrite data_writes1[] = {
3020 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3021 "Host: www.google.com\r\n"
3022 "Connection: keep-alive\r\n\r\n"),
3023 };
3024
3025 MockRead data_reads1[] = {
3026 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3027 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3028 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3029 MockRead(false, OK),
3030 };
3031
3032 // Resend with authorization (username=foo, password=bar)
3033 MockWrite data_writes2[] = {
3034 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3035 "Host: www.google.com\r\n"
3036 "Connection: keep-alive\r\n"
3037 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3038 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3039 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3040 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3041 };
3042
3043 // Sever accepts the authorization.
3044 MockRead data_reads2[] = {
3045 MockRead("HTTP/1.0 200 OK\r\n"),
3046 MockRead(false, OK),
3047 };
3048
3049 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3050 data_writes1, arraysize(data_writes1));
3051 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3052 data_writes2, arraysize(data_writes2));
3053 session_deps.socket_factory.AddSocketDataProvider(&data1);
3054 session_deps.socket_factory.AddSocketDataProvider(&data2);
3055
3056 TestCompletionCallback callback1;
3057
3058 int rv = trans->Start(&request, &callback1, BoundNetLog());
3059 EXPECT_EQ(ERR_IO_PENDING, rv);
3060
3061 rv = callback1.WaitForResult();
3062 EXPECT_EQ(OK, rv);
3063
3064 const HttpResponseInfo* response = trans->GetResponseInfo();
3065 ASSERT_FALSE(response == NULL);
3066
3067 // The password prompt info should have been set in
3068 // response->auth_challenge.
3069 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3070
3071 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3072 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3073 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3074
3075 TestCompletionCallback callback2;
3076
3077 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3078 EXPECT_EQ(ERR_IO_PENDING, rv);
3079
3080 rv = callback2.WaitForResult();
3081 EXPECT_EQ(OK, rv);
3082
3083 response = trans->GetResponseInfo();
3084 ASSERT_FALSE(response == NULL);
3085 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3086 }
3087
3088 // ------------------------------------------------------------------------
3089
3090 // Transaction 2: Request another resource in digestive's protection space.
3091 // This will preemptively add an Authorization header which should have an
3092 // "nc" value of 2 (as compared to 1 in the first use.
3093 {
3094 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3095
3096 HttpRequestInfo request;
3097 request.method = "GET";
3098 // Note that Transaction 1 was at /x/y/z, so this is in the same
3099 // protection space as digest.
3100 request.url = GURL("http://www.google.com/x/y/a/b");
3101 request.load_flags = 0;
3102
3103 MockWrite data_writes1[] = {
3104 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3105 "Host: www.google.com\r\n"
3106 "Connection: keep-alive\r\n"
3107 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3108 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3109 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3110 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3111 };
3112
3113 // Sever accepts the authorization.
3114 MockRead data_reads1[] = {
3115 MockRead("HTTP/1.0 200 OK\r\n"),
3116 MockRead("Content-Length: 100\r\n\r\n"),
3117 MockRead(false, OK),
3118 };
3119
3120 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3121 data_writes1, arraysize(data_writes1));
3122 session_deps.socket_factory.AddSocketDataProvider(&data1);
3123
3124 TestCompletionCallback callback1;
3125
3126 int rv = trans->Start(&request, &callback1, BoundNetLog());
3127 EXPECT_EQ(ERR_IO_PENDING, rv);
3128
3129 rv = callback1.WaitForResult();
3130 EXPECT_EQ(OK, rv);
3131
3132 const HttpResponseInfo* response = trans->GetResponseInfo();
3133 ASSERT_FALSE(response == NULL);
3134 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3135 }
3136}
3137
[email protected]89ceba9a2009-03-21 03:46:063138// Test the ResetStateForRestart() private method.
3139TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3140 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593141 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403142 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433143 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063144
3145 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063146 trans->read_buf_ = new IOBuffer(15);
3147 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573148 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063149
3150 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143151 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573152 response->auth_challenge = new AuthChallengeInfo();
3153 response->ssl_info.cert_status = -15;
3154 response->response_time = base::Time::Now();
3155 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063156
3157 { // Setup state for response_.vary_data
3158 HttpRequestInfo request;
3159 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3160 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573161 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433162 request.extra_headers.SetHeader("Foo", "1");
3163 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573164 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063165 }
3166
3167 // Cause the above state to be reset.
3168 trans->ResetStateForRestart();
3169
3170 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073171 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063172 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573173 EXPECT_EQ(0U, trans->request_headers_.size());
3174 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3175 EXPECT_TRUE(response->headers.get() == NULL);
3176 EXPECT_EQ(false, response->was_cached);
3177 EXPECT_EQ(0, response->ssl_info.cert_status);
3178 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063179}
3180
[email protected]bacff652009-03-31 17:50:333181// Test HTTPS connections to a site with a bad certificate
3182TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593183 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403184 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433185 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333186
3187 HttpRequestInfo request;
3188 request.method = "GET";
3189 request.url = GURL("https://www.google.com/");
3190 request.load_flags = 0;
3191
3192 MockWrite data_writes[] = {
3193 MockWrite("GET / HTTP/1.1\r\n"
3194 "Host: www.google.com\r\n"
3195 "Connection: keep-alive\r\n\r\n"),
3196 };
3197
3198 MockRead data_reads[] = {
3199 MockRead("HTTP/1.0 200 OK\r\n"),
3200 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3201 MockRead("Content-Length: 100\r\n\r\n"),
3202 MockRead(false, OK),
3203 };
3204
[email protected]5ecc992a42009-11-11 01:41:593205 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393206 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3207 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593208 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3209 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333210
[email protected]5ecc992a42009-11-11 01:41:593211 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3212 session_deps.socket_factory.AddSocketDataProvider(&data);
3213 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3214 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333215
3216 TestCompletionCallback callback;
3217
[email protected]5a1d7ca2010-04-28 20:12:273218 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333219 EXPECT_EQ(ERR_IO_PENDING, rv);
3220
3221 rv = callback.WaitForResult();
3222 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3223
3224 rv = trans->RestartIgnoringLastError(&callback);
3225 EXPECT_EQ(ERR_IO_PENDING, rv);
3226
3227 rv = callback.WaitForResult();
3228 EXPECT_EQ(OK, rv);
3229
3230 const HttpResponseInfo* response = trans->GetResponseInfo();
3231
3232 EXPECT_FALSE(response == NULL);
3233 EXPECT_EQ(100, response->headers->GetContentLength());
3234}
3235
3236// Test HTTPS connections to a site with a bad certificate, going through a
3237// proxy
3238TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593239 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333240
3241 HttpRequestInfo request;
3242 request.method = "GET";
3243 request.url = GURL("https://www.google.com/");
3244 request.load_flags = 0;
3245
3246 MockWrite proxy_writes[] = {
3247 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453248 "Host: www.google.com\r\n"
3249 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333250 };
3251
3252 MockRead proxy_reads[] = {
3253 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423254 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333255 };
3256
3257 MockWrite data_writes[] = {
3258 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453259 "Host: www.google.com\r\n"
3260 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333261 MockWrite("GET / HTTP/1.1\r\n"
3262 "Host: www.google.com\r\n"
3263 "Connection: keep-alive\r\n\r\n"),
3264 };
3265
3266 MockRead data_reads[] = {
3267 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3268 MockRead("HTTP/1.0 200 OK\r\n"),
3269 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3270 MockRead("Content-Length: 100\r\n\r\n"),
3271 MockRead(false, OK),
3272 };
3273
[email protected]31a2bfe2010-02-09 08:03:393274 StaticSocketDataProvider ssl_bad_certificate(
3275 proxy_reads, arraysize(proxy_reads),
3276 proxy_writes, arraysize(proxy_writes));
3277 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3278 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593279 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3280 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333281
[email protected]5ecc992a42009-11-11 01:41:593282 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3283 session_deps.socket_factory.AddSocketDataProvider(&data);
3284 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3285 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333286
3287 TestCompletionCallback callback;
3288
3289 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593290 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333291
[email protected]d207a5f2009-06-04 05:28:403292 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433293 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333294
[email protected]5a1d7ca2010-04-28 20:12:273295 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333296 EXPECT_EQ(ERR_IO_PENDING, rv);
3297
3298 rv = callback.WaitForResult();
3299 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3300
3301 rv = trans->RestartIgnoringLastError(&callback);
3302 EXPECT_EQ(ERR_IO_PENDING, rv);
3303
3304 rv = callback.WaitForResult();
3305 EXPECT_EQ(OK, rv);
3306
3307 const HttpResponseInfo* response = trans->GetResponseInfo();
3308
3309 EXPECT_FALSE(response == NULL);
3310 EXPECT_EQ(100, response->headers->GetContentLength());
3311 }
3312}
3313
[email protected]1c773ea12009-04-28 19:58:423314TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593315 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403316 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433317 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423318
3319 HttpRequestInfo request;
3320 request.method = "GET";
3321 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433322 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3323 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423324
3325 MockWrite data_writes[] = {
3326 MockWrite("GET / HTTP/1.1\r\n"
3327 "Host: www.google.com\r\n"
3328 "Connection: keep-alive\r\n"
3329 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3330 };
3331
3332 // Lastly, the server responds with the actual content.
3333 MockRead data_reads[] = {
3334 MockRead("HTTP/1.0 200 OK\r\n"),
3335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3336 MockRead("Content-Length: 100\r\n\r\n"),
3337 MockRead(false, OK),
3338 };
3339
[email protected]31a2bfe2010-02-09 08:03:393340 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3341 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593342 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423343
3344 TestCompletionCallback callback;
3345
[email protected]5a1d7ca2010-04-28 20:12:273346 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423347 EXPECT_EQ(ERR_IO_PENDING, rv);
3348
3349 rv = callback.WaitForResult();
3350 EXPECT_EQ(OK, rv);
3351}
3352
3353TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593354 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403355 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433356 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423357
3358 HttpRequestInfo request;
3359 request.method = "GET";
3360 request.url = GURL("http://www.google.com/");
3361 request.load_flags = 0;
3362 request.referrer = GURL("http://the.previous.site.com/");
3363
3364 MockWrite data_writes[] = {
3365 MockWrite("GET / HTTP/1.1\r\n"
3366 "Host: www.google.com\r\n"
3367 "Connection: keep-alive\r\n"
3368 "Referer: http://the.previous.site.com/\r\n\r\n"),
3369 };
3370
3371 // Lastly, the server responds with the actual content.
3372 MockRead data_reads[] = {
3373 MockRead("HTTP/1.0 200 OK\r\n"),
3374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3375 MockRead("Content-Length: 100\r\n\r\n"),
3376 MockRead(false, OK),
3377 };
3378
[email protected]31a2bfe2010-02-09 08:03:393379 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3380 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593381 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423382
3383 TestCompletionCallback callback;
3384
[email protected]5a1d7ca2010-04-28 20:12:273385 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423386 EXPECT_EQ(ERR_IO_PENDING, rv);
3387
3388 rv = callback.WaitForResult();
3389 EXPECT_EQ(OK, rv);
3390}
3391
3392TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593393 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403394 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433395 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423396
3397 HttpRequestInfo request;
3398 request.method = "POST";
3399 request.url = GURL("http://www.google.com/");
3400
3401 MockWrite data_writes[] = {
3402 MockWrite("POST / HTTP/1.1\r\n"
3403 "Host: www.google.com\r\n"
3404 "Connection: keep-alive\r\n"
3405 "Content-Length: 0\r\n\r\n"),
3406 };
3407
3408 // Lastly, the server responds with the actual content.
3409 MockRead data_reads[] = {
3410 MockRead("HTTP/1.0 200 OK\r\n"),
3411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3412 MockRead("Content-Length: 100\r\n\r\n"),
3413 MockRead(false, OK),
3414 };
3415
[email protected]31a2bfe2010-02-09 08:03:393416 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3417 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593418 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423419
3420 TestCompletionCallback callback;
3421
[email protected]5a1d7ca2010-04-28 20:12:273422 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423423 EXPECT_EQ(ERR_IO_PENDING, rv);
3424
3425 rv = callback.WaitForResult();
3426 EXPECT_EQ(OK, rv);
3427}
3428
3429TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593430 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403431 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433432 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423433
3434 HttpRequestInfo request;
3435 request.method = "PUT";
3436 request.url = GURL("http://www.google.com/");
3437
3438 MockWrite data_writes[] = {
3439 MockWrite("PUT / HTTP/1.1\r\n"
3440 "Host: www.google.com\r\n"
3441 "Connection: keep-alive\r\n"
3442 "Content-Length: 0\r\n\r\n"),
3443 };
3444
3445 // Lastly, the server responds with the actual content.
3446 MockRead data_reads[] = {
3447 MockRead("HTTP/1.0 200 OK\r\n"),
3448 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3449 MockRead("Content-Length: 100\r\n\r\n"),
3450 MockRead(false, OK),
3451 };
3452
[email protected]31a2bfe2010-02-09 08:03:393453 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3454 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593455 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423456
3457 TestCompletionCallback callback;
3458
[email protected]5a1d7ca2010-04-28 20:12:273459 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423460 EXPECT_EQ(ERR_IO_PENDING, rv);
3461
3462 rv = callback.WaitForResult();
3463 EXPECT_EQ(OK, rv);
3464}
3465
3466TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593467 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403468 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433469 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423470
3471 HttpRequestInfo request;
3472 request.method = "HEAD";
3473 request.url = GURL("http://www.google.com/");
3474
3475 MockWrite data_writes[] = {
3476 MockWrite("HEAD / HTTP/1.1\r\n"
3477 "Host: www.google.com\r\n"
3478 "Connection: keep-alive\r\n"
3479 "Content-Length: 0\r\n\r\n"),
3480 };
3481
3482 // Lastly, the server responds with the actual content.
3483 MockRead data_reads[] = {
3484 MockRead("HTTP/1.0 200 OK\r\n"),
3485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3486 MockRead("Content-Length: 100\r\n\r\n"),
3487 MockRead(false, OK),
3488 };
3489
[email protected]31a2bfe2010-02-09 08:03:393490 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3491 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593492 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423493
3494 TestCompletionCallback callback;
3495
[email protected]5a1d7ca2010-04-28 20:12:273496 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423497 EXPECT_EQ(ERR_IO_PENDING, rv);
3498
3499 rv = callback.WaitForResult();
3500 EXPECT_EQ(OK, rv);
3501}
3502
3503TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593504 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403505 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433506 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423507
3508 HttpRequestInfo request;
3509 request.method = "GET";
3510 request.url = GURL("http://www.google.com/");
3511 request.load_flags = LOAD_BYPASS_CACHE;
3512
3513 MockWrite data_writes[] = {
3514 MockWrite("GET / HTTP/1.1\r\n"
3515 "Host: www.google.com\r\n"
3516 "Connection: keep-alive\r\n"
3517 "Pragma: no-cache\r\n"
3518 "Cache-Control: no-cache\r\n\r\n"),
3519 };
3520
3521 // Lastly, the server responds with the actual content.
3522 MockRead data_reads[] = {
3523 MockRead("HTTP/1.0 200 OK\r\n"),
3524 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3525 MockRead("Content-Length: 100\r\n\r\n"),
3526 MockRead(false, OK),
3527 };
3528
[email protected]31a2bfe2010-02-09 08:03:393529 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3530 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593531 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423532
3533 TestCompletionCallback callback;
3534
[email protected]5a1d7ca2010-04-28 20:12:273535 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423536 EXPECT_EQ(ERR_IO_PENDING, rv);
3537
3538 rv = callback.WaitForResult();
3539 EXPECT_EQ(OK, rv);
3540}
3541
3542TEST_F(HttpNetworkTransactionTest,
3543 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593544 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403545 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433546 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423547
3548 HttpRequestInfo request;
3549 request.method = "GET";
3550 request.url = GURL("http://www.google.com/");
3551 request.load_flags = LOAD_VALIDATE_CACHE;
3552
3553 MockWrite data_writes[] = {
3554 MockWrite("GET / HTTP/1.1\r\n"
3555 "Host: www.google.com\r\n"
3556 "Connection: keep-alive\r\n"
3557 "Cache-Control: max-age=0\r\n\r\n"),
3558 };
3559
3560 // Lastly, the server responds with the actual content.
3561 MockRead data_reads[] = {
3562 MockRead("HTTP/1.0 200 OK\r\n"),
3563 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3564 MockRead("Content-Length: 100\r\n\r\n"),
3565 MockRead(false, OK),
3566 };
3567
[email protected]31a2bfe2010-02-09 08:03:393568 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3569 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593570 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423571
3572 TestCompletionCallback callback;
3573
[email protected]5a1d7ca2010-04-28 20:12:273574 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423575 EXPECT_EQ(ERR_IO_PENDING, rv);
3576
3577 rv = callback.WaitForResult();
3578 EXPECT_EQ(OK, rv);
3579}
3580
3581TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593582 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403583 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433584 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423585
3586 HttpRequestInfo request;
3587 request.method = "GET";
3588 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433589 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423590
3591 MockWrite data_writes[] = {
3592 MockWrite("GET / HTTP/1.1\r\n"
3593 "Host: www.google.com\r\n"
3594 "Connection: keep-alive\r\n"
3595 "FooHeader: Bar\r\n\r\n"),
3596 };
3597
3598 // Lastly, the server responds with the actual content.
3599 MockRead data_reads[] = {
3600 MockRead("HTTP/1.0 200 OK\r\n"),
3601 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3602 MockRead("Content-Length: 100\r\n\r\n"),
3603 MockRead(false, OK),
3604 };
3605
[email protected]31a2bfe2010-02-09 08:03:393606 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3607 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593608 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423609
3610 TestCompletionCallback callback;
3611
[email protected]5a1d7ca2010-04-28 20:12:273612 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423613 EXPECT_EQ(ERR_IO_PENDING, rv);
3614
3615 rv = callback.WaitForResult();
3616 EXPECT_EQ(OK, rv);
3617}
3618
[email protected]270c6412010-03-29 22:02:473619TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3620 SessionDependencies session_deps;
3621 scoped_ptr<HttpTransaction> trans(
3622 new HttpNetworkTransaction(CreateSession(&session_deps)));
3623
3624 HttpRequestInfo request;
3625 request.method = "GET";
3626 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433627 request.extra_headers.SetHeader("referer", "www.foo.com");
3628 request.extra_headers.SetHeader("hEllo", "Kitty");
3629 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473630
3631 MockWrite data_writes[] = {
3632 MockWrite("GET / HTTP/1.1\r\n"
3633 "Host: www.google.com\r\n"
3634 "Connection: keep-alive\r\n"
3635 "hEllo: Kitty\r\n"
3636 "FoO: bar\r\n\r\n"),
3637 };
3638
3639 // Lastly, the server responds with the actual content.
3640 MockRead data_reads[] = {
3641 MockRead("HTTP/1.0 200 OK\r\n"),
3642 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3643 MockRead("Content-Length: 100\r\n\r\n"),
3644 MockRead(false, OK),
3645 };
3646
3647 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3648 data_writes, arraysize(data_writes));
3649 session_deps.socket_factory.AddSocketDataProvider(&data);
3650
3651 TestCompletionCallback callback;
3652
[email protected]5a1d7ca2010-04-28 20:12:273653 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473654 EXPECT_EQ(ERR_IO_PENDING, rv);
3655
3656 rv = callback.WaitForResult();
3657 EXPECT_EQ(OK, rv);
3658}
3659
[email protected]3cd17242009-06-23 02:59:023660TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093661 SessionDependencies session_deps(
3662 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023663
3664 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433665 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023666
3667 HttpRequestInfo request;
3668 request.method = "GET";
3669 request.url = GURL("http://www.google.com/");
3670 request.load_flags = 0;
3671
3672 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3673 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3674
3675 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353676 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023677 MockWrite("GET / HTTP/1.1\r\n"
3678 "Host: www.google.com\r\n"
3679 "Connection: keep-alive\r\n\r\n")
3680 };
3681
3682 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593683 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023684 MockRead("HTTP/1.0 200 OK\r\n"),
3685 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3686 MockRead("Payload"),
3687 MockRead(false, OK)
3688 };
3689
[email protected]31a2bfe2010-02-09 08:03:393690 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3691 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593692 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023693
3694 TestCompletionCallback callback;
3695
[email protected]5a1d7ca2010-04-28 20:12:273696 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023697 EXPECT_EQ(ERR_IO_PENDING, rv);
3698
3699 rv = callback.WaitForResult();
3700 EXPECT_EQ(OK, rv);
3701
3702 const HttpResponseInfo* response = trans->GetResponseInfo();
3703 EXPECT_FALSE(response == NULL);
3704
3705 std::string response_text;
3706 rv = ReadTransaction(trans.get(), &response_text);
3707 EXPECT_EQ(OK, rv);
3708 EXPECT_EQ("Payload", response_text);
3709}
3710
3711TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093712 SessionDependencies session_deps(
3713 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023714
3715 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433716 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023717
3718 HttpRequestInfo request;
3719 request.method = "GET";
3720 request.url = GURL("https://www.google.com/");
3721 request.load_flags = 0;
3722
3723 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3724 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3725
3726 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353727 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3728 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023729 MockWrite("GET / HTTP/1.1\r\n"
3730 "Host: www.google.com\r\n"
3731 "Connection: keep-alive\r\n\r\n")
3732 };
3733
3734 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353735 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3736 arraysize(read_buffer)),
3737 MockRead("HTTP/1.0 200 OK\r\n"),
3738 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3739 MockRead("Payload"),
3740 MockRead(false, OK)
3741 };
3742
[email protected]31a2bfe2010-02-09 08:03:393743 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3744 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593745 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353746
[email protected]5ecc992a42009-11-11 01:41:593747 SSLSocketDataProvider ssl(true, OK);
3748 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353749
3750 TestCompletionCallback callback;
3751
[email protected]5a1d7ca2010-04-28 20:12:273752 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353753 EXPECT_EQ(ERR_IO_PENDING, rv);
3754
3755 rv = callback.WaitForResult();
3756 EXPECT_EQ(OK, rv);
3757
3758 const HttpResponseInfo* response = trans->GetResponseInfo();
3759 EXPECT_FALSE(response == NULL);
3760
3761 std::string response_text;
3762 rv = ReadTransaction(trans.get(), &response_text);
3763 EXPECT_EQ(OK, rv);
3764 EXPECT_EQ("Payload", response_text);
3765}
3766
3767TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093768 SessionDependencies session_deps(
3769 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353770
3771 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433772 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353773
3774 HttpRequestInfo request;
3775 request.method = "GET";
3776 request.url = GURL("http://www.google.com/");
3777 request.load_flags = 0;
3778
3779 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3780 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373781 const char kSOCKS5OkRequest[] = {
3782 0x05, // Version
3783 0x01, // Command (CONNECT)
3784 0x00, // Reserved.
3785 0x03, // Address type (DOMAINNAME).
3786 0x0E, // Length of domain (14)
3787 // Domain string:
3788 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3789 0x00, 0x50, // 16-bit port (80)
3790 };
[email protected]e0c27be2009-07-15 13:09:353791 const char kSOCKS5OkResponse[] =
3792 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3793
3794 MockWrite data_writes[] = {
3795 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3796 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3797 MockWrite("GET / HTTP/1.1\r\n"
3798 "Host: www.google.com\r\n"
3799 "Connection: keep-alive\r\n\r\n")
3800 };
3801
3802 MockRead data_reads[] = {
3803 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3804 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3805 MockRead("HTTP/1.0 200 OK\r\n"),
3806 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3807 MockRead("Payload"),
3808 MockRead(false, OK)
3809 };
3810
[email protected]31a2bfe2010-02-09 08:03:393811 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3812 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593813 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353814
3815 TestCompletionCallback callback;
3816
[email protected]5a1d7ca2010-04-28 20:12:273817 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353818 EXPECT_EQ(ERR_IO_PENDING, rv);
3819
3820 rv = callback.WaitForResult();
3821 EXPECT_EQ(OK, rv);
3822
3823 const HttpResponseInfo* response = trans->GetResponseInfo();
3824 EXPECT_FALSE(response == NULL);
3825
3826 std::string response_text;
3827 rv = ReadTransaction(trans.get(), &response_text);
3828 EXPECT_EQ(OK, rv);
3829 EXPECT_EQ("Payload", response_text);
3830}
3831
3832TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093833 SessionDependencies session_deps(
3834 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353835
3836 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433837 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353838
3839 HttpRequestInfo request;
3840 request.method = "GET";
3841 request.url = GURL("https://www.google.com/");
3842 request.load_flags = 0;
3843
3844 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3845 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373846 const unsigned char kSOCKS5OkRequest[] = {
3847 0x05, // Version
3848 0x01, // Command (CONNECT)
3849 0x00, // Reserved.
3850 0x03, // Address type (DOMAINNAME).
3851 0x0E, // Length of domain (14)
3852 // Domain string:
3853 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3854 0x01, 0xBB, // 16-bit port (443)
3855 };
3856
[email protected]e0c27be2009-07-15 13:09:353857 const char kSOCKS5OkResponse[] =
3858 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3859
3860 MockWrite data_writes[] = {
3861 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3862 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3863 arraysize(kSOCKS5OkRequest)),
3864 MockWrite("GET / HTTP/1.1\r\n"
3865 "Host: www.google.com\r\n"
3866 "Connection: keep-alive\r\n\r\n")
3867 };
3868
3869 MockRead data_reads[] = {
3870 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3871 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023872 MockRead("HTTP/1.0 200 OK\r\n"),
3873 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3874 MockRead("Payload"),
3875 MockRead(false, OK)
3876 };
3877
[email protected]31a2bfe2010-02-09 08:03:393878 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3879 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593880 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023881
[email protected]5ecc992a42009-11-11 01:41:593882 SSLSocketDataProvider ssl(true, OK);
3883 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023884
3885 TestCompletionCallback callback;
3886
[email protected]5a1d7ca2010-04-28 20:12:273887 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023888 EXPECT_EQ(ERR_IO_PENDING, rv);
3889
3890 rv = callback.WaitForResult();
3891 EXPECT_EQ(OK, rv);
3892
3893 const HttpResponseInfo* response = trans->GetResponseInfo();
3894 EXPECT_FALSE(response == NULL);
3895
3896 std::string response_text;
3897 rv = ReadTransaction(trans.get(), &response_text);
3898 EXPECT_EQ(OK, rv);
3899 EXPECT_EQ("Payload", response_text);
3900}
3901
[email protected]04e5be32009-06-26 20:00:313902// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063903
3904struct GroupNameTest {
3905 std::string proxy_server;
3906 std::string url;
3907 std::string expected_group_name;
3908};
3909
3910scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3911 const std::string& proxy_server) {
3912 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3913 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3914
3915 HttpAlternateProtocols* alternate_protocols =
3916 session->mutable_alternate_protocols();
3917 alternate_protocols->SetAlternateProtocolFor(
3918 HostPortPair("host.with.alternate", 80), 443,
3919 HttpAlternateProtocols::NPN_SPDY_1);
3920
3921 return session;
3922}
3923
3924int GroupNameTransactionHelper(
3925 const std::string& url,
3926 const scoped_refptr<HttpNetworkSession>& session) {
3927 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3928
3929 HttpRequestInfo request;
3930 request.method = "GET";
3931 request.url = GURL(url);
3932 request.load_flags = 0;
3933
3934 TestCompletionCallback callback;
3935
3936 // We do not complete this request, the dtor will clean the transaction up.
3937 return trans->Start(&request, &callback, BoundNetLog());
3938}
3939
3940TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
3941 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:313942 {
[email protected]2d731a32010-04-29 01:04:063943 "", // unused
[email protected]04e5be32009-06-26 20:00:313944 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:543945 "www.google.com:80",
3946 },
3947 {
[email protected]2d731a32010-04-29 01:04:063948 "", // unused
[email protected]2ff8b312010-04-26 22:20:543949 "http://[2001:1418:13:1::25]/direct",
3950 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:313951 },
[email protected]04e5be32009-06-26 20:00:313952
3953 // SSL Tests
3954 {
[email protected]2d731a32010-04-29 01:04:063955 "", // unused
[email protected]04e5be32009-06-26 20:00:313956 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:023957 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313958 },
3959 {
[email protected]2d731a32010-04-29 01:04:063960 "", // unused
3961 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:023962 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:313963 },
3964 {
[email protected]2d731a32010-04-29 01:04:063965 "", // unused
[email protected]2ff8b312010-04-26 22:20:543966 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:023967 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:543968 },
[email protected]2d731a32010-04-29 01:04:063969 };
[email protected]2ff8b312010-04-26 22:20:543970
[email protected]2d731a32010-04-29 01:04:063971 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3972
3973 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3974 scoped_refptr<HttpNetworkSession> session(
3975 SetupSessionForGroupNameTests(tests[i].proxy_server));
3976
3977 HttpNetworkSessionPeer peer(session);
3978 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3979 new CaptureGroupNameTCPSocketPool(session.get()));
3980 peer.SetTCPSocketPool(tcp_conn_pool);
3981
3982 EXPECT_EQ(ERR_IO_PENDING,
3983 GroupNameTransactionHelper(tests[i].url, session));
3984 EXPECT_EQ(tests[i].expected_group_name,
3985 tcp_conn_pool->last_group_name_received());
3986 }
3987
3988 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3989}
3990
3991TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
3992 const GroupNameTest tests[] = {
3993 {
3994 "http_proxy",
3995 "http://www.google.com/http_proxy_normal",
3996 "www.google.com:80",
3997 },
3998
3999 // SSL Tests
4000 {
4001 "http_proxy",
4002 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024003 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064004 },
4005
[email protected]9faeded92010-04-29 20:03:054006 {
4007 "http_proxy",
4008 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024009 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054010 },
[email protected]2d731a32010-04-29 01:04:064011 };
4012
4013 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4014
4015 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4016 scoped_refptr<HttpNetworkSession> session(
4017 SetupSessionForGroupNameTests(tests[i].proxy_server));
4018
4019 HttpNetworkSessionPeer peer(session);
4020
4021 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
4022 new CaptureGroupNameTCPSocketPool(session.get()));
4023 peer.SetSocketPoolForHTTPProxy(
4024 HostPortPair("http_proxy", 80), http_proxy_pool);
4025
4026 EXPECT_EQ(ERR_IO_PENDING,
4027 GroupNameTransactionHelper(tests[i].url, session));
4028 EXPECT_EQ(tests[i].expected_group_name,
4029 http_proxy_pool->last_group_name_received());
4030 }
4031
4032 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4033}
4034
4035TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4036 const GroupNameTest tests[] = {
4037 {
4038 "socks4://socks_proxy:1080",
4039 "http://www.google.com/socks4_direct",
4040 "socks4/www.google.com:80",
4041 },
4042 {
4043 "socks5://socks_proxy:1080",
4044 "http://www.google.com/socks5_direct",
4045 "socks5/www.google.com:80",
4046 },
4047
4048 // SSL Tests
4049 {
4050 "socks4://socks_proxy:1080",
4051 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024052 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064053 },
4054 {
4055 "socks5://socks_proxy:1080",
4056 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024057 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064058 },
4059
[email protected]9faeded92010-04-29 20:03:054060 {
4061 "socks4://socks_proxy:1080",
4062 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024063 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054064 },
[email protected]04e5be32009-06-26 20:00:314065 };
4066
[email protected]2ff8b312010-04-26 22:20:544067 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4068
[email protected]04e5be32009-06-26 20:00:314069 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064070 scoped_refptr<HttpNetworkSession> session(
4071 SetupSessionForGroupNameTests(tests[i].proxy_server));
4072 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314073
[email protected]a796bcec2010-03-22 17:17:264074 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064075 new CaptureGroupNameSOCKSSocketPool(session.get()));
4076 peer.SetSocketPoolForSOCKSProxy(
4077 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:314078
[email protected]5695b8c2009-09-30 21:36:434079 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314080
[email protected]2d731a32010-04-29 01:04:064081 EXPECT_EQ(ERR_IO_PENDING,
4082 GroupNameTransactionHelper(tests[i].url, session));
4083 EXPECT_EQ(tests[i].expected_group_name,
4084 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314085 }
[email protected]2ff8b312010-04-26 22:20:544086
4087 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314088}
4089
[email protected]9172a982009-06-06 00:30:254090TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544091 SessionDependencies session_deps(
4092 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324093
[email protected]69719062010-01-05 20:09:214094 // This simulates failure resolving all hostnames; that means we will fail
4095 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324096 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4097
[email protected]9172a982009-06-06 00:30:254098 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434099 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254100
4101 HttpRequestInfo request;
4102 request.method = "GET";
4103 request.url = GURL("http://www.google.com/");
4104
4105 TestCompletionCallback callback;
4106
[email protected]5a1d7ca2010-04-28 20:12:274107 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254108 EXPECT_EQ(ERR_IO_PENDING, rv);
4109
[email protected]9172a982009-06-06 00:30:254110 rv = callback.WaitForResult();
4111 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4112}
4113
[email protected]f3e6c1e2009-06-15 20:52:124114// Host resolution observer used by
4115// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4116// resovle requests are issued with a referrer of |expected_referrer|.
4117class ResolutionReferrerObserver : public HostResolver::Observer {
4118 public:
4119 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4120 : expected_referrer_(expected_referrer),
4121 called_start_with_referrer_(false),
4122 called_finish_with_referrer_(false) {
4123 }
4124
4125 virtual void OnStartResolution(int id,
4126 const HostResolver::RequestInfo& info) {
4127 if (info.referrer() == expected_referrer_)
4128 called_start_with_referrer_ = true;
4129 }
4130
4131 virtual void OnFinishResolutionWithStatus(
4132 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4133 if (info.referrer() == expected_referrer_)
4134 called_finish_with_referrer_ = true;
4135 }
4136
[email protected]eb255d32009-06-17 02:11:034137 virtual void OnCancelResolution(int id,
4138 const HostResolver::RequestInfo& info ) {
4139 FAIL() << "Should not be cancelling any requests!";
4140 }
4141
[email protected]f3e6c1e2009-06-15 20:52:124142 bool did_complete_with_expected_referrer() const {
4143 return called_start_with_referrer_ && called_finish_with_referrer_;
4144 }
4145
4146 private:
4147 GURL expected_referrer_;
4148 bool called_start_with_referrer_;
4149 bool called_finish_with_referrer_;
4150
4151 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4152};
4153
4154// Make sure that when HostResolver::Resolve() is invoked, it passes through
4155// the "referrer". This is depended on by the DNS prefetch observer.
4156TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4157 GURL referrer = GURL("http://expected-referrer/");
4158 EXPECT_TRUE(referrer.is_valid());
4159 ResolutionReferrerObserver resolution_observer(referrer);
4160
4161 SessionDependencies session_deps;
4162 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434163 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124164
4165 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144166 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124167
4168 // Connect up a mock socket which will fail when reading.
4169 MockRead data_reads[] = {
4170 MockRead(false, ERR_FAILED),
4171 };
[email protected]31a2bfe2010-02-09 08:03:394172 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594173 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124174
4175 // Issue a request, containing an HTTP referrer.
4176 HttpRequestInfo request;
4177 request.method = "GET";
4178 request.referrer = referrer;
4179 request.url = GURL("http://www.google.com/");
4180
4181 // Run the request until it fails reading from the socket.
4182 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274183 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124184 EXPECT_EQ(ERR_IO_PENDING, rv);
4185 rv = callback.WaitForResult();
4186 EXPECT_EQ(ERR_FAILED, rv);
4187
4188 // Check that the host resolution observer saw |referrer|.
4189 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4190}
4191
[email protected]685af592010-05-11 19:31:244192// Base test to make sure that when the load flags for a request specify to
4193// bypass the cache, the DNS cache is not used.
4194void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284195 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324196
[email protected]a2c2fb92009-07-18 07:31:044197 // Select a host resolver that does caching.
4198 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324199
[email protected]3b9cca42009-06-16 01:08:284200 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434201 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284202
4203 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4204 // a synchronous lookup.)
4205 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144206 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464207 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274208 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284209 EXPECT_EQ(OK, rv);
4210
4211 // Verify that it was added to host cache, by doing a subsequent async lookup
4212 // and confirming it completes synchronously.
4213 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464214 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284215 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274216 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324217 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284218
4219 // Inject a failure the next time that "www.google.com" is resolved. This way
4220 // we can tell if the next lookup hit the cache, or the "network".
4221 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324222 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284223
4224 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4225 // first read -- this won't be reached as the host resolution will fail first.
4226 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394227 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594228 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284229
4230 // Issue a request, asking to bypass the cache(s).
4231 HttpRequestInfo request;
4232 request.method = "GET";
[email protected]685af592010-05-11 19:31:244233 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284234 request.url = GURL("http://www.google.com/");
4235
4236 // Run the request.
4237 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274238 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284239 ASSERT_EQ(ERR_IO_PENDING, rv);
4240 rv = callback.WaitForResult();
4241
4242 // If we bypassed the cache, we would have gotten a failure while resolving
4243 // "www.google.com".
4244 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4245}
4246
[email protected]685af592010-05-11 19:31:244247// There are multiple load flags that should trigger the host cache bypass.
4248// Test each in isolation:
4249TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4250 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4251}
4252
4253TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4254 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4255}
4256
4257TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4258 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4259}
4260
[email protected]0877e3d2009-10-17 22:29:574261// Make sure we can handle an error when writing the request.
4262TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4263 SessionDependencies session_deps;
4264 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4265
4266 HttpRequestInfo request;
4267 request.method = "GET";
4268 request.url = GURL("http://www.foo.com/");
4269 request.load_flags = 0;
4270
4271 MockWrite write_failure[] = {
4272 MockWrite(true, ERR_CONNECTION_RESET),
4273 };
[email protected]31a2bfe2010-02-09 08:03:394274 StaticSocketDataProvider data(NULL, 0,
4275 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594276 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574277
4278 TestCompletionCallback callback;
4279
4280 scoped_ptr<HttpTransaction> trans(
4281 new HttpNetworkTransaction(CreateSession(&session_deps)));
4282
[email protected]5a1d7ca2010-04-28 20:12:274283 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574284 EXPECT_EQ(ERR_IO_PENDING, rv);
4285
4286 rv = callback.WaitForResult();
4287 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4288}
4289
4290// Check that a connection closed after the start of the headers finishes ok.
4291TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4292 SessionDependencies session_deps;
4293 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4294
4295 HttpRequestInfo request;
4296 request.method = "GET";
4297 request.url = GURL("http://www.foo.com/");
4298 request.load_flags = 0;
4299
4300 MockRead data_reads[] = {
4301 MockRead("HTTP/1."),
4302 MockRead(false, OK),
4303 };
4304
[email protected]31a2bfe2010-02-09 08:03:394305 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594306 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574307
4308 TestCompletionCallback callback;
4309
4310 scoped_ptr<HttpTransaction> trans(
4311 new HttpNetworkTransaction(CreateSession(&session_deps)));
4312
[email protected]5a1d7ca2010-04-28 20:12:274313 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574314 EXPECT_EQ(ERR_IO_PENDING, rv);
4315
4316 rv = callback.WaitForResult();
4317 EXPECT_EQ(OK, rv);
4318
4319 const HttpResponseInfo* response = trans->GetResponseInfo();
4320 EXPECT_TRUE(response != NULL);
4321
4322 EXPECT_TRUE(response->headers != NULL);
4323 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4324
4325 std::string response_data;
4326 rv = ReadTransaction(trans.get(), &response_data);
4327 EXPECT_EQ(OK, rv);
4328 EXPECT_EQ("", response_data);
4329}
4330
4331// Make sure that a dropped connection while draining the body for auth
4332// restart does the right thing.
4333TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4334 SessionDependencies session_deps;
4335 scoped_ptr<HttpTransaction> trans(
4336 new HttpNetworkTransaction(CreateSession(&session_deps)));
4337
4338 HttpRequestInfo request;
4339 request.method = "GET";
4340 request.url = GURL("http://www.google.com/");
4341 request.load_flags = 0;
4342
4343 MockWrite data_writes1[] = {
4344 MockWrite("GET / HTTP/1.1\r\n"
4345 "Host: www.google.com\r\n"
4346 "Connection: keep-alive\r\n\r\n"),
4347 };
4348
4349 MockRead data_reads1[] = {
4350 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4351 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4352 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4353 MockRead("Content-Length: 14\r\n\r\n"),
4354 MockRead("Unauth"),
4355 MockRead(true, ERR_CONNECTION_RESET),
4356 };
4357
[email protected]31a2bfe2010-02-09 08:03:394358 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4359 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594360 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574361
4362 // After calling trans->RestartWithAuth(), this is the request we should
4363 // be issuing -- the final header line contains the credentials.
4364 MockWrite data_writes2[] = {
4365 MockWrite("GET / HTTP/1.1\r\n"
4366 "Host: www.google.com\r\n"
4367 "Connection: keep-alive\r\n"
4368 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4369 };
4370
4371 // Lastly, the server responds with the actual content.
4372 MockRead data_reads2[] = {
4373 MockRead("HTTP/1.1 200 OK\r\n"),
4374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4375 MockRead("Content-Length: 100\r\n\r\n"),
4376 MockRead(false, OK),
4377 };
4378
[email protected]31a2bfe2010-02-09 08:03:394379 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4380 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594381 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574382
4383 TestCompletionCallback callback1;
4384
[email protected]5a1d7ca2010-04-28 20:12:274385 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574386 EXPECT_EQ(ERR_IO_PENDING, rv);
4387
4388 rv = callback1.WaitForResult();
4389 EXPECT_EQ(OK, rv);
4390
4391 const HttpResponseInfo* response = trans->GetResponseInfo();
4392 EXPECT_FALSE(response == NULL);
4393
4394 // The password prompt info should have been set in response->auth_challenge.
4395 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4396
4397 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4398 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4399 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4400
4401 TestCompletionCallback callback2;
4402
4403 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4404 EXPECT_EQ(ERR_IO_PENDING, rv);
4405
4406 rv = callback2.WaitForResult();
4407 EXPECT_EQ(OK, rv);
4408
4409 response = trans->GetResponseInfo();
4410 EXPECT_FALSE(response == NULL);
4411 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4412 EXPECT_EQ(100, response->headers->GetContentLength());
4413}
4414
4415// Test HTTPS connections going through a proxy that sends extra data.
4416TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4417 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4418
4419 HttpRequestInfo request;
4420 request.method = "GET";
4421 request.url = GURL("https://www.google.com/");
4422 request.load_flags = 0;
4423
4424 MockRead proxy_reads[] = {
4425 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4426 MockRead(false, OK)
4427 };
4428
[email protected]31a2bfe2010-02-09 08:03:394429 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594430 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574431
[email protected]5ecc992a42009-11-11 01:41:594432 session_deps.socket_factory.AddSocketDataProvider(&data);
4433 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574434
4435 TestCompletionCallback callback;
4436
4437 session_deps.socket_factory.ResetNextMockIndexes();
4438
4439 scoped_ptr<HttpTransaction> trans(
4440 new HttpNetworkTransaction(CreateSession(&session_deps)));
4441
[email protected]5a1d7ca2010-04-28 20:12:274442 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574443 EXPECT_EQ(ERR_IO_PENDING, rv);
4444
4445 rv = callback.WaitForResult();
4446 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4447}
4448
[email protected]e22e1362009-11-23 21:31:124449TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464450 SessionDependencies session_deps;
4451 scoped_ptr<HttpTransaction> trans(
4452 new HttpNetworkTransaction(CreateSession(&session_deps)));
4453
4454 HttpRequestInfo request;
4455 request.method = "GET";
4456 request.url = GURL("http://www.google.com/");
4457 request.load_flags = 0;
4458
[email protected]e22e1362009-11-23 21:31:124459 MockRead data_reads[] = {
4460 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4461 MockRead(false, OK),
4462 };
[email protected]9492e4a2010-02-24 00:58:464463
4464 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4465 session_deps.socket_factory.AddSocketDataProvider(&data);
4466
4467 TestCompletionCallback callback;
4468
[email protected]5a1d7ca2010-04-28 20:12:274469 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464470 EXPECT_EQ(ERR_IO_PENDING, rv);
4471
4472 EXPECT_EQ(OK, callback.WaitForResult());
4473
4474 const HttpResponseInfo* response = trans->GetResponseInfo();
4475 EXPECT_TRUE(response != NULL);
4476
4477 EXPECT_TRUE(response->headers != NULL);
4478 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4479
4480 std::string response_data;
4481 rv = ReadTransaction(trans.get(), &response_data);
4482 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124483}
4484
[email protected]95d88ffe2010-02-04 21:25:334485TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4486 SessionDependencies session_deps;
4487 scoped_ptr<HttpTransaction> trans(
4488 new HttpNetworkTransaction(CreateSession(&session_deps)));
4489
4490 HttpRequestInfo request;
4491 request.method = "POST";
4492 request.url = GURL("http://www.google.com/upload");
4493 request.upload_data = new UploadData;
4494 request.load_flags = 0;
4495
4496 FilePath temp_file_path;
4497 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4498 const uint64 kFakeSize = 100000; // file is actually blank
4499
4500 std::vector<UploadData::Element> elements;
4501 UploadData::Element element;
4502 element.SetToFilePath(temp_file_path);
4503 element.SetContentLength(kFakeSize);
4504 elements.push_back(element);
4505 request.upload_data->set_elements(elements);
4506 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4507
4508 MockRead data_reads[] = {
4509 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4510 MockRead("hello world"),
4511 MockRead(false, OK),
4512 };
[email protected]31a2bfe2010-02-09 08:03:394513 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334514 session_deps.socket_factory.AddSocketDataProvider(&data);
4515
4516 TestCompletionCallback callback;
4517
[email protected]5a1d7ca2010-04-28 20:12:274518 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334519 EXPECT_EQ(ERR_IO_PENDING, rv);
4520
4521 rv = callback.WaitForResult();
4522 EXPECT_EQ(OK, rv);
4523
4524 const HttpResponseInfo* response = trans->GetResponseInfo();
4525 EXPECT_TRUE(response != NULL);
4526
4527 EXPECT_TRUE(response->headers != NULL);
4528 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4529
4530 std::string response_data;
4531 rv = ReadTransaction(trans.get(), &response_data);
4532 EXPECT_EQ(OK, rv);
4533 EXPECT_EQ("hello world", response_data);
4534
4535 file_util::Delete(temp_file_path, false);
4536}
4537
[email protected]6624b4622010-03-29 19:58:364538TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4539 // If we try to upload an unreadable file, the network stack should report
4540 // the file size as zero and upload zero bytes for that file.
4541 SessionDependencies session_deps;
4542 scoped_ptr<HttpTransaction> trans(
4543 new HttpNetworkTransaction(CreateSession(&session_deps)));
4544
4545 FilePath temp_file;
4546 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4547 std::string temp_file_content("Unreadable file.");
4548 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4549 temp_file_content.length()));
4550 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4551
4552 HttpRequestInfo request;
4553 request.method = "POST";
4554 request.url = GURL("http://www.google.com/upload");
4555 request.upload_data = new UploadData;
4556 request.load_flags = 0;
4557
4558 std::vector<UploadData::Element> elements;
4559 UploadData::Element element;
4560 element.SetToFilePath(temp_file);
4561 elements.push_back(element);
4562 request.upload_data->set_elements(elements);
4563
4564 MockRead data_reads[] = {
4565 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4566 MockRead(false, OK),
4567 };
4568 MockWrite data_writes[] = {
4569 MockWrite("POST /upload HTTP/1.1\r\n"
4570 "Host: www.google.com\r\n"
4571 "Connection: keep-alive\r\n"
4572 "Content-Length: 0\r\n\r\n"),
4573 MockWrite(false, OK),
4574 };
4575 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4576 arraysize(data_writes));
4577 session_deps.socket_factory.AddSocketDataProvider(&data);
4578
4579 TestCompletionCallback callback;
4580
[email protected]5a1d7ca2010-04-28 20:12:274581 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364582 EXPECT_EQ(ERR_IO_PENDING, rv);
4583
4584 rv = callback.WaitForResult();
4585 EXPECT_EQ(OK, rv);
4586
4587 const HttpResponseInfo* response = trans->GetResponseInfo();
4588 EXPECT_TRUE(response != NULL);
4589 EXPECT_TRUE(response->headers != NULL);
4590 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4591
4592 file_util::Delete(temp_file, false);
4593}
4594
4595TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4596 SessionDependencies session_deps;
4597 scoped_ptr<HttpTransaction> trans(
4598 new HttpNetworkTransaction(CreateSession(&session_deps)));
4599
4600 FilePath temp_file;
4601 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4602 std::string temp_file_contents("Unreadable file.");
4603 std::string unreadable_contents(temp_file_contents.length(), '\0');
4604 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4605 temp_file_contents.length()));
4606
4607 HttpRequestInfo request;
4608 request.method = "POST";
4609 request.url = GURL("http://www.google.com/upload");
4610 request.upload_data = new UploadData;
4611 request.load_flags = 0;
4612
4613 std::vector<UploadData::Element> elements;
4614 UploadData::Element element;
4615 element.SetToFilePath(temp_file);
4616 elements.push_back(element);
4617 request.upload_data->set_elements(elements);
4618
4619 MockRead data_reads[] = {
4620 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4621 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4622 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4623
4624 MockRead("HTTP/1.1 200 OK\r\n"),
4625 MockRead("Content-Length: 0\r\n\r\n"),
4626 MockRead(false, OK),
4627 };
4628 MockWrite data_writes[] = {
4629 MockWrite("POST /upload HTTP/1.1\r\n"
4630 "Host: www.google.com\r\n"
4631 "Connection: keep-alive\r\n"
4632 "Content-Length: 16\r\n\r\n"),
4633 MockWrite(false, temp_file_contents.c_str()),
4634
4635 MockWrite("POST /upload HTTP/1.1\r\n"
4636 "Host: www.google.com\r\n"
4637 "Connection: keep-alive\r\n"
4638 "Content-Length: 16\r\n"
4639 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4640 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4641 MockWrite(false, OK),
4642 };
4643 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4644 arraysize(data_writes));
4645 session_deps.socket_factory.AddSocketDataProvider(&data);
4646
4647 TestCompletionCallback callback1;
4648
[email protected]5a1d7ca2010-04-28 20:12:274649 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364650 EXPECT_EQ(ERR_IO_PENDING, rv);
4651
4652 rv = callback1.WaitForResult();
4653 EXPECT_EQ(OK, rv);
4654
4655 const HttpResponseInfo* response = trans->GetResponseInfo();
4656 EXPECT_TRUE(response != NULL);
4657 EXPECT_TRUE(response->headers != NULL);
4658 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4659
4660 // The password prompt info should have been set in response->auth_challenge.
4661 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4662 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4663 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4664 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4665
4666 // Now make the file unreadable and try again.
4667 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4668
4669 TestCompletionCallback callback2;
4670
4671 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4672 EXPECT_EQ(ERR_IO_PENDING, rv);
4673
4674 rv = callback2.WaitForResult();
4675 EXPECT_EQ(OK, rv);
4676
4677 response = trans->GetResponseInfo();
4678 EXPECT_TRUE(response != NULL);
4679 EXPECT_TRUE(response->headers != NULL);
4680 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4681 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4682
4683 file_util::Delete(temp_file, false);
4684}
4685
[email protected]aeefc9e82010-02-19 16:18:274686// Tests that changes to Auth realms are treated like auth rejections.
4687TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4688 SessionDependencies session_deps;
4689 scoped_ptr<HttpTransaction> trans(
4690 new HttpNetworkTransaction(CreateSession(&session_deps)));
4691
4692 HttpRequestInfo request;
4693 request.method = "GET";
4694 request.url = GURL("http://www.google.com/");
4695 request.load_flags = 0;
4696
4697 // First transaction will request a resource and receive a Basic challenge
4698 // with realm="first_realm".
4699 MockWrite data_writes1[] = {
4700 MockWrite("GET / HTTP/1.1\r\n"
4701 "Host: www.google.com\r\n"
4702 "Connection: keep-alive\r\n"
4703 "\r\n"),
4704 };
4705 MockRead data_reads1[] = {
4706 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4707 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4708 "\r\n"),
4709 };
4710
4711 // After calling trans->RestartWithAuth(), provide an Authentication header
4712 // for first_realm. The server will reject and provide a challenge with
4713 // second_realm.
4714 MockWrite data_writes2[] = {
4715 MockWrite("GET / HTTP/1.1\r\n"
4716 "Host: www.google.com\r\n"
4717 "Connection: keep-alive\r\n"
4718 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4719 "\r\n"),
4720 };
4721 MockRead data_reads2[] = {
4722 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4723 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4724 "\r\n"),
4725 };
4726
4727 // This again fails, and goes back to first_realm. Make sure that the
4728 // entry is removed from cache.
4729 MockWrite data_writes3[] = {
4730 MockWrite("GET / HTTP/1.1\r\n"
4731 "Host: www.google.com\r\n"
4732 "Connection: keep-alive\r\n"
4733 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4734 "\r\n"),
4735 };
4736 MockRead data_reads3[] = {
4737 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4738 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4739 "\r\n"),
4740 };
4741
4742 // Try one last time (with the correct password) and get the resource.
4743 MockWrite data_writes4[] = {
4744 MockWrite("GET / HTTP/1.1\r\n"
4745 "Host: www.google.com\r\n"
4746 "Connection: keep-alive\r\n"
4747 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4748 "\r\n"),
4749 };
4750 MockRead data_reads4[] = {
4751 MockRead("HTTP/1.1 200 OK\r\n"
4752 "Content-Type: text/html; charset=iso-8859-1\r\n"
4753 "Content-Length: 100\r\n"
4754 "\r\n"),
4755 };
4756
4757 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4758 data_writes1, arraysize(data_writes1));
4759 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4760 data_writes2, arraysize(data_writes2));
4761 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4762 data_writes3, arraysize(data_writes3));
4763 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4764 data_writes4, arraysize(data_writes4));
4765 session_deps.socket_factory.AddSocketDataProvider(&data1);
4766 session_deps.socket_factory.AddSocketDataProvider(&data2);
4767 session_deps.socket_factory.AddSocketDataProvider(&data3);
4768 session_deps.socket_factory.AddSocketDataProvider(&data4);
4769
4770 TestCompletionCallback callback1;
4771
4772 // Issue the first request with Authorize headers. There should be a
4773 // password prompt for first_realm waiting to be filled in after the
4774 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274775 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274776 EXPECT_EQ(ERR_IO_PENDING, rv);
4777 rv = callback1.WaitForResult();
4778 EXPECT_EQ(OK, rv);
4779 const HttpResponseInfo* response = trans->GetResponseInfo();
4780 ASSERT_FALSE(response == NULL);
4781 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4782 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4783 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4784 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4785
4786 // Issue the second request with an incorrect password. There should be a
4787 // password prompt for second_realm waiting to be filled in after the
4788 // transaction completes.
4789 TestCompletionCallback callback2;
4790 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4791 EXPECT_EQ(ERR_IO_PENDING, rv);
4792 rv = callback2.WaitForResult();
4793 EXPECT_EQ(OK, rv);
4794 response = trans->GetResponseInfo();
4795 ASSERT_FALSE(response == NULL);
4796 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4797 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4798 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4799 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4800
4801 // Issue the third request with another incorrect password. There should be
4802 // a password prompt for first_realm waiting to be filled in. If the password
4803 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4804 // first_realm was not correctly removed.
4805 TestCompletionCallback callback3;
4806 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4807 EXPECT_EQ(ERR_IO_PENDING, rv);
4808 rv = callback3.WaitForResult();
4809 EXPECT_EQ(OK, rv);
4810 response = trans->GetResponseInfo();
4811 ASSERT_FALSE(response == NULL);
4812 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4813 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4814 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4815 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4816
4817 // Issue the fourth request with the correct password and username.
4818 TestCompletionCallback callback4;
4819 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4820 EXPECT_EQ(ERR_IO_PENDING, rv);
4821 rv = callback4.WaitForResult();
4822 EXPECT_EQ(OK, rv);
4823 response = trans->GetResponseInfo();
4824 ASSERT_FALSE(response == NULL);
4825 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4826}
4827
[email protected]564b4912010-03-09 16:30:424828TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424829 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064830 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424831
[email protected]564b4912010-03-09 16:30:424832 SessionDependencies session_deps;
4833
4834 MockRead data_reads[] = {
4835 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064836 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424837 MockRead("hello world"),
4838 MockRead(false, OK),
4839 };
4840
4841 HttpRequestInfo request;
4842 request.method = "GET";
4843 request.url = GURL("http://www.google.com/");
4844 request.load_flags = 0;
4845
4846 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4847
4848 session_deps.socket_factory.AddSocketDataProvider(&data);
4849
4850 TestCompletionCallback callback;
4851
4852 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4853 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4854
[email protected]5a1d7ca2010-04-28 20:12:274855 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424856 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534857
[email protected]564b4912010-03-09 16:30:424858 HostPortPair http_host_port_pair;
4859 http_host_port_pair.host = "www.google.com";
4860 http_host_port_pair.port = 80;
4861 const HttpAlternateProtocols& alternate_protocols =
4862 session->alternate_protocols();
4863 EXPECT_FALSE(
4864 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4865
4866 EXPECT_EQ(OK, callback.WaitForResult());
4867
4868 const HttpResponseInfo* response = trans->GetResponseInfo();
4869 ASSERT_TRUE(response != NULL);
4870 ASSERT_TRUE(response->headers != NULL);
4871 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:534872 EXPECT_FALSE(response->was_fetched_via_spdy);
4873 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:424874
4875 std::string response_data;
4876 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4877 EXPECT_EQ("hello world", response_data);
4878
4879 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4880 const HttpAlternateProtocols::PortProtocolPair alternate =
4881 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4882 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4883 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064884 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424885 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424886
[email protected]31e2c69e2010-04-15 18:06:064887 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424888 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424889}
4890
4891TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064892 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424893 SessionDependencies session_deps;
4894
4895 HttpRequestInfo request;
4896 request.method = "GET";
4897 request.url = GURL("http://www.google.com/");
4898 request.load_flags = 0;
4899
4900 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4901 StaticSocketDataProvider first_data;
4902 first_data.set_connect_data(mock_connect);
4903 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4904
4905 MockRead data_reads[] = {
4906 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4907 MockRead("hello world"),
4908 MockRead(true, OK),
4909 };
4910 StaticSocketDataProvider second_data(
4911 data_reads, arraysize(data_reads), NULL, 0);
4912 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4913
4914 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4915 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4916 // http://crbug.com/37454.
4917 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4918
4919 TestCompletionCallback callback;
4920
4921 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4922
4923 HostPortPair http_host_port_pair;
4924 http_host_port_pair.host = "www.google.com";
4925 http_host_port_pair.port = 80;
4926 HttpAlternateProtocols* alternate_protocols =
4927 session->mutable_alternate_protocols();
4928 alternate_protocols->SetAlternateProtocolFor(
4929 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064930 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424931
4932 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4933
[email protected]5a1d7ca2010-04-28 20:12:274934 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424935 EXPECT_EQ(ERR_IO_PENDING, rv);
4936 EXPECT_EQ(OK, callback.WaitForResult());
4937
4938 const HttpResponseInfo* response = trans->GetResponseInfo();
4939 ASSERT_TRUE(response != NULL);
4940 ASSERT_TRUE(response->headers != NULL);
4941 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4942
4943 std::string response_data;
4944 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4945 EXPECT_EQ("hello world", response_data);
4946
4947 ASSERT_TRUE(
4948 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4949 const HttpAlternateProtocols::PortProtocolPair alternate =
4950 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4951 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064952 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424953}
4954
4955// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4956// says that it does SPDY, but it just does the TLS handshake, but the NPN
4957// response does not indicate SPDY, so we just do standard HTTPS over the port.
4958// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4959// on the original port.
[email protected]a2cb8122010-03-10 17:22:424960// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4961// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534962//
[email protected]a2cb8122010-03-10 17:22:424963// HttpRequestInfo request;
4964// request.method = "GET";
4965// request.url = GURL("http://www.google.com/");
4966// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534967//
[email protected]a2cb8122010-03-10 17:22:424968// MockRead data_reads[] = {
4969// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4970// MockRead("hello world"),
4971// MockRead(true, OK),
4972// };
4973// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4974// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534975//
[email protected]a2cb8122010-03-10 17:22:424976// SSLSocketDataProvider ssl(true, OK);
4977// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534978//
[email protected]a2cb8122010-03-10 17:22:424979// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534980//
[email protected]a2cb8122010-03-10 17:22:424981// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534982//
[email protected]a2cb8122010-03-10 17:22:424983// HostPortPair http_host_port_pair;
4984// http_host_port_pair.host = "www.google.com";
4985// http_host_port_pair.port = 80;
4986// HttpAlternateProtocols* alternate_protocols =
4987// session->mutable_alternate_protocols();
4988// alternate_protocols->SetAlternateProtocolFor(
4989// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064990// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534991//
[email protected]a2cb8122010-03-10 17:22:424992// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534993//
[email protected]5a1d7ca2010-04-28 20:12:274994// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:424995// EXPECT_EQ(ERR_IO_PENDING, rv);
4996// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534997//
[email protected]a2cb8122010-03-10 17:22:424998// const HttpResponseInfo* response = trans->GetResponseInfo();
4999// ASSERT_TRUE(response != NULL);
5000// ASSERT_TRUE(response->headers != NULL);
5001// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535002//
[email protected]a2cb8122010-03-10 17:22:425003// std::string response_data;
5004// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5005// EXPECT_EQ("hello world", response_data);
5006// }
5007
5008TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065009 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545010 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115011 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425012 SessionDependencies session_deps;
5013
5014 HttpRequestInfo request;
5015 request.method = "GET";
5016 request.url = GURL("http://www.google.com/");
5017 request.load_flags = 0;
5018
[email protected]a2cb8122010-03-10 17:22:425019 StaticSocketDataProvider first_tcp_connect;
5020 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5021
5022 SSLSocketDataProvider ssl(true, OK);
5023 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5024
[email protected]564b4912010-03-09 16:30:425025 MockRead data_reads[] = {
5026 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5027 MockRead("hello world"),
5028 MockRead(true, OK),
5029 };
[email protected]a2cb8122010-03-10 17:22:425030 StaticSocketDataProvider fallback_data(
5031 data_reads, arraysize(data_reads), NULL, 0);
5032 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425033
5034 TestCompletionCallback callback;
5035
5036 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5037
5038 HostPortPair http_host_port_pair;
5039 http_host_port_pair.host = "www.google.com";
5040 http_host_port_pair.port = 80;
5041 HttpAlternateProtocols* alternate_protocols =
5042 session->mutable_alternate_protocols();
5043 alternate_protocols->SetAlternateProtocolFor(
5044 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065045 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425046
5047 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5048
[email protected]5a1d7ca2010-04-28 20:12:275049 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425050 EXPECT_EQ(ERR_IO_PENDING, rv);
5051 EXPECT_EQ(OK, callback.WaitForResult());
5052
5053 const HttpResponseInfo* response = trans->GetResponseInfo();
5054 ASSERT_TRUE(response != NULL);
5055 ASSERT_TRUE(response->headers != NULL);
5056 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5057
5058 std::string response_data;
5059 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5060 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545061 HttpNetworkTransaction::SetNextProtos("");
5062 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5063}
5064
5065TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5066 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5067 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115068 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545069 SessionDependencies session_deps;
5070
5071 HttpRequestInfo request;
5072 request.method = "GET";
5073 request.url = GURL("http://www.google.com/");
5074 request.load_flags = 0;
5075
5076 MockRead data_reads[] = {
5077 MockRead("HTTP/1.1 200 OK\r\n"),
5078 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5079 MockRead("hello world"),
5080 MockRead(true, OK),
5081 };
5082
5083 StaticSocketDataProvider first_transaction(
5084 data_reads, arraysize(data_reads), NULL, 0);
5085 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5086
5087 SSLSocketDataProvider ssl(true, OK);
5088 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5089 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535090 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545091 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5092
5093 MockWrite spdy_writes[] = {
5094 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5095 arraysize(kGetSyn)),
5096 };
5097
5098 MockRead spdy_reads[] = {
5099 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5100 arraysize(kGetSynReply)),
5101 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5102 arraysize(kGetBodyFrame)),
5103 MockRead(true, 0, 0),
5104 };
5105
5106 scoped_refptr<DelayedSocketData> spdy_data(
5107 new DelayedSocketData(
5108 1, // wait for one write to finish before reading.
5109 spdy_reads, arraysize(spdy_reads),
5110 spdy_writes, arraysize(spdy_writes)));
5111 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5112
5113 TestCompletionCallback callback;
5114
5115 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5116 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5117
[email protected]5a1d7ca2010-04-28 20:12:275118 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545119 EXPECT_EQ(ERR_IO_PENDING, rv);
5120 EXPECT_EQ(OK, callback.WaitForResult());
5121
5122 const HttpResponseInfo* response = trans->GetResponseInfo();
5123 ASSERT_TRUE(response != NULL);
5124 ASSERT_TRUE(response->headers != NULL);
5125 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5126
5127 std::string response_data;
5128 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5129 EXPECT_EQ("hello world", response_data);
5130
5131 trans.reset(new HttpNetworkTransaction(session));
5132
[email protected]5a1d7ca2010-04-28 20:12:275133 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545134 EXPECT_EQ(ERR_IO_PENDING, rv);
5135 EXPECT_EQ(OK, callback.WaitForResult());
5136
5137 response = trans->GetResponseInfo();
5138 ASSERT_TRUE(response != NULL);
5139 ASSERT_TRUE(response->headers != NULL);
5140 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535141 EXPECT_TRUE(response->was_fetched_via_spdy);
5142 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:545143
5144 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5145 EXPECT_EQ("hello!", response_data);
5146
5147 HttpNetworkTransaction::SetNextProtos("");
5148 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5149}
5150
[email protected]631f1322010-04-30 17:59:115151class CapturingProxyResolver : public ProxyResolver {
5152 public:
5153 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5154 virtual ~CapturingProxyResolver() {}
5155
5156 virtual int GetProxyForURL(const GURL& url,
5157 ProxyInfo* results,
5158 CompletionCallback* callback,
5159 RequestHandle* request,
5160 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425161 ProxyServer proxy_server(
5162 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5163 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115164 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425165 return OK;
[email protected]631f1322010-04-30 17:59:115166 }
5167
5168 virtual void CancelRequest(RequestHandle request) {
5169 NOTREACHED();
5170 }
5171
5172 const std::vector<GURL>& resolved() const { return resolved_; }
5173
5174 private:
5175 virtual int SetPacScript(const GURL& /*pac_url*/,
5176 const std::string& /*pac_bytes*/,
5177 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425178 return OK;
[email protected]631f1322010-04-30 17:59:115179 }
5180
5181 std::vector<GURL> resolved_;
5182
5183 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5184};
5185
[email protected]631f1322010-04-30 17:59:115186TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5187 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5188 HttpNetworkTransaction::SetNextProtos(
5189 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5190
5191 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425192 proxy_config.set_auto_detect(true);
5193 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115194
[email protected]631f1322010-04-30 17:59:115195 CapturingProxyResolver* capturing_proxy_resolver =
5196 new CapturingProxyResolver();
5197 SessionDependencies session_deps(
5198 new ProxyService(new ProxyConfigServiceFixed(proxy_config),
5199 capturing_proxy_resolver,
5200 NULL,
5201 NULL));
5202
5203 HttpRequestInfo request;
5204 request.method = "GET";
5205 request.url = GURL("http://www.google.com/");
5206 request.load_flags = 0;
5207
5208 MockRead data_reads[] = {
5209 MockRead("HTTP/1.1 200 OK\r\n"),
5210 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5211 MockRead("hello world"),
5212 MockRead(true, OK),
5213 };
5214
5215 StaticSocketDataProvider first_transaction(
5216 data_reads, arraysize(data_reads), NULL, 0);
5217 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5218
5219 SSLSocketDataProvider ssl(true, OK);
5220 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5221 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535222 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115223 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5224
5225 MockWrite spdy_writes[] = {
5226 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5227 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425228 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]631f1322010-04-30 17:59:115229 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
[email protected]d911f1b2010-05-05 22:39:425230 arraysize(kGetSyn)), // 3
[email protected]631f1322010-04-30 17:59:115231 };
5232
[email protected]d911f1b2010-05-05 22:39:425233 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5234
[email protected]631f1322010-04-30 17:59:115235 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425236 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
5237 MockRead(true, reinterpret_cast<const char*>(kGetSynReply), // 2, 4
5238 arraysize(kGetSynReply), 4),
5239 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame), // 5
5240 arraysize(kGetBodyFrame), 4),
5241 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115242 };
5243
[email protected]d911f1b2010-05-05 22:39:425244 scoped_refptr<OrderedSocketData> spdy_data(
5245 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115246 spdy_reads, arraysize(spdy_reads),
5247 spdy_writes, arraysize(spdy_writes)));
5248 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5249
5250 TestCompletionCallback callback;
5251
5252 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5253 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5254
5255 int rv = trans->Start(&request, &callback, BoundNetLog());
5256 EXPECT_EQ(ERR_IO_PENDING, rv);
5257 EXPECT_EQ(OK, callback.WaitForResult());
5258
5259 const HttpResponseInfo* response = trans->GetResponseInfo();
5260 ASSERT_TRUE(response != NULL);
5261 ASSERT_TRUE(response->headers != NULL);
5262 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535263 EXPECT_FALSE(response->was_fetched_via_spdy);
5264 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115265
5266 std::string response_data;
5267 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5268 EXPECT_EQ("hello world", response_data);
5269
5270 trans.reset(new HttpNetworkTransaction(session));
5271
5272 rv = trans->Start(&request, &callback, BoundNetLog());
5273 EXPECT_EQ(ERR_IO_PENDING, rv);
5274 EXPECT_EQ(OK, callback.WaitForResult());
5275
5276 response = trans->GetResponseInfo();
5277 ASSERT_TRUE(response != NULL);
5278 ASSERT_TRUE(response->headers != NULL);
5279 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535280 EXPECT_TRUE(response->was_fetched_via_spdy);
5281 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115282
5283 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5284 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425285 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5286 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115287 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425288 EXPECT_EQ("https://www.google.com/",
5289 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115290
5291 HttpNetworkTransaction::SetNextProtos("");
5292 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5293}
[email protected]631f1322010-04-30 17:59:115294
[email protected]2ff8b312010-04-26 22:20:545295TEST_F(HttpNetworkTransactionTest,
5296 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5297 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5298 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115299 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545300 SessionDependencies session_deps;
5301
5302 HttpRequestInfo request;
5303 request.method = "GET";
5304 request.url = GURL("http://www.google.com/");
5305 request.load_flags = 0;
5306
5307 MockRead data_reads[] = {
5308 MockRead("HTTP/1.1 200 OK\r\n"),
5309 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5310 MockRead("hello world"),
5311 MockRead(true, OK),
5312 };
5313
5314 StaticSocketDataProvider first_transaction(
5315 data_reads, arraysize(data_reads), NULL, 0);
5316 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5317
5318 SSLSocketDataProvider ssl(true, OK);
5319 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5320 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535321 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545322 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535323 // Make sure we use ssl for spdy here.
5324 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545325
5326 MockWrite spdy_writes[] = {
5327 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5328 arraysize(kGetSyn)),
5329 };
5330
5331 MockRead spdy_reads[] = {
5332 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5333 arraysize(kGetSynReply)),
5334 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5335 arraysize(kGetBodyFrame)),
5336 MockRead(true, 0, 0),
5337 };
5338
5339 scoped_refptr<DelayedSocketData> spdy_data(
5340 new DelayedSocketData(
5341 1, // wait for one write to finish before reading.
5342 spdy_reads, arraysize(spdy_reads),
5343 spdy_writes, arraysize(spdy_writes)));
5344 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5345
5346 TestCompletionCallback callback;
5347
5348 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5349
5350 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5351
[email protected]5a1d7ca2010-04-28 20:12:275352 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545353 EXPECT_EQ(ERR_IO_PENDING, rv);
5354 EXPECT_EQ(OK, callback.WaitForResult());
5355
5356 const HttpResponseInfo* response = trans->GetResponseInfo();
5357 ASSERT_TRUE(response != NULL);
5358 ASSERT_TRUE(response->headers != NULL);
5359 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5360
5361 std::string response_data;
5362 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5363 EXPECT_EQ("hello world", response_data);
5364
5365 // Set up an initial SpdySession in the pool to reuse.
5366 scoped_refptr<SpdySession> spdy_session =
5367 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365368 session, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545369 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365370 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545371 trans.reset(new HttpNetworkTransaction(session));
5372
[email protected]5a1d7ca2010-04-28 20:12:275373 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545374 EXPECT_EQ(ERR_IO_PENDING, rv);
5375 EXPECT_EQ(OK, callback.WaitForResult());
5376
5377 response = trans->GetResponseInfo();
5378 ASSERT_TRUE(response != NULL);
5379 ASSERT_TRUE(response->headers != NULL);
5380 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535381 EXPECT_TRUE(response->was_fetched_via_spdy);
5382 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:545383
5384 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5385 EXPECT_EQ("hello!", response_data);
5386
5387 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065388 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425389}
5390
[email protected]044de0642010-06-17 10:42:155391// MockAuthHandler is used in tests to reliably trigger edge cases.
5392class MockAuthHandler : public HttpAuthHandler {
[email protected]e5ae96a2010-04-14 20:12:455393 public:
5394 enum Resolve {
5395 RESOLVE_INIT,
5396 RESOLVE_SKIP,
5397 RESOLVE_SYNC,
5398 RESOLVE_ASYNC,
5399 RESOLVE_TESTED,
5400 };
5401
[email protected]044de0642010-06-17 10:42:155402 MockAuthHandler()
[email protected]36c8e5f72010-06-07 14:17:145403 : resolve_(RESOLVE_INIT), user_callback_(NULL),
[email protected]044de0642010-06-17 10:42:155404 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
5405 generate_async_(false), generate_rv_(OK), auth_token_(NULL) {
[email protected]36c8e5f72010-06-07 14:17:145406 }
5407
[email protected]044de0642010-06-17 10:42:155408 virtual ~MockAuthHandler() {
[email protected]36c8e5f72010-06-07 14:17:145409 }
[email protected]e5ae96a2010-04-14 20:12:455410
5411 void SetResolveExpectation(Resolve resolve) {
5412 EXPECT_EQ(RESOLVE_INIT, resolve_);
5413 resolve_ = resolve;
5414 }
5415
[email protected]e5ae96a2010-04-14 20:12:455416 virtual bool NeedsCanonicalName() {
5417 switch (resolve_) {
5418 case RESOLVE_SYNC:
5419 case RESOLVE_ASYNC:
5420 return true;
5421 case RESOLVE_SKIP:
5422 resolve_ = RESOLVE_TESTED;
5423 return false;
5424 default:
5425 NOTREACHED();
5426 return false;
5427 }
5428 }
5429
5430 virtual int ResolveCanonicalName(HostResolver* host_resolver,
[email protected]ac5c06e2010-05-27 15:07:385431 CompletionCallback* callback) {
[email protected]e5ae96a2010-04-14 20:12:455432 EXPECT_NE(RESOLVE_TESTED, resolve_);
5433 int rv = OK;
5434 switch (resolve_) {
5435 case RESOLVE_SYNC:
5436 resolve_ = RESOLVE_TESTED;
5437 break;
5438 case RESOLVE_ASYNC:
5439 EXPECT_TRUE(user_callback_ == NULL);
5440 rv = ERR_IO_PENDING;
5441 user_callback_ = callback;
5442 MessageLoop::current()->PostTask(
[email protected]36c8e5f72010-06-07 14:17:145443 FROM_HERE, method_factory_.NewRunnableMethod(
[email protected]044de0642010-06-17 10:42:155444 &MockAuthHandler::OnResolveCanonicalName));
[email protected]e5ae96a2010-04-14 20:12:455445 break;
5446 default:
5447 NOTREACHED();
5448 break;
5449 }
5450 return rv;
5451 }
5452
[email protected]044de0642010-06-17 10:42:155453 void SetGenerateExpectation(bool async, int rv) {
5454 generate_async_ = async;
5455 generate_rv_ = rv;
5456 }
5457
[email protected]e5ae96a2010-04-14 20:12:455458 // The Factory class simply returns the same handler each time
5459 // CreateAuthHandler is called.
5460 class Factory : public HttpAuthHandlerFactory {
5461 public:
5462 Factory() {}
5463 virtual ~Factory() {}
5464
[email protected]044de0642010-06-17 10:42:155465 void set_mock_handler(HttpAuthHandler* handler, HttpAuth::Target target) {
5466 EXPECT_TRUE(handlers_[target].get() == NULL);
5467 handlers_[target].reset(handler);
[email protected]e5ae96a2010-04-14 20:12:455468 }
5469
5470 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
5471 HttpAuth::Target target,
5472 const GURL& origin,
[email protected]fa82f932010-05-20 11:09:245473 CreateReason reason,
5474 int nonce_count,
[email protected]ac5c06e2010-05-27 15:07:385475 const BoundNetLog& net_log,
[email protected]36c8e5f72010-06-07 14:17:145476 scoped_ptr<HttpAuthHandler>* handler) {
[email protected]044de0642010-06-17 10:42:155477 if (!handlers_[target].get())
[email protected]36c8e5f72010-06-07 14:17:145478 return ERR_UNEXPECTED;
[email protected]044de0642010-06-17 10:42:155479 handler->swap(handlers_[target]);
[email protected]e5ae96a2010-04-14 20:12:455480 return OK;
5481 }
5482
5483 private:
[email protected]044de0642010-06-17 10:42:155484 scoped_ptr<HttpAuthHandler> handlers_[HttpAuth::AUTH_NUM_TARGETS];
[email protected]e5ae96a2010-04-14 20:12:455485 };
5486
[email protected]bcc528e2010-06-10 15:03:245487 protected:
5488 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
5489 scheme_ = "mock";
5490 score_ = 1;
5491 properties_ = 0;
5492 return true;
5493 }
5494
5495 virtual int GenerateAuthTokenImpl(const std::wstring* username,
5496 const std::wstring* password,
5497 const HttpRequestInfo* request,
5498 CompletionCallback* callback,
5499 std::string* auth_token) {
[email protected]044de0642010-06-17 10:42:155500 if (generate_async_) {
5501 EXPECT_TRUE(user_callback_ == NULL);
5502 EXPECT_TRUE(auth_token_ == NULL);
5503 user_callback_ = callback;
5504 auth_token_ = auth_token;
5505 MessageLoop::current()->PostTask(
5506 FROM_HERE, method_factory_.NewRunnableMethod(
5507 &MockAuthHandler::OnGenerateAuthToken));
5508 return ERR_IO_PENDING;
5509 } else {
5510 if (generate_rv_ == OK)
5511 *auth_token = "auth_token";
5512 return generate_rv_;
5513 }
[email protected]bcc528e2010-06-10 15:03:245514 }
5515
[email protected]e5ae96a2010-04-14 20:12:455516 private:
[email protected]bcc528e2010-06-10 15:03:245517 void OnResolveCanonicalName() {
5518 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
5519 EXPECT_TRUE(user_callback_ != NULL);
5520 resolve_ = RESOLVE_TESTED;
5521 CompletionCallback* callback = user_callback_;
5522 user_callback_ = NULL;
5523 callback->Run(OK);
5524 }
5525
[email protected]044de0642010-06-17 10:42:155526 void OnGenerateAuthToken() {
5527 EXPECT_EQ(true, generate_async_);
5528 EXPECT_TRUE(user_callback_ != NULL);
5529 if (generate_rv_ == OK)
5530 *auth_token_ = "auth_token";
5531 auth_token_ = NULL;
5532 CompletionCallback* callback = user_callback_;
5533 user_callback_ = NULL;
5534 callback->Run(generate_rv_);
5535 }
5536
[email protected]e5ae96a2010-04-14 20:12:455537 Resolve resolve_;
5538 CompletionCallback* user_callback_;
[email protected]044de0642010-06-17 10:42:155539 ScopedRunnableMethodFactory<MockAuthHandler> method_factory_;
5540 bool generate_async_;
5541 int generate_rv_;
5542 std::string* auth_token_;
[email protected]e5ae96a2010-04-14 20:12:455543};
5544
5545// Tests that ResolveCanonicalName is handled correctly by the
5546// HttpNetworkTransaction.
5547TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5548 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:155549 MockAuthHandler::Factory* auth_factory(new MockAuthHandler::Factory());
[email protected]e5ae96a2010-04-14 20:12:455550 session_deps.http_auth_handler_factory.reset(auth_factory);
5551
5552 for (int i = 0; i < 2; ++i) {
[email protected]044de0642010-06-17 10:42:155553 MockAuthHandler* auth_handler(new MockAuthHandler());
[email protected]bcc528e2010-06-10 15:03:245554 std::string auth_challenge = "Mock";
5555 GURL origin("http://www.example.com");
5556 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5557 auth_challenge.end());
5558 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5559 origin, BoundNetLog());
[email protected]044de0642010-06-17 10:42:155560 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]36c8e5f72010-06-07 14:17:145561
[email protected]e5ae96a2010-04-14 20:12:455562 scoped_ptr<HttpTransaction> trans(
5563 new HttpNetworkTransaction(CreateSession(&session_deps)));
5564
5565 // Set up expectations for this pass of the test. Many of the EXPECT calls
[email protected]044de0642010-06-17 10:42:155566 // are contained inside the MockAuthHandler codebase in response to
[email protected]e5ae96a2010-04-14 20:12:455567 // the expectations.
[email protected]044de0642010-06-17 10:42:155568 MockAuthHandler::Resolve resolve = ((i == 0) ?
5569 MockAuthHandler::RESOLVE_SYNC :
5570 MockAuthHandler::RESOLVE_ASYNC);
[email protected]e5ae96a2010-04-14 20:12:455571 auth_handler->SetResolveExpectation(resolve);
5572 HttpRequestInfo request;
5573 request.method = "GET";
5574 request.url = GURL("http://myserver/");
5575 request.load_flags = 0;
5576
5577 MockWrite data_writes1[] = {
5578 MockWrite("GET / HTTP/1.1\r\n"
5579 "Host: myserver\r\n"
5580 "Connection: keep-alive\r\n\r\n"),
5581 };
5582
5583 MockRead data_reads1[] = {
5584 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5585 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5586 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5587 MockRead("Content-Length: 14\r\n\r\n"),
5588 MockRead("Unauthorized\r\n"),
5589 };
5590
5591 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5592 data_writes1, arraysize(data_writes1));
5593 session_deps.socket_factory.AddSocketDataProvider(&data1);
5594
5595 TestCompletionCallback callback1;
5596
[email protected]5a1d7ca2010-04-28 20:12:275597 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455598 EXPECT_EQ(ERR_IO_PENDING, rv);
5599
5600 rv = callback1.WaitForResult();
5601 EXPECT_EQ(OK, rv);
5602
5603 const HttpResponseInfo* response = trans->GetResponseInfo();
5604 EXPECT_FALSE(response == NULL);
5605
5606 // The password prompt is set after the canonical name is resolved.
5607 // If it isn't present or is incorrect, it indicates that the scheme
5608 // did not complete correctly.
5609 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5610
5611 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5612 EXPECT_EQ(L"", response->auth_challenge->realm);
5613 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
[email protected]044de0642010-06-17 10:42:155614 }
5615}
5616
5617// GenerateAuthToken is a mighty big test.
5618// It tests all permutation of GenerateAuthToken behavior:
5619// - Synchronous and Asynchronous completion.
5620// - OK or error on completion.
5621// - Direct connection, non-authenticating proxy, and authenticating proxy.
5622// - HTTP or HTTPS backend (to include proxy tunneling).
5623// - Non-authenticating and authenticating backend.
5624//
5625// In all, there are 44 reasonable permuations (for example, if there are
5626// problems generating an auth token for an authenticating proxy, we don't
5627// need to test all permutations of the backend server).
5628//
5629// The test proceeds by going over each of the configuration cases, and
5630// potentially running up to three rounds in each of the tests. The TestConfig
5631// specifies both the configuration for the test as well as the expectations
5632// for the results.
5633TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5634 const char* kServer = "http://www.example.com";
5635 const char* kSecureServer = "https://www.example.com";
5636 const char* kProxy = "myproxy:70";
5637 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5638
5639 enum AuthTiming {
5640 AUTH_NONE,
5641 AUTH_SYNC,
5642 AUTH_ASYNC,
5643 };
5644
5645 const MockWrite kGet(
5646 "GET / HTTP/1.1\r\n"
5647 "Host: www.example.com\r\n"
5648 "Connection: keep-alive\r\n\r\n");
5649 const MockWrite kGetProxy(
5650 "GET http://www.example.com/ HTTP/1.1\r\n"
5651 "Host: www.example.com\r\n"
5652 "Proxy-Connection: keep-alive\r\n\r\n");
5653 const MockWrite kGetAuth(
5654 "GET / HTTP/1.1\r\n"
5655 "Host: www.example.com\r\n"
5656 "Connection: keep-alive\r\n"
5657 "Authorization: auth_token\r\n\r\n");
5658 const MockWrite kGetProxyAuth(
5659 "GET http://www.example.com/ HTTP/1.1\r\n"
5660 "Host: www.example.com\r\n"
5661 "Proxy-Connection: keep-alive\r\n"
5662 "Proxy-Authorization: auth_token\r\n\r\n");
5663 const MockWrite kGetAuthThroughProxy(
5664 "GET http://www.example.com/ HTTP/1.1\r\n"
5665 "Host: www.example.com\r\n"
5666 "Proxy-Connection: keep-alive\r\n"
5667 "Authorization: auth_token\r\n\r\n");
5668 const MockWrite kGetAuthWithProxyAuth(
5669 "GET http://www.example.com/ HTTP/1.1\r\n"
5670 "Host: www.example.com\r\n"
5671 "Proxy-Connection: keep-alive\r\n"
5672 "Proxy-Authorization: auth_token\r\n"
5673 "Authorization: auth_token\r\n\r\n");
5674 const MockWrite kConnect(
5675 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5676 "Host: www.example.com\r\n"
5677 "Proxy-Connection: keep-alive\r\n\r\n");
5678 const MockWrite kConnectProxyAuth(
5679 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5680 "Host: www.example.com\r\n"
5681 "Proxy-Connection: keep-alive\r\n"
5682 "Proxy-Authorization: auth_token\r\n\r\n");
5683
5684 const MockRead kSuccess(
5685 "HTTP/1.1 200 OK\r\n"
5686 "Content-Type: text/html; charset=iso-8859-1\r\n"
5687 "Content-Length: 3\r\n\r\n"
5688 "Yes");
5689 const MockRead kFailure(
5690 "Should not be called.");
5691 const MockRead kServerChallenge(
5692 "HTTP/1.1 401 Unauthorized\r\n"
5693 "WWW-Authenticate: Mock realm=server\r\n"
5694 "Content-Type: text/html; charset=iso-8859-1\r\n"
5695 "Content-Length: 14\r\n\r\n"
5696 "Unauthorized\r\n");
5697 const MockRead kProxyChallenge(
5698 "HTTP/1.1 407 Unauthorized\r\n"
5699 "Proxy-Authenticate: Mock realm=proxy\r\n"
5700 "Proxy-Connection: close\r\n"
5701 "Content-Type: text/html; charset=iso-8859-1\r\n"
5702 "Content-Length: 14\r\n\r\n"
5703 "Unauthorized\r\n");
5704 const MockRead kProxyConnected(
5705 "HTTP/1.1 200 Connection Established\r\n\r\n");
5706
5707 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5708 // no constructors, but the C++ compiler on Windows warns about
5709 // unspecified data in compound literals. So, moved to using constructors,
5710 // and TestRound's created with the default constructor should not be used.
5711 struct TestRound {
5712 TestRound()
5713 : expected_rv(ERR_UNEXPECTED),
5714 extra_write(NULL),
5715 extra_read(NULL) {
5716 }
5717 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5718 int expected_rv_arg)
5719 : write(write_arg),
5720 read(read_arg),
5721 expected_rv(expected_rv_arg),
5722 extra_write(NULL),
5723 extra_read(NULL) {
5724 }
5725 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5726 int expected_rv_arg, const MockWrite* extra_write_arg,
5727 const MockWrite* extra_read_arg)
5728 : write(write_arg),
5729 read(read_arg),
5730 expected_rv(expected_rv_arg),
5731 extra_write(extra_write_arg),
5732 extra_read(extra_read_arg) {
5733 }
5734 MockWrite write;
5735 MockRead read;
5736 int expected_rv;
5737 const MockWrite* extra_write;
5738 const MockRead* extra_read;
5739 };
5740
5741 static const int kNoSSL = 500;
5742
5743 struct TestConfig {
5744 const char* proxy_url;
5745 AuthTiming proxy_auth_timing;
5746 int proxy_auth_rv;
5747 const char* server_url;
5748 AuthTiming server_auth_timing;
5749 int server_auth_rv;
5750 int num_auth_rounds;
5751 int first_ssl_round;
5752 TestRound rounds[3];
5753 } test_configs[] = {
5754 // Non-authenticating HTTP server with a direct connection.
5755 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5756 { TestRound(kGet, kSuccess, OK)}},
5757 // Authenticating HTTP server with a direct connection.
5758 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5759 { TestRound(kGet, kServerChallenge, OK),
5760 TestRound(kGetAuth, kSuccess, OK)}},
5761 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5762 { TestRound(kGet, kServerChallenge, OK),
5763 TestRound(kGetAuth, kFailure, kAuthErr)}},
5764 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5765 { TestRound(kGet, kServerChallenge, OK),
5766 TestRound(kGetAuth, kSuccess, OK)}},
5767 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5768 { TestRound(kGet, kServerChallenge, OK),
5769 TestRound(kGetAuth, kFailure, kAuthErr)}},
5770 // Non-authenticating HTTP server through a non-authenticating proxy.
5771 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5772 { TestRound(kGetProxy, kSuccess, OK)}},
5773 // Authenticating HTTP server through a non-authenticating proxy.
5774 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5775 { TestRound(kGetProxy, kServerChallenge, OK),
5776 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5777 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5778 { TestRound(kGetProxy, kServerChallenge, OK),
5779 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5780 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5781 { TestRound(kGetProxy, kServerChallenge, OK),
5782 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5783 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5784 { TestRound(kGetProxy, kServerChallenge, OK),
5785 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5786 // Non-authenticating HTTP server through an authenticating proxy.
5787 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5788 { TestRound(kGetProxy, kProxyChallenge, OK),
5789 TestRound(kGetProxyAuth, kSuccess, OK)}},
5790 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5791 { TestRound(kGetProxy, kProxyChallenge, OK),
5792 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5793 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5794 { TestRound(kGetProxy, kProxyChallenge, OK),
5795 TestRound(kGetProxyAuth, kSuccess, OK)}},
5796 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5797 { TestRound(kGetProxy, kProxyChallenge, OK),
5798 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5799 // Authenticating HTTP server through an authenticating proxy.
5800 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5801 { TestRound(kGetProxy, kProxyChallenge, OK),
5802 TestRound(kGetProxyAuth, kServerChallenge, OK),
5803 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5804 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5805 { TestRound(kGetProxy, kProxyChallenge, OK),
5806 TestRound(kGetProxyAuth, kServerChallenge, OK),
5807 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5808 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5809 { TestRound(kGetProxy, kProxyChallenge, OK),
5810 TestRound(kGetProxyAuth, kServerChallenge, OK),
5811 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5812 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5813 { TestRound(kGetProxy, kProxyChallenge, OK),
5814 TestRound(kGetProxyAuth, kServerChallenge, OK),
5815 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5816 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5817 { TestRound(kGetProxy, kProxyChallenge, OK),
5818 TestRound(kGetProxyAuth, kServerChallenge, OK),
5819 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5820 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5821 { TestRound(kGetProxy, kProxyChallenge, OK),
5822 TestRound(kGetProxyAuth, kServerChallenge, OK),
5823 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5824 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5825 { TestRound(kGetProxy, kProxyChallenge, OK),
5826 TestRound(kGetProxyAuth, kServerChallenge, OK),
5827 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5828 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5829 { TestRound(kGetProxy, kProxyChallenge, OK),
5830 TestRound(kGetProxyAuth, kServerChallenge, OK),
5831 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5832 // Non-authenticating HTTPS server with a direct connection.
5833 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5834 { TestRound(kGet, kSuccess, OK)}},
5835 // Authenticating HTTPS server with a direct connection.
5836 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5837 { TestRound(kGet, kServerChallenge, OK),
5838 TestRound(kGetAuth, kSuccess, OK)}},
5839 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5840 { TestRound(kGet, kServerChallenge, OK),
5841 TestRound(kGetAuth, kFailure, kAuthErr)}},
5842 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5843 { TestRound(kGet, kServerChallenge, OK),
5844 TestRound(kGetAuth, kSuccess, OK)}},
5845 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5846 { TestRound(kGet, kServerChallenge, OK),
5847 TestRound(kGetAuth, kFailure, kAuthErr)}},
5848 // Non-authenticating HTTPS server with a non-authenticating proxy.
5849 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5850 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5851 // Authenticating HTTPS server through a non-authenticating proxy.
5852 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5853 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5854 TestRound(kGetAuth, kSuccess, OK)}},
5855 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5856 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5857 TestRound(kGetAuth, kFailure, kAuthErr)}},
5858 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5859 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5860 TestRound(kGetAuth, kSuccess, OK)}},
5861 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5862 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5863 TestRound(kGetAuth, kFailure, kAuthErr)}},
5864 // Non-Authenticating HTTPS server through an authenticating proxy.
5865 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5866 { TestRound(kConnect, kProxyChallenge, OK),
5867 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5868 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5869 { TestRound(kConnect, kProxyChallenge, OK),
5870 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5871 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5872 { TestRound(kConnect, kProxyChallenge, OK),
5873 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5874 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5875 { TestRound(kConnect, kProxyChallenge, OK),
5876 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5877 // Authenticating HTTPS server through an authenticating proxy.
5878 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5879 { TestRound(kConnect, kProxyChallenge, OK),
5880 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5881 &kGet, &kServerChallenge),
5882 TestRound(kGetAuth, kSuccess, OK)}},
5883 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5884 { TestRound(kConnect, kProxyChallenge, OK),
5885 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5886 &kGet, &kServerChallenge),
5887 TestRound(kGetAuth, kFailure, kAuthErr)}},
5888 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5889 { TestRound(kConnect, kProxyChallenge, OK),
5890 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5891 &kGet, &kServerChallenge),
5892 TestRound(kGetAuth, kSuccess, OK)}},
5893 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5894 { TestRound(kConnect, kProxyChallenge, OK),
5895 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5896 &kGet, &kServerChallenge),
5897 TestRound(kGetAuth, kFailure, kAuthErr)}},
5898 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5899 { TestRound(kConnect, kProxyChallenge, OK),
5900 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5901 &kGet, &kServerChallenge),
5902 TestRound(kGetAuth, kSuccess, OK)}},
5903 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5904 { TestRound(kConnect, kProxyChallenge, OK),
5905 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5906 &kGet, &kServerChallenge),
5907 TestRound(kGetAuth, kFailure, kAuthErr)}},
5908 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5909 { TestRound(kConnect, kProxyChallenge, OK),
5910 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5911 &kGet, &kServerChallenge),
5912 TestRound(kGetAuth, kSuccess, OK)}},
5913 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5914 { TestRound(kConnect, kProxyChallenge, OK),
5915 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5916 &kGet, &kServerChallenge),
5917 TestRound(kGetAuth, kFailure, kAuthErr)}},
5918 };
5919
5920 SessionDependencies session_deps;
5921 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5922 MockAuthHandler::Factory* auth_factory(new MockAuthHandler::Factory());
5923 session_deps.http_auth_handler_factory.reset(auth_factory);
5924
5925 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5926 const TestConfig& test_config = test_configs[i];
5927 if (test_config.proxy_auth_timing != AUTH_NONE) {
5928 MockAuthHandler* auth_handler(new MockAuthHandler());
5929 std::string auth_challenge = "Mock realm=proxy";
5930 GURL origin(test_config.proxy_url);
5931 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5932 auth_challenge.end());
5933 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5934 origin, BoundNetLog());
5935 auth_handler->SetGenerateExpectation(
5936 test_config.proxy_auth_timing == AUTH_ASYNC,
5937 test_config.proxy_auth_rv);
5938 auth_handler->SetResolveExpectation(MockAuthHandler::RESOLVE_SKIP);
5939 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5940 }
5941 if (test_config.server_auth_timing != AUTH_NONE) {
5942 MockAuthHandler* auth_handler(new MockAuthHandler());
5943 std::string auth_challenge = "Mock realm=server";
5944 GURL origin(test_config.server_url);
5945 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5946 auth_challenge.end());
5947 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5948 origin, BoundNetLog());
5949 auth_handler->SetGenerateExpectation(
5950 test_config.server_auth_timing == AUTH_ASYNC,
5951 test_config.server_auth_rv);
5952 auth_handler->SetResolveExpectation(MockAuthHandler::RESOLVE_SKIP);
5953 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5954 }
5955 if (test_config.proxy_url) {
5956 session_deps.proxy_service =
5957 CreateFixedProxyService(test_config.proxy_url);
5958 } else {
5959 session_deps.proxy_service = ProxyService::CreateNull();
5960 }
5961
5962 HttpRequestInfo request;
5963 request.method = "GET";
5964 request.url = GURL(test_config.server_url);
5965 request.load_flags = 0;
5966
5967 scoped_ptr<HttpTransaction> trans(
5968 new HttpNetworkTransaction(CreateSession(&session_deps)));
5969
5970 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5971 const TestRound& read_write_round = test_config.rounds[round];
5972
5973 // Set up expected reads and writes.
5974 MockRead reads[2];
5975 reads[0] = read_write_round.read;
5976 size_t length_reads = 1;
5977 if (read_write_round.extra_read) {
5978 reads[1] = *read_write_round.extra_read;
5979 length_reads = 2;
5980 }
5981
5982 MockWrite writes[2];
5983 writes[0] = read_write_round.write;
5984 size_t length_writes = 1;
5985 if (read_write_round.extra_write) {
5986 writes[1] = *read_write_round.extra_write;
5987 length_writes = 2;
5988 }
5989 StaticSocketDataProvider data_provider(
5990 reads, length_reads, writes, length_writes);
5991 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
5992
5993 // Add an SSL sequence if necessary.
5994 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
5995 if (round >= test_config.first_ssl_round)
5996 session_deps.socket_factory.AddSSLSocketDataProvider(
5997 &ssl_socket_data_provider);
5998
5999 // Start or restart the transaction.
6000 TestCompletionCallback callback;
6001 int rv;
6002 if (round == 0) {
6003 rv = trans->Start(&request, &callback, BoundNetLog());
6004 } else {
6005 rv = trans->RestartWithAuth(L"foo", L"bar", &callback);
6006 }
6007 if (rv == ERR_IO_PENDING)
6008 rv = callback.WaitForResult();
6009
6010 // Compare results with expected data.
6011 EXPECT_EQ(read_write_round.expected_rv, rv);
6012 const HttpResponseInfo* response = trans->GetResponseInfo();
6013 if (read_write_round.expected_rv == OK) {
6014 EXPECT_FALSE(response == NULL);
6015 } else {
6016 EXPECT_TRUE(response == NULL);
6017 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6018 continue;
6019 }
6020 if (round + 1 < test_config.num_auth_rounds) {
6021 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6022 } else {
6023 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6024 }
6025 }
[email protected]e5ae96a2010-04-14 20:12:456026 }
6027}
6028
[email protected]aeaca1f2010-04-20 22:05:216029class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6030 public:
[email protected]06650c52010-06-03 00:49:176031 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216032 : fail_all_(fail_all) {
6033 }
6034
6035 virtual MockRead GetNextRead() {
6036 if (fail_all_)
6037 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6038
6039 return MockRead(false /* async */,
6040 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6041 }
6042
6043 virtual MockWriteResult OnWrite(const std::string& data) {
6044 return MockWriteResult(false /* async */, data.size());
6045 }
6046
6047 void Reset() {
6048 }
6049
6050 private:
6051 const bool fail_all_;
6052};
6053
6054// Test that we restart a connection when we see a decompression failure from
6055// the peer during the handshake. (In the real world we'll restart with SSLv3
6056// and we won't offer DEFLATE in that case.)
6057TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6058 HttpRequestInfo request;
6059 request.method = "GET";
6060 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6061 request.load_flags = 0;
6062
6063 SessionDependencies session_deps;
6064 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6065 false /* fail all reads */);
6066 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6067 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116068 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216069 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6070 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6071 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6072 session_deps.socket_factory.AddSSLSocketDataProvider(
6073 &ssl_socket_data_provider1);
6074 session_deps.socket_factory.AddSSLSocketDataProvider(
6075 &ssl_socket_data_provider2);
6076
6077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6078 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6079 TestCompletionCallback callback;
6080
[email protected]5a1d7ca2010-04-28 20:12:276081 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216082 EXPECT_EQ(ERR_IO_PENDING, rv);
6083 EXPECT_EQ(OK, callback.WaitForResult());
6084
6085 const HttpResponseInfo* response = trans->GetResponseInfo();
6086 ASSERT_TRUE(response != NULL);
6087 ASSERT_TRUE(response->headers != NULL);
6088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6089
6090 std::string response_data;
6091 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6092 EXPECT_EQ("ok.", response_data);
6093}
6094
6095// Test that we restart a connection if we get a decompression failure from the
6096// peer while reading the first bytes from the connection. This occurs when the
6097// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6098// in the handshake.
6099TEST_F(HttpNetworkTransactionTest,
6100 RestartAfterTLSDecompressionFailureWithFalseStart) {
6101 HttpRequestInfo request;
6102 request.method = "GET";
6103 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6104 request.load_flags = 0;
6105
6106 SessionDependencies session_deps;
6107 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6108 true /* fail all reads */);
6109 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6110 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6111 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6112 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6113 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6114 session_deps.socket_factory.AddSSLSocketDataProvider(
6115 &ssl_socket_data_provider1);
6116 session_deps.socket_factory.AddSSLSocketDataProvider(
6117 &ssl_socket_data_provider2);
6118
6119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6120 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6121 TestCompletionCallback callback;
6122
[email protected]5a1d7ca2010-04-28 20:12:276123 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216124 EXPECT_EQ(ERR_IO_PENDING, rv);
6125 EXPECT_EQ(OK, callback.WaitForResult());
6126
6127 const HttpResponseInfo* response = trans->GetResponseInfo();
6128 ASSERT_TRUE(response != NULL);
6129 ASSERT_TRUE(response->headers != NULL);
6130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6131
6132 std::string response_data;
6133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6134 EXPECT_EQ("ok.", response_data);
6135}
6136
[email protected]65041fa2010-05-21 06:56:536137// This tests the case that a request is issued via http instead of spdy after
6138// npn is negotiated.
6139TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6140 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6141 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6142 SessionDependencies session_deps;
6143 HttpRequestInfo request;
6144 request.method = "GET";
6145 request.url = GURL("https://www.google.com/");
6146 request.load_flags = 0;
6147
6148 MockWrite data_writes[] = {
6149 MockWrite("GET / HTTP/1.1\r\n"
6150 "Host: www.google.com\r\n"
6151 "Connection: keep-alive\r\n\r\n"),
6152 };
6153
6154 MockRead data_reads[] = {
6155 MockRead("HTTP/1.1 200 OK\r\n"),
6156 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
6157 MockRead("hello world"),
6158 MockRead(false, OK),
6159 };
6160
6161 SSLSocketDataProvider ssl(true, OK);
6162 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6163 ssl.next_proto = "http/1.1";
6164
6165 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6166
6167 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6168 data_writes, arraysize(data_writes));
6169 session_deps.socket_factory.AddSocketDataProvider(&data);
6170
6171 TestCompletionCallback callback;
6172
6173 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6174 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6175
6176 int rv = trans->Start(&request, &callback, BoundNetLog());
6177
6178 EXPECT_EQ(ERR_IO_PENDING, rv);
6179 EXPECT_EQ(OK, callback.WaitForResult());
6180
6181 const HttpResponseInfo* response = trans->GetResponseInfo();
6182 ASSERT_TRUE(response != NULL);
6183 ASSERT_TRUE(response->headers != NULL);
6184 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6185
6186 std::string response_data;
6187 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6188 EXPECT_EQ("hello world", response_data);
6189
6190 EXPECT_FALSE(response->was_fetched_via_spdy);
6191 EXPECT_TRUE(response->was_npn_negotiated);
6192
6193 HttpNetworkTransaction::SetNextProtos("");
6194 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6195}
[email protected]89ceba9a2009-03-21 03:46:066196} // namespace net