blob: dd047730114dba5bcc95ecffe0e51290d28d84ba [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]169d0012010-05-10 23:20:1215#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3217#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/net_log.h"
19#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3120#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4221#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "net/base/test_completion_callback.h"
24#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1225#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0026#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2927#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5728#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5332#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1133#include "net/proxy/proxy_resolver.h"
34#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4435#include "net/socket/client_socket_factory.h"
36#include "net/socket/socket_test_util.h"
37#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5438#include "net/spdy/spdy_framer.h"
39#include "net/spdy/spdy_session.h"
40#include "net/spdy/spdy_session_pool.h"
41#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5242#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1543#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5244
45//-----------------------------------------------------------------------------
46
[email protected]89ceba9a2009-03-21 03:46:0647namespace net {
48
[email protected]2d731a32010-04-29 01:04:0649class HttpNetworkSessionPeer {
50 public:
51 explicit HttpNetworkSessionPeer(
52 const scoped_refptr<HttpNetworkSession>& session)
53 : session_(session) {}
54
55 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
56 session_->tcp_socket_pool_ = pool;
57 }
58
59 void SetSocketPoolForSOCKSProxy(
60 const HostPortPair& socks_proxy,
61 const scoped_refptr<SOCKSClientSocketPool>& pool) {
62 session_->socks_socket_pool_[socks_proxy] = pool;
63 }
64
65 void SetSocketPoolForHTTPProxy(
66 const HostPortPair& http_proxy,
67 const scoped_refptr<TCPClientSocketPool>& pool) {
68 session_->http_proxy_socket_pool_[http_proxy] = pool;
69 }
70
71 private:
72 const scoped_refptr<HttpNetworkSession> session_;
73
74 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
75};
76
[email protected]e44de5d2009-06-05 20:12:4577// Helper to manage the lifetimes of the dependencies for a
78// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4479struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5980 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4281 SessionDependencies()
82 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3783 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1084 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5285 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]66761b952010-06-25 21:30:3886 spdy_session_pool(new SpdySessionPool()) {}
[email protected]228ff742009-06-05 01:19:5987
88 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4589 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4290 : host_resolver(new MockHostResolver),
91 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1092 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5293 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]66761b952010-06-25 21:30:3894 spdy_session_pool(new SpdySessionPool()) {}
[email protected]228ff742009-06-05 01:19:5995
[email protected]a2c2fb92009-07-18 07:31:0496 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0997 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4298 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5999 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50100 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52101 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:59102};
103
[email protected]1c773ea12009-04-28 19:58:42104ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50105 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48106 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39107 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53108}
109
[email protected]228ff742009-06-05 01:19:59110HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38111 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09112 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42113 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10114 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52115 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17116 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44117 NULL,
[email protected]06650c52010-06-03 00:49:17118 NULL);
[email protected]e8d536192008-10-17 22:21:14119}
120
[email protected]89836e22008-09-25 20:33:42121class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52122 public:
[email protected]2ff8b312010-04-26 22:20:54123 virtual void SetUp() {
124 spdy::SpdyFramer::set_enable_compression_default(false);
125 }
126
[email protected]0e75a732008-10-16 20:36:09127 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54128 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09129 // Empty the current queue.
130 MessageLoop::current()->RunAllPending();
131 PlatformTest::TearDown();
132 }
133
[email protected]3d2a59b2008-09-26 19:44:25134 protected:
135 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52136
[email protected]ff007e162009-05-23 09:13:15137 struct SimpleGetHelperResult {
138 int rv;
139 std::string status_line;
140 std::string response_data;
141 };
initial.commit586acc5fe2008-07-26 22:42:52142
[email protected]31a2bfe2010-02-09 08:03:39143 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
144 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15145 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52146
[email protected]228ff742009-06-05 01:19:59147 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40148 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43149 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]ff007e162009-05-23 09:13:15151 HttpRequestInfo request;
152 request.method = "GET";
153 request.url = GURL("http://www.google.com/");
154 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]31a2bfe2010-02-09 08:03:39156 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59157 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]ff007e162009-05-23 09:13:15159 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52160
[email protected]169d0012010-05-10 23:20:12161 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
162 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15163 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52164
[email protected]ff007e162009-05-23 09:13:15165 out.rv = callback.WaitForResult();
166 if (out.rv != OK)
167 return out;
168
169 const HttpResponseInfo* response = trans->GetResponseInfo();
170 EXPECT_TRUE(response != NULL);
171
172 EXPECT_TRUE(response->headers != NULL);
173 out.status_line = response->headers->GetStatusLine();
174
175 rv = ReadTransaction(trans.get(), &out.response_data);
176 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39177 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12178 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
179 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39180 ExpectLogContainsSomewhere(
181 log.entries(), pos,
182 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
183 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15184
[email protected]aecfbf22008-10-16 02:02:47185 return out;
[email protected]ff007e162009-05-23 09:13:15186 }
initial.commit586acc5fe2008-07-26 22:42:52187
[email protected]ff007e162009-05-23 09:13:15188 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
189 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52190
[email protected]ff007e162009-05-23 09:13:15191 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15192};
[email protected]231d5a32008-09-13 00:45:27193
[email protected]15a5ccf82008-10-23 19:57:43194// Fill |str| with a long header list that consumes >= |size| bytes.
195void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19196 const char* row =
197 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
198 const int sizeof_row = strlen(row);
199 const int num_rows = static_cast<int>(
200 ceil(static_cast<float>(size) / sizeof_row));
201 const int sizeof_data = num_rows * sizeof_row;
202 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43203 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51204
[email protected]4ddaf2502008-10-23 18:26:19205 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43206 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19207}
208
[email protected]385a4672009-03-11 22:21:29209// Alternative functions that eliminate randomness and dependency on the local
210// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20211void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29212 static const uint8 bytes[] = {
213 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
214 };
215 static size_t current_byte = 0;
216 for (size_t i = 0; i < n; ++i) {
217 output[i] = bytes[current_byte++];
218 current_byte %= arraysize(bytes);
219 }
220}
221
[email protected]fe2bc6a2009-03-23 16:52:20222void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29223 static const uint8 bytes[] = {
224 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
225 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
226 };
227 static size_t current_byte = 0;
228 for (size_t i = 0; i < n; ++i) {
229 output[i] = bytes[current_byte++];
230 current_byte %= arraysize(bytes);
231 }
232}
233
[email protected]fe2bc6a2009-03-23 16:52:20234std::string MockGetHostName() {
235 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29236}
237
[email protected]2d731a32010-04-29 01:04:06238template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26239class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31240 public:
[email protected]06650c52010-06-03 00:49:17241 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]b89f7e42010-05-20 20:37:00242 : EmulatedClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
[email protected]66761b952010-06-25 21:30:38243 NULL) {
244 }
[email protected]d80a4322009-08-14 07:07:49245 const std::string last_group_name_received() const {
246 return last_group_name_;
247 }
248
[email protected]684970b2009-08-14 04:54:46249 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49250 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31251 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31252 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46253 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53254 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31255 last_group_name_ = group_name;
256 return ERR_IO_PENDING;
257 }
[email protected]04e5be32009-06-26 20:00:31258 virtual void CancelRequest(const std::string& group_name,
259 const ClientSocketHandle* handle) { }
260 virtual void ReleaseSocket(const std::string& group_name,
261 ClientSocket* socket) {}
262 virtual void CloseIdleSockets() {}
263 virtual HostResolver* GetHostResolver() const {
264 return NULL;
265 }
266 virtual int IdleSocketCount() const {
267 return 0;
268 }
269 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
270 return 0;
271 }
272 virtual LoadState GetLoadState(const std::string& group_name,
273 const ClientSocketHandle* handle) const {
274 return LOAD_STATE_IDLE;
275 }
[email protected]a796bcec2010-03-22 17:17:26276 virtual base::TimeDelta ConnectionTimeout() const {
277 return base::TimeDelta();
278 }
[email protected]d80a4322009-08-14 07:07:49279
280 private:
[email protected]04e5be32009-06-26 20:00:31281 std::string last_group_name_;
282};
283
[email protected]2d731a32010-04-29 01:04:06284typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11285CaptureGroupNameTCPSocketPool;
[email protected]2d731a32010-04-29 01:04:06286typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11287CaptureGroupNameSOCKSSocketPool;
288
[email protected]231d5a32008-09-13 00:45:27289//-----------------------------------------------------------------------------
290
291TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59292 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40293 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43294 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27295}
296
297TEST_F(HttpNetworkTransactionTest, SimpleGET) {
298 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35299 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
300 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42301 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27302 };
[email protected]31a2bfe2010-02-09 08:03:39303 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
304 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42305 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27306 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
307 EXPECT_EQ("hello world", out.response_data);
308}
309
310// Response with no status line.
311TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
312 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35313 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42314 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27315 };
[email protected]31a2bfe2010-02-09 08:03:39316 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
317 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42318 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27319 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
320 EXPECT_EQ("hello world", out.response_data);
321}
322
323// Allow up to 4 bytes of junk to precede status line.
324TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
325 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35326 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42327 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27328 };
[email protected]31a2bfe2010-02-09 08:03:39329 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
330 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42331 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27332 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
333 EXPECT_EQ("DATA", out.response_data);
334}
335
336// Allow up to 4 bytes of junk to precede status line.
337TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
338 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35339 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42340 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27341 };
[email protected]31a2bfe2010-02-09 08:03:39342 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
343 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42344 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27345 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
346 EXPECT_EQ("DATA", out.response_data);
347}
348
349// Beyond 4 bytes of slop and it should fail to find a status line.
350TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35352 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42353 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27354 };
[email protected]31a2bfe2010-02-09 08:03:39355 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
356 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42357 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25358 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
359 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27360}
361
362// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
363TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
364 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35365 MockRead("\n"),
366 MockRead("\n"),
367 MockRead("Q"),
368 MockRead("J"),
369 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42370 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27371 };
[email protected]31a2bfe2010-02-09 08:03:39372 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
373 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42374 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27375 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
376 EXPECT_EQ("DATA", out.response_data);
377}
378
379// Close the connection before enough bytes to have a status line.
380TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
381 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35382 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42383 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27384 };
[email protected]31a2bfe2010-02-09 08:03:39385 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
386 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42387 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27388 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
389 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52390}
391
[email protected]f9d44aa2008-09-23 23:57:17392// Simulate a 204 response, lacking a Content-Length header, sent over a
393// persistent connection. The response should still terminate since a 204
394// cannot have a response body.
395TEST_F(HttpNetworkTransactionTest, StopsReading204) {
396 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35397 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
398 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42399 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17400 };
[email protected]31a2bfe2010-02-09 08:03:39401 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
402 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42403 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17404 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
405 EXPECT_EQ("", out.response_data);
406}
407
[email protected]0877e3d2009-10-17 22:29:57408// A simple request using chunked encoding with some extra data after.
409// (Like might be seen in a pipelined response.)
410TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
411 MockRead data_reads[] = {
412 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
413 MockRead("5\r\nHello\r\n"),
414 MockRead("1\r\n"),
415 MockRead(" \r\n"),
416 MockRead("5\r\nworld\r\n"),
417 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
418 MockRead(false, OK),
419 };
[email protected]31a2bfe2010-02-09 08:03:39420 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
421 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57422 EXPECT_EQ(OK, out.rv);
423 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
424 EXPECT_EQ("Hello world", out.response_data);
425}
426
[email protected]ef0faf2e72009-03-05 23:27:23427// Do a request using the HEAD method. Verify that we don't try to read the
428// message body (since HEAD has none).
429TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59430 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40431 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43432 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23433
[email protected]1c773ea12009-04-28 19:58:42434 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23435 request.method = "HEAD";
436 request.url = GURL("http://www.google.com/");
437 request.load_flags = 0;
438
439 MockWrite data_writes1[] = {
440 MockWrite("HEAD / HTTP/1.1\r\n"
441 "Host: www.google.com\r\n"
442 "Connection: keep-alive\r\n"
443 "Content-Length: 0\r\n\r\n"),
444 };
445 MockRead data_reads1[] = {
446 MockRead("HTTP/1.1 404 Not Found\r\n"),
447 MockRead("Server: Blah\r\n"),
448 MockRead("Content-Length: 1234\r\n\r\n"),
449
450 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42451 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23452 };
453
[email protected]31a2bfe2010-02-09 08:03:39454 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
455 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59456 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23457
458 TestCompletionCallback callback1;
459
[email protected]5a1d7ca2010-04-28 20:12:27460 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42461 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23462
463 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42464 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23465
[email protected]1c773ea12009-04-28 19:58:42466 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23467 EXPECT_FALSE(response == NULL);
468
469 // Check that the headers got parsed.
470 EXPECT_TRUE(response->headers != NULL);
471 EXPECT_EQ(1234, response->headers->GetContentLength());
472 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
473
474 std::string server_header;
475 void* iter = NULL;
476 bool has_server_header = response->headers->EnumerateHeader(
477 &iter, "Server", &server_header);
478 EXPECT_TRUE(has_server_header);
479 EXPECT_EQ("Blah", server_header);
480
481 // Reading should give EOF right away, since there is no message body
482 // (despite non-zero content-length).
483 std::string response_data;
484 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42485 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23486 EXPECT_EQ("", response_data);
487}
488
initial.commit586acc5fe2008-07-26 22:42:52489TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59490 SessionDependencies session_deps;
491 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52492
493 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35494 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
495 MockRead("hello"),
496 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
497 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42498 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52499 };
[email protected]31a2bfe2010-02-09 08:03:39500 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59501 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52502
503 const char* kExpectedResponseData[] = {
504 "hello", "world"
505 };
506
507 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43508 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52509
[email protected]1c773ea12009-04-28 19:58:42510 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52511 request.method = "GET";
512 request.url = GURL("http://www.google.com/");
513 request.load_flags = 0;
514
515 TestCompletionCallback callback;
516
[email protected]5a1d7ca2010-04-28 20:12:27517 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42518 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52519
520 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42521 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52522
[email protected]1c773ea12009-04-28 19:58:42523 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52524 EXPECT_TRUE(response != NULL);
525
526 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25527 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52528
529 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57530 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42531 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25532 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52533 }
534}
535
536TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59537 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40538 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43539 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52540
[email protected]1c773ea12009-04-28 19:58:42541 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52542 request.method = "POST";
543 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42544 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52545 request.upload_data->AppendBytes("foo", 3);
546 request.load_flags = 0;
547
548 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35549 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
550 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
551 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42552 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52553 };
[email protected]31a2bfe2010-02-09 08:03:39554 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59555 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52556
557 TestCompletionCallback callback;
558
[email protected]5a1d7ca2010-04-28 20:12:27559 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42560 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52561
562 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42563 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52564
[email protected]1c773ea12009-04-28 19:58:42565 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52566 EXPECT_TRUE(response != NULL);
567
568 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25569 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52570
571 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57572 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42573 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25574 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52575}
576
[email protected]3a2d3662009-03-27 03:49:14577// This test is almost the same as Ignores100 above, but the response contains
578// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57579// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14580TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59581 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40582 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43583 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14584
[email protected]1c773ea12009-04-28 19:58:42585 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14586 request.method = "GET";
587 request.url = GURL("http://www.foo.com/");
588 request.load_flags = 0;
589
590 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57591 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
592 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14593 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42594 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14595 };
[email protected]31a2bfe2010-02-09 08:03:39596 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59597 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14598
599 TestCompletionCallback callback;
600
[email protected]5a1d7ca2010-04-28 20:12:27601 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42602 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14603
604 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42605 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14606
[email protected]1c773ea12009-04-28 19:58:42607 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14608 EXPECT_TRUE(response != NULL);
609
610 EXPECT_TRUE(response->headers != NULL);
611 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
612
613 std::string response_data;
614 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42615 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14616 EXPECT_EQ("hello world", response_data);
617}
618
[email protected]ee9410e72010-01-07 01:42:38619TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
620 SessionDependencies session_deps;
621 scoped_ptr<HttpTransaction> trans(
622 new HttpNetworkTransaction(CreateSession(&session_deps)));
623
624 HttpRequestInfo request;
625 request.method = "POST";
626 request.url = GURL("http://www.foo.com/");
627 request.load_flags = 0;
628
629 MockRead data_reads[] = {
630 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
631 MockRead(true, 0),
632 };
[email protected]31a2bfe2010-02-09 08:03:39633 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38634 session_deps.socket_factory.AddSocketDataProvider(&data);
635
636 TestCompletionCallback callback;
637
[email protected]5a1d7ca2010-04-28 20:12:27638 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38639 EXPECT_EQ(ERR_IO_PENDING, rv);
640
641 rv = callback.WaitForResult();
642 EXPECT_EQ(OK, rv);
643
644 std::string response_data;
645 rv = ReadTransaction(trans.get(), &response_data);
646 EXPECT_EQ(OK, rv);
647 EXPECT_EQ("", response_data);
648}
649
650TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
651 SessionDependencies session_deps;
652 scoped_ptr<HttpTransaction> trans(
653 new HttpNetworkTransaction(CreateSession(&session_deps)));
654
655 HttpRequestInfo request;
656 request.method = "POST";
657 request.url = GURL("http://www.foo.com/");
658 request.load_flags = 0;
659
660 MockRead data_reads[] = {
661 MockRead(true, 0),
662 };
[email protected]31a2bfe2010-02-09 08:03:39663 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38664 session_deps.socket_factory.AddSocketDataProvider(&data);
665
666 TestCompletionCallback callback;
667
[email protected]5a1d7ca2010-04-28 20:12:27668 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38669 EXPECT_EQ(ERR_IO_PENDING, rv);
670
671 rv = callback.WaitForResult();
672 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
673}
674
[email protected]3d2a59b2008-09-26 19:44:25675// read_failure specifies a read failure that should cause the network
676// transaction to resend the request.
677void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
678 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59679 SessionDependencies session_deps;
680 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52681
[email protected]1c773ea12009-04-28 19:58:42682 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52683 request.method = "GET";
684 request.url = GURL("http://www.foo.com/");
685 request.load_flags = 0;
686
687 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35688 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
689 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25690 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52691 };
[email protected]31a2bfe2010-02-09 08:03:39692 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59693 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52694
695 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35696 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
697 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42698 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52699 };
[email protected]31a2bfe2010-02-09 08:03:39700 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59701 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52702
703 const char* kExpectedResponseData[] = {
704 "hello", "world"
705 };
706
707 for (int i = 0; i < 2; ++i) {
708 TestCompletionCallback callback;
709
[email protected]5695b8c2009-09-30 21:36:43710 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52711
[email protected]5a1d7ca2010-04-28 20:12:27712 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52714
715 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42716 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52717
[email protected]1c773ea12009-04-28 19:58:42718 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52719 EXPECT_TRUE(response != NULL);
720
721 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25722 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52723
724 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57725 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42726 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25727 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52728 }
729}
[email protected]3d2a59b2008-09-26 19:44:25730
731TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42732 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25733 KeepAliveConnectionResendRequestTest(read_failure);
734}
735
736TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42737 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25738 KeepAliveConnectionResendRequestTest(read_failure);
739}
740
741TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59742 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40743 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43744 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25745
[email protected]1c773ea12009-04-28 19:58:42746 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25747 request.method = "GET";
748 request.url = GURL("http://www.google.com/");
749 request.load_flags = 0;
750
751 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42752 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35753 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
754 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42755 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25756 };
[email protected]31a2bfe2010-02-09 08:03:39757 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59758 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25759
760 TestCompletionCallback callback;
761
[email protected]5a1d7ca2010-04-28 20:12:27762 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42763 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25764
765 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42766 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25767
[email protected]1c773ea12009-04-28 19:58:42768 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25769 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25770}
771
772// What do various browsers do when the server closes a non-keepalive
773// connection without sending any response header or body?
774//
775// IE7: error page
776// Safari 3.1.2 (Windows): error page
777// Firefox 3.0.1: blank page
778// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42779// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
780// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25781TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
782 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42783 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35784 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
785 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42786 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25787 };
[email protected]31a2bfe2010-02-09 08:03:39788 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
789 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42790 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25791}
[email protected]038e9a32008-10-08 22:40:16792
[email protected]fc31d6a42010-06-24 18:05:13793// Test that we correctly reuse a keep-alive connection after receiving a 304.
794TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
795 SessionDependencies session_deps;
796 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
797
798 HttpRequestInfo request;
799 request.method = "GET";
800 request.url = GURL("http://www.foo.com/");
801 request.load_flags = 0;
802
803 MockRead data1_reads[] = {
804 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
805 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
806 MockRead("hello"),
807 };
808 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
809 session_deps.socket_factory.AddSocketDataProvider(&data1);
810
811 MockRead data2_reads[] = {
812 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
813 };
814 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
815 session_deps.socket_factory.AddSocketDataProvider(&data2);
816
817 for (int i = 0; i < 2; ++i) {
818 TestCompletionCallback callback;
819
820 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
821
822 int rv = trans->Start(&request, &callback, BoundNetLog());
823 EXPECT_EQ(ERR_IO_PENDING, rv);
824
825 rv = callback.WaitForResult();
826 EXPECT_EQ(OK, rv);
827
828 const HttpResponseInfo* response = trans->GetResponseInfo();
829 EXPECT_TRUE(response != NULL);
830
831 EXPECT_TRUE(response->headers != NULL);
832 if (i == 0) {
833 EXPECT_EQ("HTTP/1.1 304 Not Modified",
834 response->headers->GetStatusLine());
835 // We intentionally don't read the response in this case, to reflect how
836 // HttpCache::Transaction uses HttpNetworkTransaction.
837 } else {
838 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
839 std::string response_data;
840 rv = ReadTransaction(trans.get(), &response_data);
841 EXPECT_EQ(OK, rv);
842 EXPECT_EQ("hello", response_data);
843 }
844 }
845}
846
[email protected]038e9a32008-10-08 22:40:16847// Test the request-challenge-retry sequence for basic auth.
848// (basic auth is the easiest to mock, because it has no randomness).
849TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59850 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40851 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43852 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16853
[email protected]1c773ea12009-04-28 19:58:42854 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16855 request.method = "GET";
856 request.url = GURL("http://www.google.com/");
857 request.load_flags = 0;
858
[email protected]f9ee6b52008-11-08 06:46:23859 MockWrite data_writes1[] = {
860 MockWrite("GET / HTTP/1.1\r\n"
861 "Host: www.google.com\r\n"
862 "Connection: keep-alive\r\n\r\n"),
863 };
864
[email protected]038e9a32008-10-08 22:40:16865 MockRead data_reads1[] = {
866 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
867 // Give a couple authenticate options (only the middle one is actually
868 // supported).
[email protected]22927ad2009-09-21 19:56:19869 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16870 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
871 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
872 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
873 // Large content-length -- won't matter, as connection will be reset.
874 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42875 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16876 };
877
878 // After calling trans->RestartWithAuth(), this is the request we should
879 // be issuing -- the final header line contains the credentials.
880 MockWrite data_writes2[] = {
881 MockWrite("GET / HTTP/1.1\r\n"
882 "Host: www.google.com\r\n"
883 "Connection: keep-alive\r\n"
884 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
885 };
886
887 // Lastly, the server responds with the actual content.
888 MockRead data_reads2[] = {
889 MockRead("HTTP/1.0 200 OK\r\n"),
890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
891 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42892 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16893 };
894
[email protected]31a2bfe2010-02-09 08:03:39895 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
896 data_writes1, arraysize(data_writes1));
897 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
898 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59899 session_deps.socket_factory.AddSocketDataProvider(&data1);
900 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16901
902 TestCompletionCallback callback1;
903
[email protected]5a1d7ca2010-04-28 20:12:27904 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16906
907 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42908 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16909
[email protected]1c773ea12009-04-28 19:58:42910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16911 EXPECT_FALSE(response == NULL);
912
913 // The password prompt info should have been set in response->auth_challenge.
914 EXPECT_FALSE(response->auth_challenge.get() == NULL);
915
[email protected]71e4573a2009-05-21 22:03:00916 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16917 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
918 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
919
920 TestCompletionCallback callback2;
921
922 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42923 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16924
925 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42926 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16927
928 response = trans->GetResponseInfo();
929 EXPECT_FALSE(response == NULL);
930 EXPECT_TRUE(response->auth_challenge.get() == NULL);
931 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16932}
933
[email protected]861fcd52009-08-26 02:33:46934TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
935 SessionDependencies session_deps;
936 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43937 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46938
939 HttpRequestInfo request;
940 request.method = "GET";
941 request.url = GURL("http://www.google.com/");
942 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
943
944 MockWrite data_writes[] = {
945 MockWrite("GET / HTTP/1.1\r\n"
946 "Host: www.google.com\r\n"
947 "Connection: keep-alive\r\n\r\n"),
948 };
949
950 MockRead data_reads[] = {
951 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
952 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
954 // Large content-length -- won't matter, as connection will be reset.
955 MockRead("Content-Length: 10000\r\n\r\n"),
956 MockRead(false, ERR_FAILED),
957 };
958
[email protected]31a2bfe2010-02-09 08:03:39959 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
960 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59961 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46962 TestCompletionCallback callback;
963
[email protected]5a1d7ca2010-04-28 20:12:27964 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46965 EXPECT_EQ(ERR_IO_PENDING, rv);
966
967 rv = callback.WaitForResult();
968 EXPECT_EQ(0, rv);
969
970 const HttpResponseInfo* response = trans->GetResponseInfo();
971 ASSERT_FALSE(response == NULL);
972 EXPECT_TRUE(response->auth_challenge.get() == NULL);
973}
974
[email protected]2d2697f92009-02-18 21:00:32975// Test the request-challenge-retry sequence for basic auth, over a keep-alive
976// connection.
977TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59978 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40979 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43980 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32981
[email protected]1c773ea12009-04-28 19:58:42982 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32983 request.method = "GET";
984 request.url = GURL("http://www.google.com/");
985 request.load_flags = 0;
986
987 MockWrite data_writes1[] = {
988 MockWrite("GET / HTTP/1.1\r\n"
989 "Host: www.google.com\r\n"
990 "Connection: keep-alive\r\n\r\n"),
991
992 // After calling trans->RestartWithAuth(), this is the request we should
993 // be issuing -- the final header line contains the credentials.
994 MockWrite("GET / HTTP/1.1\r\n"
995 "Host: www.google.com\r\n"
996 "Connection: keep-alive\r\n"
997 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
998 };
999
1000 MockRead data_reads1[] = {
1001 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1002 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1004 MockRead("Content-Length: 14\r\n\r\n"),
1005 MockRead("Unauthorized\r\n"),
1006
1007 // Lastly, the server responds with the actual content.
1008 MockRead("HTTP/1.1 200 OK\r\n"),
1009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1010 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421011 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321012 };
1013
[email protected]31a2bfe2010-02-09 08:03:391014 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1015 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591016 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321017
1018 TestCompletionCallback callback1;
1019
[email protected]5a1d7ca2010-04-28 20:12:271020 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421021 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321022
1023 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421024 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321025
[email protected]1c773ea12009-04-28 19:58:421026 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321027 EXPECT_FALSE(response == NULL);
1028
1029 // The password prompt info should have been set in response->auth_challenge.
1030 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1031
[email protected]71e4573a2009-05-21 22:03:001032 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321033 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1034 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1035
1036 TestCompletionCallback callback2;
1037
1038 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421039 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321040
1041 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421042 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321043
1044 response = trans->GetResponseInfo();
1045 EXPECT_FALSE(response == NULL);
1046 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1047 EXPECT_EQ(100, response->headers->GetContentLength());
1048}
1049
1050// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1051// connection and with no response body to drain.
1052TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591053 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401054 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431055 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321056
[email protected]1c773ea12009-04-28 19:58:421057 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321058 request.method = "GET";
1059 request.url = GURL("http://www.google.com/");
1060 request.load_flags = 0;
1061
1062 MockWrite data_writes1[] = {
1063 MockWrite("GET / HTTP/1.1\r\n"
1064 "Host: www.google.com\r\n"
1065 "Connection: keep-alive\r\n\r\n"),
1066
1067 // After calling trans->RestartWithAuth(), this is the request we should
1068 // be issuing -- the final header line contains the credentials.
1069 MockWrite("GET / HTTP/1.1\r\n"
1070 "Host: www.google.com\r\n"
1071 "Connection: keep-alive\r\n"
1072 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1073 };
1074
[email protected]2d2697f92009-02-18 21:00:321075 MockRead data_reads1[] = {
1076 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1077 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311078 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321079
1080 // Lastly, the server responds with the actual content.
1081 MockRead("HTTP/1.1 200 OK\r\n"),
1082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1083 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421084 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321085 };
1086
[email protected]31a2bfe2010-02-09 08:03:391087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1088 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591089 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321090
1091 TestCompletionCallback callback1;
1092
[email protected]5a1d7ca2010-04-28 20:12:271093 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421094 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321095
1096 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421097 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321098
[email protected]1c773ea12009-04-28 19:58:421099 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321100 EXPECT_FALSE(response == NULL);
1101
1102 // The password prompt info should have been set in response->auth_challenge.
1103 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1104
[email protected]71e4573a2009-05-21 22:03:001105 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321106 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1107 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1108
1109 TestCompletionCallback callback2;
1110
1111 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421112 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321113
1114 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421115 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321116
1117 response = trans->GetResponseInfo();
1118 EXPECT_FALSE(response == NULL);
1119 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1120 EXPECT_EQ(100, response->headers->GetContentLength());
1121}
1122
1123// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1124// connection and with a large response body to drain.
1125TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591126 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401127 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431128 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321129
[email protected]1c773ea12009-04-28 19:58:421130 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321131 request.method = "GET";
1132 request.url = GURL("http://www.google.com/");
1133 request.load_flags = 0;
1134
1135 MockWrite data_writes1[] = {
1136 MockWrite("GET / HTTP/1.1\r\n"
1137 "Host: www.google.com\r\n"
1138 "Connection: keep-alive\r\n\r\n"),
1139
1140 // After calling trans->RestartWithAuth(), this is the request we should
1141 // be issuing -- the final header line contains the credentials.
1142 MockWrite("GET / HTTP/1.1\r\n"
1143 "Host: www.google.com\r\n"
1144 "Connection: keep-alive\r\n"
1145 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1146 };
1147
1148 // Respond with 5 kb of response body.
1149 std::string large_body_string("Unauthorized");
1150 large_body_string.append(5 * 1024, ' ');
1151 large_body_string.append("\r\n");
1152
1153 MockRead data_reads1[] = {
1154 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1155 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1157 // 5134 = 12 + 5 * 1024 + 2
1158 MockRead("Content-Length: 5134\r\n\r\n"),
1159 MockRead(true, large_body_string.data(), large_body_string.size()),
1160
1161 // Lastly, the server responds with the actual content.
1162 MockRead("HTTP/1.1 200 OK\r\n"),
1163 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1164 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421165 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321166 };
1167
[email protected]31a2bfe2010-02-09 08:03:391168 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1169 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591170 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321171
1172 TestCompletionCallback callback1;
1173
[email protected]5a1d7ca2010-04-28 20:12:271174 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421175 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321176
1177 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421178 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321179
[email protected]1c773ea12009-04-28 19:58:421180 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321181 EXPECT_FALSE(response == NULL);
1182
1183 // The password prompt info should have been set in response->auth_challenge.
1184 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1185
[email protected]71e4573a2009-05-21 22:03:001186 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321187 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1188 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1189
1190 TestCompletionCallback callback2;
1191
1192 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421193 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321194
1195 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421196 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321197
1198 response = trans->GetResponseInfo();
1199 EXPECT_FALSE(response == NULL);
1200 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1201 EXPECT_EQ(100, response->headers->GetContentLength());
1202}
1203
1204// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311205// connection, but the server gets impatient and closes the connection.
1206TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1207 SessionDependencies session_deps;
1208 scoped_ptr<HttpTransaction> trans(
1209 new HttpNetworkTransaction(CreateSession(&session_deps)));
1210
1211 HttpRequestInfo request;
1212 request.method = "GET";
1213 request.url = GURL("http://www.google.com/");
1214 request.load_flags = 0;
1215
1216 MockWrite data_writes1[] = {
1217 MockWrite("GET / HTTP/1.1\r\n"
1218 "Host: www.google.com\r\n"
1219 "Connection: keep-alive\r\n\r\n"),
1220 // This simulates the seemingly successful write to a closed connection
1221 // if the bug is not fixed.
1222 MockWrite("GET / HTTP/1.1\r\n"
1223 "Host: www.google.com\r\n"
1224 "Connection: keep-alive\r\n"
1225 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1226 };
1227
1228 MockRead data_reads1[] = {
1229 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1230 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1231 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1232 MockRead("Content-Length: 14\r\n\r\n"),
1233 // Tell MockTCPClientSocket to simulate the server closing the connection.
1234 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1235 MockRead("Unauthorized\r\n"),
1236 MockRead(false, OK), // The server closes the connection.
1237 };
1238
1239 // After calling trans->RestartWithAuth(), this is the request we should
1240 // be issuing -- the final header line contains the credentials.
1241 MockWrite data_writes2[] = {
1242 MockWrite("GET / HTTP/1.1\r\n"
1243 "Host: www.google.com\r\n"
1244 "Connection: keep-alive\r\n"
1245 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1246 };
1247
1248 // Lastly, the server responds with the actual content.
1249 MockRead data_reads2[] = {
1250 MockRead("HTTP/1.1 200 OK\r\n"),
1251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1252 MockRead("Content-Length: 100\r\n\r\n"),
1253 MockRead(false, OK),
1254 };
1255
[email protected]31a2bfe2010-02-09 08:03:391256 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1257 data_writes1, arraysize(data_writes1));
1258 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1259 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311260 session_deps.socket_factory.AddSocketDataProvider(&data1);
1261 session_deps.socket_factory.AddSocketDataProvider(&data2);
1262
1263 TestCompletionCallback callback1;
1264
[email protected]5a1d7ca2010-04-28 20:12:271265 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311266 EXPECT_EQ(ERR_IO_PENDING, rv);
1267
1268 rv = callback1.WaitForResult();
1269 EXPECT_EQ(OK, rv);
1270
1271 const HttpResponseInfo* response = trans->GetResponseInfo();
1272 EXPECT_FALSE(response == NULL);
1273
1274 // The password prompt info should have been set in response->auth_challenge.
1275 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1276
1277 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1278 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1279 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1280
1281 TestCompletionCallback callback2;
1282
1283 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1284 EXPECT_EQ(ERR_IO_PENDING, rv);
1285
1286 rv = callback2.WaitForResult();
1287 EXPECT_EQ(OK, rv);
1288
1289 response = trans->GetResponseInfo();
1290 ASSERT_FALSE(response == NULL);
1291 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1292 EXPECT_EQ(100, response->headers->GetContentLength());
1293}
1294
1295// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321296// proxy connection, when setting up an SSL tunnel.
1297TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1298 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591299 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321301
[email protected]5695b8c2009-09-30 21:36:431302 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321303
[email protected]1c773ea12009-04-28 19:58:421304 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321305 request.method = "GET";
1306 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461307 // Ensure that proxy authentication is attempted even
1308 // when the no authentication data flag is set.
1309 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321310
1311 // Since we have proxy, should try to establish tunnel.
1312 MockWrite data_writes1[] = {
1313 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451314 "Host: www.google.com\r\n"
1315 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321316
1317 // After calling trans->RestartWithAuth(), this is the request we should
1318 // be issuing -- the final header line contains the credentials.
1319 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1320 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451321 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321322 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1323 };
1324
1325 // The proxy responds to the connect with a 407, using a persistent
1326 // connection.
1327 MockRead data_reads1[] = {
1328 // No credentials.
1329 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1330 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1331 MockRead("Content-Length: 10\r\n\r\n"),
1332 MockRead("0123456789"),
1333
1334 // Wrong credentials (wrong password).
1335 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1336 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1337 MockRead("Content-Length: 10\r\n\r\n"),
1338 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421339 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321340 };
1341
[email protected]31a2bfe2010-02-09 08:03:391342 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1343 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591344 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321345
1346 TestCompletionCallback callback1;
1347
[email protected]dbb83db2010-05-11 18:13:391348 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1349 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421350 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321351
1352 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421353 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391354 size_t pos = ExpectLogContainsSomewhere(
1355 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1356 NetLog::PHASE_NONE);
1357 ExpectLogContainsSomewhere(
1358 log.entries(), pos,
1359 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1360 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321361
[email protected]1c773ea12009-04-28 19:58:421362 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321363 EXPECT_FALSE(response == NULL);
1364
1365 EXPECT_TRUE(response->headers->IsKeepAlive());
1366 EXPECT_EQ(407, response->headers->response_code());
1367 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421368 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321369
1370 // The password prompt info should have been set in response->auth_challenge.
1371 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1372
[email protected]71e4573a2009-05-21 22:03:001373 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321374 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1375 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1376
1377 TestCompletionCallback callback2;
1378
1379 // Wrong password (should be "bar").
1380 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321382
1383 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421384 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321385
1386 response = trans->GetResponseInfo();
1387 EXPECT_FALSE(response == NULL);
1388
1389 EXPECT_TRUE(response->headers->IsKeepAlive());
1390 EXPECT_EQ(407, response->headers->response_code());
1391 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421392 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321393
1394 // The password prompt info should have been set in response->auth_challenge.
1395 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1396
[email protected]71e4573a2009-05-21 22:03:001397 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321398 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1399 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1400}
1401
[email protected]a8e9b162009-03-12 00:06:441402// Test that we don't read the response body when we fail to establish a tunnel,
1403// even if the user cancels the proxy's auth attempt.
1404TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1405 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591406 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441407
[email protected]e44de5d2009-06-05 20:12:451408 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441409
[email protected]5695b8c2009-09-30 21:36:431410 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441411
[email protected]1c773ea12009-04-28 19:58:421412 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441413 request.method = "GET";
1414 request.url = GURL("https://www.google.com/");
1415 request.load_flags = 0;
1416
1417 // Since we have proxy, should try to establish tunnel.
1418 MockWrite data_writes[] = {
1419 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451420 "Host: www.google.com\r\n"
1421 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441422 };
1423
1424 // The proxy responds to the connect with a 407.
1425 MockRead data_reads[] = {
1426 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1427 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1428 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421429 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441430 };
1431
[email protected]31a2bfe2010-02-09 08:03:391432 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1433 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591434 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441435
1436 TestCompletionCallback callback;
1437
[email protected]5a1d7ca2010-04-28 20:12:271438 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421439 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441440
1441 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421442 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441443
[email protected]1c773ea12009-04-28 19:58:421444 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441445 EXPECT_FALSE(response == NULL);
1446
1447 EXPECT_TRUE(response->headers->IsKeepAlive());
1448 EXPECT_EQ(407, response->headers->response_code());
1449 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421450 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441451
1452 std::string response_data;
1453 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421454 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441455}
1456
[email protected]8fdbcd22010-05-05 02:54:521457// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1458// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1459TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1460 // We are using a DIRECT connection (i.e. no proxy) for this session.
1461 SessionDependencies session_deps;
1462 scoped_ptr<HttpTransaction> trans(
1463 new HttpNetworkTransaction(CreateSession(&session_deps)));
1464
1465 HttpRequestInfo request;
1466 request.method = "GET";
1467 request.url = GURL("http://www.google.com/");
1468 request.load_flags = 0;
1469
1470 MockWrite data_writes1[] = {
1471 MockWrite("GET / HTTP/1.1\r\n"
1472 "Host: www.google.com\r\n"
1473 "Connection: keep-alive\r\n\r\n"),
1474 };
1475
1476 MockRead data_reads1[] = {
1477 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1478 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1479 // Large content-length -- won't matter, as connection will be reset.
1480 MockRead("Content-Length: 10000\r\n\r\n"),
1481 MockRead(false, ERR_FAILED),
1482 };
1483
1484 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1485 data_writes1, arraysize(data_writes1));
1486 session_deps.socket_factory.AddSocketDataProvider(&data1);
1487
1488 TestCompletionCallback callback;
1489
1490 int rv = trans->Start(&request, &callback, BoundNetLog());
1491 EXPECT_EQ(ERR_IO_PENDING, rv);
1492
1493 rv = callback.WaitForResult();
1494 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1495}
1496
[email protected]ff007e162009-05-23 09:13:151497void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081498 const MockRead& status, int expected_status) {
1499 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591500 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081501
[email protected]228ff742009-06-05 01:19:591502 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081503
[email protected]5695b8c2009-09-30 21:36:431504 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081505
[email protected]1c773ea12009-04-28 19:58:421506 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081507 request.method = "GET";
1508 request.url = GURL("https://www.google.com/");
1509 request.load_flags = 0;
1510
1511 // Since we have proxy, should try to establish tunnel.
1512 MockWrite data_writes[] = {
1513 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451514 "Host: www.google.com\r\n"
1515 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081516 };
1517
1518 MockRead data_reads[] = {
1519 status,
1520 MockRead("Content-Length: 10\r\n\r\n"),
1521 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421522 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081523 };
1524
[email protected]31a2bfe2010-02-09 08:03:391525 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1526 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591527 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081528
1529 TestCompletionCallback callback;
1530
[email protected]5a1d7ca2010-04-28 20:12:271531 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421532 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081533
1534 rv = callback.WaitForResult();
1535 EXPECT_EQ(expected_status, rv);
1536}
1537
[email protected]ff007e162009-05-23 09:13:151538void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081539 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421540 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081541}
1542
1543TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1544 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1545}
1546
1547TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1548 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1549}
1550
1551TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1552 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1553}
1554
1555TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1556 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1557}
1558
1559TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1560 ConnectStatusHelper(
1561 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1562}
1563
1564TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1565 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1566}
1567
1568TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1569 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1570}
1571
1572TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1573 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1574}
1575
1576TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1577 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1578}
1579
1580TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1581 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1582}
1583
1584TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1585 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1586}
1587
1588TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1589 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1590}
1591
1592TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1593 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1594}
1595
1596TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1597 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1598}
1599
1600TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1601 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1602}
1603
1604TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1605 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1606}
1607
1608TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1609 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1610}
1611
1612TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1613 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1614}
1615
1616TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1617 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1618}
1619
1620TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1621 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1622}
1623
1624TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1625 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1626}
1627
1628TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1629 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1630}
1631
1632TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1633 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1634}
1635
1636TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1637 ConnectStatusHelperWithExpectedStatus(
1638 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421639 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081640}
1641
1642TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1643 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1644}
1645
1646TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1647 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1648}
1649
1650TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1651 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1652}
1653
1654TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1655 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1656}
1657
1658TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1659 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1660}
1661
1662TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1663 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1664}
1665
1666TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1667 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1668}
1669
1670TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1671 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1672}
1673
1674TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1675 ConnectStatusHelper(
1676 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1677}
1678
1679TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1680 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1681}
1682
1683TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1684 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1685}
1686
1687TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1688 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1689}
1690
1691TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1692 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1693}
1694
1695TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1696 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1697}
1698
1699TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1700 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1701}
1702
1703TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1704 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1705}
1706
[email protected]038e9a32008-10-08 22:40:161707// Test the flow when both the proxy server AND origin server require
1708// authentication. Again, this uses basic auth for both since that is
1709// the simplest to mock.
1710TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591711 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011712
[email protected]038e9a32008-10-08 22:40:161713 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431715 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161716
[email protected]1c773ea12009-04-28 19:58:421717 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161718 request.method = "GET";
1719 request.url = GURL("http://www.google.com/");
1720 request.load_flags = 0;
1721
[email protected]f9ee6b52008-11-08 06:46:231722 MockWrite data_writes1[] = {
1723 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1724 "Host: www.google.com\r\n"
1725 "Proxy-Connection: keep-alive\r\n\r\n"),
1726 };
1727
[email protected]038e9a32008-10-08 22:40:161728 MockRead data_reads1[] = {
1729 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1730 // Give a couple authenticate options (only the middle one is actually
1731 // supported).
[email protected]22927ad2009-09-21 19:56:191732 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161733 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1734 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1735 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1736 // Large content-length -- won't matter, as connection will be reset.
1737 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421738 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161739 };
1740
1741 // After calling trans->RestartWithAuth() the first time, this is the
1742 // request we should be issuing -- the final header line contains the
1743 // proxy's credentials.
1744 MockWrite data_writes2[] = {
1745 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1746 "Host: www.google.com\r\n"
1747 "Proxy-Connection: keep-alive\r\n"
1748 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1749 };
1750
1751 // Now the proxy server lets the request pass through to origin server.
1752 // The origin server responds with a 401.
1753 MockRead data_reads2[] = {
1754 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1755 // Note: We are using the same realm-name as the proxy server. This is
1756 // completely valid, as realms are unique across hosts.
1757 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1758 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1759 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421760 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161761 };
1762
1763 // After calling trans->RestartWithAuth() the second time, we should send
1764 // the credentials for both the proxy and origin server.
1765 MockWrite data_writes3[] = {
1766 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1767 "Host: www.google.com\r\n"
1768 "Proxy-Connection: keep-alive\r\n"
1769 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1770 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1771 };
1772
1773 // Lastly we get the desired content.
1774 MockRead data_reads3[] = {
1775 MockRead("HTTP/1.0 200 OK\r\n"),
1776 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1777 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421778 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161779 };
1780
[email protected]31a2bfe2010-02-09 08:03:391781 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1782 data_writes1, arraysize(data_writes1));
1783 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1784 data_writes2, arraysize(data_writes2));
1785 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1786 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591787 session_deps.socket_factory.AddSocketDataProvider(&data1);
1788 session_deps.socket_factory.AddSocketDataProvider(&data2);
1789 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161790
1791 TestCompletionCallback callback1;
1792
[email protected]5a1d7ca2010-04-28 20:12:271793 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421794 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161795
1796 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421797 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161798
[email protected]1c773ea12009-04-28 19:58:421799 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161800 EXPECT_FALSE(response == NULL);
1801
1802 // The password prompt info should have been set in response->auth_challenge.
1803 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1804
[email protected]71e4573a2009-05-21 22:03:001805 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161806 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1807 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1808
1809 TestCompletionCallback callback2;
1810
1811 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421812 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161813
1814 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421815 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161816
1817 response = trans->GetResponseInfo();
1818 EXPECT_FALSE(response == NULL);
1819 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1820
[email protected]71e4573a2009-05-21 22:03:001821 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161822 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1823 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1824
1825 TestCompletionCallback callback3;
1826
1827 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421828 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161829
1830 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421831 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161832
1833 response = trans->GetResponseInfo();
1834 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1835 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161836}
[email protected]4ddaf2502008-10-23 18:26:191837
[email protected]ea9dc9a2009-09-05 00:43:321838// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1839// can't hook into its internals to cause it to generate predictable NTLM
1840// authorization headers.
1841#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291842// The NTLM authentication unit tests were generated by capturing the HTTP
1843// requests and responses using Fiddler 2 and inspecting the generated random
1844// bytes in the debugger.
1845
1846// Enter the correct password and authenticate successfully.
1847TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421848 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111849 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591850 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401851 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431852 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241853
[email protected]1c773ea12009-04-28 19:58:421854 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241855 request.method = "GET";
1856 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1857 request.load_flags = 0;
1858
1859 MockWrite data_writes1[] = {
1860 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1861 "Host: 172.22.68.17\r\n"
1862 "Connection: keep-alive\r\n\r\n"),
1863 };
1864
1865 MockRead data_reads1[] = {
1866 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1867 // Negotiate and NTLM are often requested together. We only support NTLM.
1868 MockRead("WWW-Authenticate: Negotiate\r\n"),
1869 MockRead("WWW-Authenticate: NTLM\r\n"),
1870 MockRead("Connection: close\r\n"),
1871 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361872 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241873 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421874 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241875 };
1876
1877 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221878 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241879 // request we should be issuing -- the final header line contains a Type
1880 // 1 message.
1881 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1882 "Host: 172.22.68.17\r\n"
1883 "Connection: keep-alive\r\n"
1884 "Authorization: NTLM "
1885 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1886
1887 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1888 // (the credentials for the origin server). The second request continues
1889 // on the same connection.
1890 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1891 "Host: 172.22.68.17\r\n"
1892 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291893 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1894 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1895 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1896 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1897 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241898 };
1899
1900 MockRead data_reads2[] = {
1901 // The origin server responds with a Type 2 message.
1902 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1903 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291904 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241905 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1906 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1907 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1908 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1909 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1910 "BtAAAAAAA=\r\n"),
1911 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361912 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241913 MockRead("You are not authorized to view this page\r\n"),
1914
1915 // Lastly we get the desired content.
1916 MockRead("HTTP/1.1 200 OK\r\n"),
1917 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1918 MockRead("Content-Length: 13\r\n\r\n"),
1919 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421920 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241921 };
1922
[email protected]31a2bfe2010-02-09 08:03:391923 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1924 data_writes1, arraysize(data_writes1));
1925 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1926 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591927 session_deps.socket_factory.AddSocketDataProvider(&data1);
1928 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241929
1930 TestCompletionCallback callback1;
1931
[email protected]5a1d7ca2010-04-28 20:12:271932 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241934
1935 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421936 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241937
[email protected]0757e7702009-03-27 04:00:221938 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1939 TestCompletionCallback callback2;
1940 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421941 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221942 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421943 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221944 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1945
[email protected]1c773ea12009-04-28 19:58:421946 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241947 EXPECT_FALSE(response == NULL);
1948
1949 // The password prompt info should have been set in response->auth_challenge.
1950 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1951
[email protected]71e4573a2009-05-21 22:03:001952 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241953 EXPECT_EQ(L"", response->auth_challenge->realm);
1954 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1955
[email protected]0757e7702009-03-27 04:00:221956 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241957
[email protected]0757e7702009-03-27 04:00:221958 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421959 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241960
[email protected]0757e7702009-03-27 04:00:221961 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421962 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241963
1964 response = trans->GetResponseInfo();
1965 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1966 EXPECT_EQ(13, response->headers->GetContentLength());
1967}
1968
[email protected]385a4672009-03-11 22:21:291969// Enter a wrong password, and then the correct one.
1970TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421971 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111972 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591973 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401974 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431975 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291976
[email protected]1c773ea12009-04-28 19:58:421977 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291978 request.method = "GET";
1979 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1980 request.load_flags = 0;
1981
1982 MockWrite data_writes1[] = {
1983 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1984 "Host: 172.22.68.17\r\n"
1985 "Connection: keep-alive\r\n\r\n"),
1986 };
1987
1988 MockRead data_reads1[] = {
1989 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1990 // Negotiate and NTLM are often requested together. We only support NTLM.
1991 MockRead("WWW-Authenticate: Negotiate\r\n"),
1992 MockRead("WWW-Authenticate: NTLM\r\n"),
1993 MockRead("Connection: close\r\n"),
1994 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361995 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291996 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421997 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291998 };
1999
2000 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222001 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292002 // request we should be issuing -- the final header line contains a Type
2003 // 1 message.
2004 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2005 "Host: 172.22.68.17\r\n"
2006 "Connection: keep-alive\r\n"
2007 "Authorization: NTLM "
2008 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2009
2010 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2011 // (the credentials for the origin server). The second request continues
2012 // on the same connection.
2013 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2014 "Host: 172.22.68.17\r\n"
2015 "Connection: keep-alive\r\n"
2016 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2017 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2018 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2019 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2020 "4Ww7b7E=\r\n\r\n"),
2021 };
2022
2023 MockRead data_reads2[] = {
2024 // The origin server responds with a Type 2 message.
2025 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2026 MockRead("WWW-Authenticate: NTLM "
2027 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2028 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2029 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2030 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2031 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2032 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2033 "BtAAAAAAA=\r\n"),
2034 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362035 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292036 MockRead("You are not authorized to view this page\r\n"),
2037
2038 // Wrong password.
2039 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2040 MockRead("WWW-Authenticate: Negotiate\r\n"),
2041 MockRead("WWW-Authenticate: NTLM\r\n"),
2042 MockRead("Connection: close\r\n"),
2043 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362044 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292045 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422046 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292047 };
2048
2049 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222050 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292051 // request we should be issuing -- the final header line contains a Type
2052 // 1 message.
2053 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2054 "Host: 172.22.68.17\r\n"
2055 "Connection: keep-alive\r\n"
2056 "Authorization: NTLM "
2057 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2058
2059 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2060 // (the credentials for the origin server). The second request continues
2061 // on the same connection.
2062 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2063 "Host: 172.22.68.17\r\n"
2064 "Connection: keep-alive\r\n"
2065 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2066 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2067 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2068 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2069 "+4MUm7c=\r\n\r\n"),
2070 };
2071
2072 MockRead data_reads3[] = {
2073 // The origin server responds with a Type 2 message.
2074 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2075 MockRead("WWW-Authenticate: NTLM "
2076 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2077 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2078 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2079 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2080 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2081 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2082 "BtAAAAAAA=\r\n"),
2083 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362084 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292085 MockRead("You are not authorized to view this page\r\n"),
2086
2087 // Lastly we get the desired content.
2088 MockRead("HTTP/1.1 200 OK\r\n"),
2089 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2090 MockRead("Content-Length: 13\r\n\r\n"),
2091 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422092 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292093 };
2094
[email protected]31a2bfe2010-02-09 08:03:392095 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2096 data_writes1, arraysize(data_writes1));
2097 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2098 data_writes2, arraysize(data_writes2));
2099 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2100 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592101 session_deps.socket_factory.AddSocketDataProvider(&data1);
2102 session_deps.socket_factory.AddSocketDataProvider(&data2);
2103 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292104
2105 TestCompletionCallback callback1;
2106
[email protected]5a1d7ca2010-04-28 20:12:272107 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292109
2110 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422111 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292112
[email protected]0757e7702009-03-27 04:00:222113 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292114 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222115 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422116 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292117 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422118 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222119 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292120
[email protected]1c773ea12009-04-28 19:58:422121 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292122 EXPECT_FALSE(response == NULL);
2123
2124 // The password prompt info should have been set in response->auth_challenge.
2125 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2126
[email protected]71e4573a2009-05-21 22:03:002127 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292128 EXPECT_EQ(L"", response->auth_challenge->realm);
2129 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2130
2131 TestCompletionCallback callback3;
2132
[email protected]0757e7702009-03-27 04:00:222133 // Enter the wrong password.
2134 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422135 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292136
2137 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422138 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292139
[email protected]0757e7702009-03-27 04:00:222140 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2141 TestCompletionCallback callback4;
2142 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422143 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222144 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422145 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222146 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2147
2148 response = trans->GetResponseInfo();
2149 EXPECT_FALSE(response == NULL);
2150
2151 // The password prompt info should have been set in response->auth_challenge.
2152 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2153
[email protected]71e4573a2009-05-21 22:03:002154 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222155 EXPECT_EQ(L"", response->auth_challenge->realm);
2156 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2157
2158 TestCompletionCallback callback5;
2159
2160 // Now enter the right password.
2161 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422162 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222163
2164 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422165 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222166
[email protected]385a4672009-03-11 22:21:292167 response = trans->GetResponseInfo();
2168 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2169 EXPECT_EQ(13, response->headers->GetContentLength());
2170}
[email protected]ea9dc9a2009-09-05 00:43:322171#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292172
[email protected]4ddaf2502008-10-23 18:26:192173// Test reading a server response which has only headers, and no body.
2174// After some maximum number of bytes is consumed, the transaction should
2175// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2176TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592177 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402178 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432179 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192180
[email protected]1c773ea12009-04-28 19:58:422181 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192182 request.method = "GET";
2183 request.url = GURL("http://www.google.com/");
2184 request.load_flags = 0;
2185
[email protected]b75b7b2f2009-10-06 00:54:532186 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432187 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532188 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192189
2190 MockRead data_reads[] = {
2191 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432192 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192193 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422194 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192195 };
[email protected]31a2bfe2010-02-09 08:03:392196 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592197 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192198
2199 TestCompletionCallback callback;
2200
[email protected]5a1d7ca2010-04-28 20:12:272201 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422202 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192203
2204 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422205 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192206
[email protected]1c773ea12009-04-28 19:58:422207 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192208 EXPECT_TRUE(response == NULL);
2209}
[email protected]f4e426b2008-11-05 00:24:492210
2211// Make sure that we don't try to reuse a TCPClientSocket when failing to
2212// establish tunnel.
2213// http://code.google.com/p/chromium/issues/detail?id=3772
2214TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2215 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592216 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012217
[email protected]228ff742009-06-05 01:19:592218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492219
[email protected]5695b8c2009-09-30 21:36:432220 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492221
[email protected]1c773ea12009-04-28 19:58:422222 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492223 request.method = "GET";
2224 request.url = GURL("https://www.google.com/");
2225 request.load_flags = 0;
2226
2227 // Since we have proxy, should try to establish tunnel.
2228 MockWrite data_writes1[] = {
2229 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452230 "Host: www.google.com\r\n"
2231 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492232 };
2233
[email protected]77848d12008-11-14 00:00:222234 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492235 // connection. Usually a proxy would return 501 (not implemented),
2236 // or 200 (tunnel established).
2237 MockRead data_reads1[] = {
2238 MockRead("HTTP/1.1 404 Not Found\r\n"),
2239 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422240 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492241 };
2242
[email protected]31a2bfe2010-02-09 08:03:392243 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2244 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592245 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492246
2247 TestCompletionCallback callback1;
2248
[email protected]5a1d7ca2010-04-28 20:12:272249 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422250 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492251
2252 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422253 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492254
[email protected]1c773ea12009-04-28 19:58:422255 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082256 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492257
[email protected]b4404c02009-04-10 16:38:522258 // Empty the current queue. This is necessary because idle sockets are
2259 // added to the connection pool asynchronously with a PostTask.
2260 MessageLoop::current()->RunAllPending();
2261
[email protected]f4e426b2008-11-05 00:24:492262 // We now check to make sure the TCPClientSocket was not added back to
2263 // the pool.
[email protected]a937a06d2009-08-19 21:19:242264 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492265 trans.reset();
[email protected]b4404c02009-04-10 16:38:522266 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492267 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242268 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492269}
[email protected]372d34a2008-11-05 21:30:512270
[email protected]1b157c02009-04-21 01:55:402271// Make sure that we recycle a socket after reading all of the response body.
2272TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592273 SessionDependencies session_deps;
2274 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402275
[email protected]5695b8c2009-09-30 21:36:432276 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402277
[email protected]1c773ea12009-04-28 19:58:422278 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402279 request.method = "GET";
2280 request.url = GURL("http://www.google.com/");
2281 request.load_flags = 0;
2282
2283 MockRead data_reads[] = {
2284 // A part of the response body is received with the response headers.
2285 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2286 // The rest of the response body is received in two parts.
2287 MockRead("lo"),
2288 MockRead(" world"),
2289 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422290 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402291 };
2292
[email protected]31a2bfe2010-02-09 08:03:392293 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592294 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402295
2296 TestCompletionCallback callback;
2297
[email protected]5a1d7ca2010-04-28 20:12:272298 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422299 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402300
2301 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422302 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402303
[email protected]1c773ea12009-04-28 19:58:422304 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402305 EXPECT_TRUE(response != NULL);
2306
2307 EXPECT_TRUE(response->headers != NULL);
2308 std::string status_line = response->headers->GetStatusLine();
2309 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2310
[email protected]a937a06d2009-08-19 21:19:242311 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402312
2313 std::string response_data;
2314 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422315 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402316 EXPECT_EQ("hello world", response_data);
2317
2318 // Empty the current queue. This is necessary because idle sockets are
2319 // added to the connection pool asynchronously with a PostTask.
2320 MessageLoop::current()->RunAllPending();
2321
2322 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242323 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402324}
2325
[email protected]b4404c02009-04-10 16:38:522326// Make sure that we recycle a socket after a zero-length response.
2327// http://crbug.com/9880
2328TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592329 SessionDependencies session_deps;
2330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522331
[email protected]5695b8c2009-09-30 21:36:432332 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522333
[email protected]1c773ea12009-04-28 19:58:422334 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522335 request.method = "GET";
2336 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2337 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2338 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2339 "rt=prt.2642,ol.2649,xjs.2951");
2340 request.load_flags = 0;
2341
2342 MockRead data_reads[] = {
2343 MockRead("HTTP/1.1 204 No Content\r\n"
2344 "Content-Length: 0\r\n"
2345 "Content-Type: text/html\r\n\r\n"),
2346 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422347 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522348 };
2349
[email protected]31a2bfe2010-02-09 08:03:392350 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592351 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522352
2353 TestCompletionCallback callback;
2354
[email protected]5a1d7ca2010-04-28 20:12:272355 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422356 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522357
2358 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422359 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522360
[email protected]1c773ea12009-04-28 19:58:422361 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522362 EXPECT_TRUE(response != NULL);
2363
2364 EXPECT_TRUE(response->headers != NULL);
2365 std::string status_line = response->headers->GetStatusLine();
2366 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2367
[email protected]a937a06d2009-08-19 21:19:242368 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522369
2370 std::string response_data;
2371 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422372 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522373 EXPECT_EQ("", response_data);
2374
2375 // Empty the current queue. This is necessary because idle sockets are
2376 // added to the connection pool asynchronously with a PostTask.
2377 MessageLoop::current()->RunAllPending();
2378
2379 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242380 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522381}
2382
[email protected]372d34a2008-11-05 21:30:512383TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422384 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512385 // Transaction 1: a GET request that succeeds. The socket is recycled
2386 // after use.
2387 request[0].method = "GET";
2388 request[0].url = GURL("http://www.google.com/");
2389 request[0].load_flags = 0;
2390 // Transaction 2: a POST request. Reuses the socket kept alive from
2391 // transaction 1. The first attempts fails when writing the POST data.
2392 // This causes the transaction to retry with a new socket. The second
2393 // attempt succeeds.
2394 request[1].method = "POST";
2395 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422396 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512397 request[1].upload_data->AppendBytes("foo", 3);
2398 request[1].load_flags = 0;
2399
[email protected]228ff742009-06-05 01:19:592400 SessionDependencies session_deps;
2401 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512402
2403 // The first socket is used for transaction 1 and the first attempt of
2404 // transaction 2.
2405
2406 // The response of transaction 1.
2407 MockRead data_reads1[] = {
2408 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2409 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422410 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512411 };
2412 // The mock write results of transaction 1 and the first attempt of
2413 // transaction 2.
2414 MockWrite data_writes1[] = {
2415 MockWrite(false, 64), // GET
2416 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422417 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512418 };
[email protected]31a2bfe2010-02-09 08:03:392419 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2420 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512421
2422 // The second socket is used for the second attempt of transaction 2.
2423
2424 // The response of transaction 2.
2425 MockRead data_reads2[] = {
2426 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2427 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422428 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512429 };
2430 // The mock write results of the second attempt of transaction 2.
2431 MockWrite data_writes2[] = {
2432 MockWrite(false, 93), // POST
2433 MockWrite(false, 3), // POST data
2434 };
[email protected]31a2bfe2010-02-09 08:03:392435 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2436 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512437
[email protected]5ecc992a42009-11-11 01:41:592438 session_deps.socket_factory.AddSocketDataProvider(&data1);
2439 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512440
2441 const char* kExpectedResponseData[] = {
2442 "hello world", "welcome"
2443 };
2444
2445 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422446 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432447 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512448
2449 TestCompletionCallback callback;
2450
[email protected]5a1d7ca2010-04-28 20:12:272451 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422452 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512453
2454 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422455 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512456
[email protected]1c773ea12009-04-28 19:58:422457 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512458 EXPECT_TRUE(response != NULL);
2459
2460 EXPECT_TRUE(response->headers != NULL);
2461 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2462
2463 std::string response_data;
2464 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422465 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512466 EXPECT_EQ(kExpectedResponseData[i], response_data);
2467 }
2468}
[email protected]f9ee6b52008-11-08 06:46:232469
2470// Test the request-challenge-retry sequence for basic auth when there is
2471// an identity in the URL. The request should be sent as normal, but when
2472// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322473TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592474 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402475 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432476 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232477
[email protected]1c773ea12009-04-28 19:58:422478 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232479 request.method = "GET";
2480 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292481 request.url = GURL("http://foo:b@[email protected]/");
2482
2483 // The password contains an escaped character -- for this test to pass it
2484 // will need to be unescaped by HttpNetworkTransaction.
2485 EXPECT_EQ("b%40r", request.url.password());
2486
[email protected]ea9dc9a2009-09-05 00:43:322487 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232488
2489 MockWrite data_writes1[] = {
2490 MockWrite("GET / HTTP/1.1\r\n"
2491 "Host: www.google.com\r\n"
2492 "Connection: keep-alive\r\n\r\n"),
2493 };
2494
2495 MockRead data_reads1[] = {
2496 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2497 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2498 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422499 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232500 };
2501
2502 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322503 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232504 MockWrite data_writes2[] = {
2505 MockWrite("GET / HTTP/1.1\r\n"
2506 "Host: www.google.com\r\n"
2507 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292508 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232509 };
2510
2511 MockRead data_reads2[] = {
2512 MockRead("HTTP/1.0 200 OK\r\n"),
2513 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422514 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232515 };
2516
[email protected]31a2bfe2010-02-09 08:03:392517 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2518 data_writes1, arraysize(data_writes1));
2519 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2520 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592521 session_deps.socket_factory.AddSocketDataProvider(&data1);
2522 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232523
2524 TestCompletionCallback callback1;
2525
[email protected]5a1d7ca2010-04-28 20:12:272526 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422527 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232528
2529 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422530 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232531
[email protected]0757e7702009-03-27 04:00:222532 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2533 TestCompletionCallback callback2;
2534 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422535 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222536 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422537 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222538 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2539
[email protected]1c773ea12009-04-28 19:58:422540 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232541 EXPECT_FALSE(response == NULL);
2542
2543 // There is no challenge info, since the identity in URL worked.
2544 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2545
2546 EXPECT_EQ(100, response->headers->GetContentLength());
2547
2548 // Empty the current queue.
2549 MessageLoop::current()->RunAllPending();
2550}
2551
[email protected]ea9dc9a2009-09-05 00:43:322552// Test the request-challenge-retry sequence for basic auth when there is
2553// an incorrect identity in the URL. The identity from the URL should be used
2554// only once.
2555TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2556 SessionDependencies session_deps;
2557 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432558 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322559
2560 HttpRequestInfo request;
2561 request.method = "GET";
2562 // Note: the URL has a username:password in it. The password "baz" is
2563 // wrong (should be "bar").
2564 request.url = GURL("http://foo:[email protected]/");
2565
2566 request.load_flags = LOAD_NORMAL;
2567
2568 MockWrite data_writes1[] = {
2569 MockWrite("GET / HTTP/1.1\r\n"
2570 "Host: www.google.com\r\n"
2571 "Connection: keep-alive\r\n\r\n"),
2572 };
2573
2574 MockRead data_reads1[] = {
2575 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2576 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2577 MockRead("Content-Length: 10\r\n\r\n"),
2578 MockRead(false, ERR_FAILED),
2579 };
2580
2581 // After the challenge above, the transaction will be restarted using the
2582 // identity from the url (foo, baz) to answer the challenge.
2583 MockWrite data_writes2[] = {
2584 MockWrite("GET / HTTP/1.1\r\n"
2585 "Host: www.google.com\r\n"
2586 "Connection: keep-alive\r\n"
2587 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2588 };
2589
2590 MockRead data_reads2[] = {
2591 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2592 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2593 MockRead("Content-Length: 10\r\n\r\n"),
2594 MockRead(false, ERR_FAILED),
2595 };
2596
2597 // After the challenge above, the transaction will be restarted using the
2598 // identity supplied by the user (foo, bar) to answer the challenge.
2599 MockWrite data_writes3[] = {
2600 MockWrite("GET / HTTP/1.1\r\n"
2601 "Host: www.google.com\r\n"
2602 "Connection: keep-alive\r\n"
2603 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2604 };
2605
2606 MockRead data_reads3[] = {
2607 MockRead("HTTP/1.0 200 OK\r\n"),
2608 MockRead("Content-Length: 100\r\n\r\n"),
2609 MockRead(false, OK),
2610 };
2611
[email protected]31a2bfe2010-02-09 08:03:392612 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2613 data_writes1, arraysize(data_writes1));
2614 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2615 data_writes2, arraysize(data_writes2));
2616 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2617 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592618 session_deps.socket_factory.AddSocketDataProvider(&data1);
2619 session_deps.socket_factory.AddSocketDataProvider(&data2);
2620 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322621
2622 TestCompletionCallback callback1;
2623
[email protected]5a1d7ca2010-04-28 20:12:272624 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322625 EXPECT_EQ(ERR_IO_PENDING, rv);
2626
2627 rv = callback1.WaitForResult();
2628 EXPECT_EQ(OK, rv);
2629
2630 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2631 TestCompletionCallback callback2;
2632 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2633 EXPECT_EQ(ERR_IO_PENDING, rv);
2634 rv = callback2.WaitForResult();
2635 EXPECT_EQ(OK, rv);
2636 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2637
2638 const HttpResponseInfo* response = trans->GetResponseInfo();
2639 EXPECT_FALSE(response == NULL);
2640 // The password prompt info should have been set in response->auth_challenge.
2641 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2642
2643 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2644 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2645 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2646
2647 TestCompletionCallback callback3;
2648 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2649 EXPECT_EQ(ERR_IO_PENDING, rv);
2650 rv = callback3.WaitForResult();
2651 EXPECT_EQ(OK, rv);
2652 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2653
2654 response = trans->GetResponseInfo();
2655 EXPECT_FALSE(response == NULL);
2656
2657 // There is no challenge info, since the identity worked.
2658 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2659
2660 EXPECT_EQ(100, response->headers->GetContentLength());
2661
2662 // Empty the current queue.
2663 MessageLoop::current()->RunAllPending();
2664}
2665
[email protected]f9ee6b52008-11-08 06:46:232666// Test that previously tried username/passwords for a realm get re-used.
2667TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592668 SessionDependencies session_deps;
2669 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232670
2671 // Transaction 1: authenticate (foo, bar) on MyRealm1
2672 {
[email protected]5695b8c2009-09-30 21:36:432673 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232674
[email protected]1c773ea12009-04-28 19:58:422675 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232676 request.method = "GET";
2677 request.url = GURL("http://www.google.com/x/y/z");
2678 request.load_flags = 0;
2679
2680 MockWrite data_writes1[] = {
2681 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2682 "Host: www.google.com\r\n"
2683 "Connection: keep-alive\r\n\r\n"),
2684 };
2685
2686 MockRead data_reads1[] = {
2687 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2689 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422690 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232691 };
2692
2693 // Resend with authorization (username=foo, password=bar)
2694 MockWrite data_writes2[] = {
2695 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2696 "Host: www.google.com\r\n"
2697 "Connection: keep-alive\r\n"
2698 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2699 };
2700
2701 // Sever accepts the authorization.
2702 MockRead data_reads2[] = {
2703 MockRead("HTTP/1.0 200 OK\r\n"),
2704 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422705 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232706 };
2707
[email protected]31a2bfe2010-02-09 08:03:392708 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2709 data_writes1, arraysize(data_writes1));
2710 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2711 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592712 session_deps.socket_factory.AddSocketDataProvider(&data1);
2713 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232714
2715 TestCompletionCallback callback1;
2716
[email protected]5a1d7ca2010-04-28 20:12:272717 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422718 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232719
2720 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422721 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232722
[email protected]1c773ea12009-04-28 19:58:422723 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232724 EXPECT_FALSE(response == NULL);
2725
2726 // The password prompt info should have been set in
2727 // response->auth_challenge.
2728 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2729
[email protected]71e4573a2009-05-21 22:03:002730 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232731 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2732 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2733
2734 TestCompletionCallback callback2;
2735
2736 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422737 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232738
2739 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422740 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232741
2742 response = trans->GetResponseInfo();
2743 EXPECT_FALSE(response == NULL);
2744 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2745 EXPECT_EQ(100, response->headers->GetContentLength());
2746 }
2747
2748 // ------------------------------------------------------------------------
2749
2750 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2751 {
[email protected]5695b8c2009-09-30 21:36:432752 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232753
[email protected]1c773ea12009-04-28 19:58:422754 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232755 request.method = "GET";
2756 // Note that Transaction 1 was at /x/y/z, so this is in the same
2757 // protection space as MyRealm1.
2758 request.url = GURL("http://www.google.com/x/y/a/b");
2759 request.load_flags = 0;
2760
2761 MockWrite data_writes1[] = {
2762 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2763 "Host: www.google.com\r\n"
2764 "Connection: keep-alive\r\n"
2765 // Send preemptive authorization for MyRealm1
2766 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2767 };
2768
2769 // The server didn't like the preemptive authorization, and
2770 // challenges us for a different realm (MyRealm2).
2771 MockRead data_reads1[] = {
2772 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2773 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2774 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422775 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232776 };
2777
2778 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2779 MockWrite data_writes2[] = {
2780 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2781 "Host: www.google.com\r\n"
2782 "Connection: keep-alive\r\n"
2783 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2784 };
2785
2786 // Sever accepts the authorization.
2787 MockRead data_reads2[] = {
2788 MockRead("HTTP/1.0 200 OK\r\n"),
2789 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422790 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232791 };
2792
[email protected]31a2bfe2010-02-09 08:03:392793 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2794 data_writes1, arraysize(data_writes1));
2795 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2796 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592797 session_deps.socket_factory.AddSocketDataProvider(&data1);
2798 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232799
2800 TestCompletionCallback callback1;
2801
[email protected]5a1d7ca2010-04-28 20:12:272802 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422803 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232804
2805 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422806 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232807
[email protected]1c773ea12009-04-28 19:58:422808 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232809 EXPECT_FALSE(response == NULL);
2810
2811 // The password prompt info should have been set in
2812 // response->auth_challenge.
2813 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2814
[email protected]71e4573a2009-05-21 22:03:002815 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232816 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2817 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2818
2819 TestCompletionCallback callback2;
2820
2821 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422822 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232823
2824 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422825 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232826
2827 response = trans->GetResponseInfo();
2828 EXPECT_FALSE(response == NULL);
2829 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2830 EXPECT_EQ(100, response->headers->GetContentLength());
2831 }
2832
2833 // ------------------------------------------------------------------------
2834
2835 // Transaction 3: Resend a request in MyRealm's protection space --
2836 // succeed with preemptive authorization.
2837 {
[email protected]5695b8c2009-09-30 21:36:432838 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232839
[email protected]1c773ea12009-04-28 19:58:422840 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232841 request.method = "GET";
2842 request.url = GURL("http://www.google.com/x/y/z2");
2843 request.load_flags = 0;
2844
2845 MockWrite data_writes1[] = {
2846 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2847 "Host: www.google.com\r\n"
2848 "Connection: keep-alive\r\n"
2849 // The authorization for MyRealm1 gets sent preemptively
2850 // (since the url is in the same protection space)
2851 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2852 };
2853
2854 // Sever accepts the preemptive authorization
2855 MockRead data_reads1[] = {
2856 MockRead("HTTP/1.0 200 OK\r\n"),
2857 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422858 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232859 };
2860
[email protected]31a2bfe2010-02-09 08:03:392861 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2862 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592863 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232864
2865 TestCompletionCallback callback1;
2866
[email protected]5a1d7ca2010-04-28 20:12:272867 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422868 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232869
2870 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422871 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232872
[email protected]1c773ea12009-04-28 19:58:422873 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232874 EXPECT_FALSE(response == NULL);
2875
2876 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2877 EXPECT_EQ(100, response->headers->GetContentLength());
2878 }
2879
2880 // ------------------------------------------------------------------------
2881
2882 // Transaction 4: request another URL in MyRealm (however the
2883 // url is not known to belong to the protection space, so no pre-auth).
2884 {
[email protected]5695b8c2009-09-30 21:36:432885 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232886
[email protected]1c773ea12009-04-28 19:58:422887 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232888 request.method = "GET";
2889 request.url = GURL("http://www.google.com/x/1");
2890 request.load_flags = 0;
2891
2892 MockWrite data_writes1[] = {
2893 MockWrite("GET /x/1 HTTP/1.1\r\n"
2894 "Host: www.google.com\r\n"
2895 "Connection: keep-alive\r\n\r\n"),
2896 };
2897
2898 MockRead data_reads1[] = {
2899 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2900 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2901 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422902 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232903 };
2904
2905 // Resend with authorization from MyRealm's cache.
2906 MockWrite data_writes2[] = {
2907 MockWrite("GET /x/1 HTTP/1.1\r\n"
2908 "Host: www.google.com\r\n"
2909 "Connection: keep-alive\r\n"
2910 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2911 };
2912
2913 // Sever accepts the authorization.
2914 MockRead data_reads2[] = {
2915 MockRead("HTTP/1.0 200 OK\r\n"),
2916 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422917 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232918 };
2919
[email protected]31a2bfe2010-02-09 08:03:392920 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2921 data_writes1, arraysize(data_writes1));
2922 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2923 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592924 session_deps.socket_factory.AddSocketDataProvider(&data1);
2925 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232926
2927 TestCompletionCallback callback1;
2928
[email protected]5a1d7ca2010-04-28 20:12:272929 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422930 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232931
2932 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422933 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232934
[email protected]0757e7702009-03-27 04:00:222935 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2936 TestCompletionCallback callback2;
2937 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422938 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222939 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422940 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222941 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2942
[email protected]1c773ea12009-04-28 19:58:422943 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232944 EXPECT_FALSE(response == NULL);
2945 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2946 EXPECT_EQ(100, response->headers->GetContentLength());
2947 }
2948
2949 // ------------------------------------------------------------------------
2950
2951 // Transaction 5: request a URL in MyRealm, but the server rejects the
2952 // cached identity. Should invalidate and re-prompt.
2953 {
[email protected]5695b8c2009-09-30 21:36:432954 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232955
[email protected]1c773ea12009-04-28 19:58:422956 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232957 request.method = "GET";
2958 request.url = GURL("http://www.google.com/p/q/t");
2959 request.load_flags = 0;
2960
2961 MockWrite data_writes1[] = {
2962 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2963 "Host: www.google.com\r\n"
2964 "Connection: keep-alive\r\n\r\n"),
2965 };
2966
2967 MockRead data_reads1[] = {
2968 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2969 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2970 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422971 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232972 };
2973
2974 // Resend with authorization from cache for MyRealm.
2975 MockWrite data_writes2[] = {
2976 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2977 "Host: www.google.com\r\n"
2978 "Connection: keep-alive\r\n"
2979 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2980 };
2981
2982 // Sever rejects the authorization.
2983 MockRead data_reads2[] = {
2984 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2985 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2986 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422987 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232988 };
2989
2990 // At this point we should prompt for new credentials for MyRealm.
2991 // Restart with username=foo3, password=foo4.
2992 MockWrite data_writes3[] = {
2993 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2994 "Host: www.google.com\r\n"
2995 "Connection: keep-alive\r\n"
2996 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2997 };
2998
2999 // Sever accepts the authorization.
3000 MockRead data_reads3[] = {
3001 MockRead("HTTP/1.0 200 OK\r\n"),
3002 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423003 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233004 };
3005
[email protected]31a2bfe2010-02-09 08:03:393006 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3007 data_writes1, arraysize(data_writes1));
3008 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3009 data_writes2, arraysize(data_writes2));
3010 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3011 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593012 session_deps.socket_factory.AddSocketDataProvider(&data1);
3013 session_deps.socket_factory.AddSocketDataProvider(&data2);
3014 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233015
3016 TestCompletionCallback callback1;
3017
[email protected]5a1d7ca2010-04-28 20:12:273018 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423019 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233020
3021 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423022 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233023
[email protected]0757e7702009-03-27 04:00:223024 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3025 TestCompletionCallback callback2;
3026 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223028 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423029 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223030 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3031
[email protected]1c773ea12009-04-28 19:58:423032 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233033 EXPECT_FALSE(response == NULL);
3034
3035 // The password prompt info should have been set in
3036 // response->auth_challenge.
3037 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3038
[email protected]71e4573a2009-05-21 22:03:003039 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233040 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3041 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3042
[email protected]0757e7702009-03-27 04:00:223043 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233044
[email protected]0757e7702009-03-27 04:00:223045 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:423046 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233047
[email protected]0757e7702009-03-27 04:00:223048 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423049 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233050
3051 response = trans->GetResponseInfo();
3052 EXPECT_FALSE(response == NULL);
3053 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3054 EXPECT_EQ(100, response->headers->GetContentLength());
3055 }
3056}
[email protected]89ceba9a2009-03-21 03:46:063057
[email protected]3c32c5f2010-05-18 15:18:123058// Tests that nonce count increments when multiple auth attempts
3059// are started with the same nonce.
3060TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3061 SessionDependencies session_deps;
3062 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3063 HttpAuthHandlerDigest::SetFixedCnonce(true);
3064
3065 // Transaction 1: authenticate (foo, bar) on MyRealm1
3066 {
3067 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3068
3069 HttpRequestInfo request;
3070 request.method = "GET";
3071 request.url = GURL("http://www.google.com/x/y/z");
3072 request.load_flags = 0;
3073
3074 MockWrite data_writes1[] = {
3075 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3076 "Host: www.google.com\r\n"
3077 "Connection: keep-alive\r\n\r\n"),
3078 };
3079
3080 MockRead data_reads1[] = {
3081 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3082 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3083 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3084 MockRead(false, OK),
3085 };
3086
3087 // Resend with authorization (username=foo, password=bar)
3088 MockWrite data_writes2[] = {
3089 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3090 "Host: www.google.com\r\n"
3091 "Connection: keep-alive\r\n"
3092 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3093 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3094 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3095 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3096 };
3097
3098 // Sever accepts the authorization.
3099 MockRead data_reads2[] = {
3100 MockRead("HTTP/1.0 200 OK\r\n"),
3101 MockRead(false, OK),
3102 };
3103
3104 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3105 data_writes1, arraysize(data_writes1));
3106 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3107 data_writes2, arraysize(data_writes2));
3108 session_deps.socket_factory.AddSocketDataProvider(&data1);
3109 session_deps.socket_factory.AddSocketDataProvider(&data2);
3110
3111 TestCompletionCallback callback1;
3112
3113 int rv = trans->Start(&request, &callback1, BoundNetLog());
3114 EXPECT_EQ(ERR_IO_PENDING, rv);
3115
3116 rv = callback1.WaitForResult();
3117 EXPECT_EQ(OK, rv);
3118
3119 const HttpResponseInfo* response = trans->GetResponseInfo();
3120 ASSERT_FALSE(response == NULL);
3121
3122 // The password prompt info should have been set in
3123 // response->auth_challenge.
3124 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3125
3126 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3127 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3128 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3129
3130 TestCompletionCallback callback2;
3131
3132 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3133 EXPECT_EQ(ERR_IO_PENDING, rv);
3134
3135 rv = callback2.WaitForResult();
3136 EXPECT_EQ(OK, rv);
3137
3138 response = trans->GetResponseInfo();
3139 ASSERT_FALSE(response == NULL);
3140 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3141 }
3142
3143 // ------------------------------------------------------------------------
3144
3145 // Transaction 2: Request another resource in digestive's protection space.
3146 // This will preemptively add an Authorization header which should have an
3147 // "nc" value of 2 (as compared to 1 in the first use.
3148 {
3149 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3150
3151 HttpRequestInfo request;
3152 request.method = "GET";
3153 // Note that Transaction 1 was at /x/y/z, so this is in the same
3154 // protection space as digest.
3155 request.url = GURL("http://www.google.com/x/y/a/b");
3156 request.load_flags = 0;
3157
3158 MockWrite data_writes1[] = {
3159 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3160 "Host: www.google.com\r\n"
3161 "Connection: keep-alive\r\n"
3162 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3163 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3164 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3165 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3166 };
3167
3168 // Sever accepts the authorization.
3169 MockRead data_reads1[] = {
3170 MockRead("HTTP/1.0 200 OK\r\n"),
3171 MockRead("Content-Length: 100\r\n\r\n"),
3172 MockRead(false, OK),
3173 };
3174
3175 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3176 data_writes1, arraysize(data_writes1));
3177 session_deps.socket_factory.AddSocketDataProvider(&data1);
3178
3179 TestCompletionCallback callback1;
3180
3181 int rv = trans->Start(&request, &callback1, BoundNetLog());
3182 EXPECT_EQ(ERR_IO_PENDING, rv);
3183
3184 rv = callback1.WaitForResult();
3185 EXPECT_EQ(OK, rv);
3186
3187 const HttpResponseInfo* response = trans->GetResponseInfo();
3188 ASSERT_FALSE(response == NULL);
3189 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3190 }
3191}
3192
[email protected]89ceba9a2009-03-21 03:46:063193// Test the ResetStateForRestart() private method.
3194TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3195 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593196 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403197 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433198 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063199
3200 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063201 trans->read_buf_ = new IOBuffer(15);
3202 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573203 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063204
3205 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143206 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573207 response->auth_challenge = new AuthChallengeInfo();
3208 response->ssl_info.cert_status = -15;
3209 response->response_time = base::Time::Now();
3210 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063211
3212 { // Setup state for response_.vary_data
3213 HttpRequestInfo request;
3214 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3215 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573216 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433217 request.extra_headers.SetHeader("Foo", "1");
3218 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573219 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063220 }
3221
3222 // Cause the above state to be reset.
3223 trans->ResetStateForRestart();
3224
3225 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073226 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063227 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573228 EXPECT_EQ(0U, trans->request_headers_.size());
3229 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3230 EXPECT_TRUE(response->headers.get() == NULL);
3231 EXPECT_EQ(false, response->was_cached);
3232 EXPECT_EQ(0, response->ssl_info.cert_status);
3233 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063234}
3235
[email protected]bacff652009-03-31 17:50:333236// Test HTTPS connections to a site with a bad certificate
3237TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593238 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403239 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433240 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333241
3242 HttpRequestInfo request;
3243 request.method = "GET";
3244 request.url = GURL("https://www.google.com/");
3245 request.load_flags = 0;
3246
3247 MockWrite data_writes[] = {
3248 MockWrite("GET / HTTP/1.1\r\n"
3249 "Host: www.google.com\r\n"
3250 "Connection: keep-alive\r\n\r\n"),
3251 };
3252
3253 MockRead data_reads[] = {
3254 MockRead("HTTP/1.0 200 OK\r\n"),
3255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3256 MockRead("Content-Length: 100\r\n\r\n"),
3257 MockRead(false, OK),
3258 };
3259
[email protected]5ecc992a42009-11-11 01:41:593260 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393261 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3262 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593263 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3264 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333265
[email protected]5ecc992a42009-11-11 01:41:593266 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3267 session_deps.socket_factory.AddSocketDataProvider(&data);
3268 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3269 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333270
3271 TestCompletionCallback callback;
3272
[email protected]5a1d7ca2010-04-28 20:12:273273 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333274 EXPECT_EQ(ERR_IO_PENDING, rv);
3275
3276 rv = callback.WaitForResult();
3277 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3278
3279 rv = trans->RestartIgnoringLastError(&callback);
3280 EXPECT_EQ(ERR_IO_PENDING, rv);
3281
3282 rv = callback.WaitForResult();
3283 EXPECT_EQ(OK, rv);
3284
3285 const HttpResponseInfo* response = trans->GetResponseInfo();
3286
3287 EXPECT_FALSE(response == NULL);
3288 EXPECT_EQ(100, response->headers->GetContentLength());
3289}
3290
3291// Test HTTPS connections to a site with a bad certificate, going through a
3292// proxy
3293TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593294 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333295
3296 HttpRequestInfo request;
3297 request.method = "GET";
3298 request.url = GURL("https://www.google.com/");
3299 request.load_flags = 0;
3300
3301 MockWrite proxy_writes[] = {
3302 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453303 "Host: www.google.com\r\n"
3304 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333305 };
3306
3307 MockRead proxy_reads[] = {
3308 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423309 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333310 };
3311
3312 MockWrite data_writes[] = {
3313 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453314 "Host: www.google.com\r\n"
3315 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333316 MockWrite("GET / HTTP/1.1\r\n"
3317 "Host: www.google.com\r\n"
3318 "Connection: keep-alive\r\n\r\n"),
3319 };
3320
3321 MockRead data_reads[] = {
3322 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3323 MockRead("HTTP/1.0 200 OK\r\n"),
3324 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3325 MockRead("Content-Length: 100\r\n\r\n"),
3326 MockRead(false, OK),
3327 };
3328
[email protected]31a2bfe2010-02-09 08:03:393329 StaticSocketDataProvider ssl_bad_certificate(
3330 proxy_reads, arraysize(proxy_reads),
3331 proxy_writes, arraysize(proxy_writes));
3332 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3333 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593334 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3335 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333336
[email protected]5ecc992a42009-11-11 01:41:593337 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3338 session_deps.socket_factory.AddSocketDataProvider(&data);
3339 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3340 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333341
3342 TestCompletionCallback callback;
3343
3344 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593345 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333346
[email protected]d207a5f2009-06-04 05:28:403347 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433348 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333349
[email protected]5a1d7ca2010-04-28 20:12:273350 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333351 EXPECT_EQ(ERR_IO_PENDING, rv);
3352
3353 rv = callback.WaitForResult();
3354 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3355
3356 rv = trans->RestartIgnoringLastError(&callback);
3357 EXPECT_EQ(ERR_IO_PENDING, rv);
3358
3359 rv = callback.WaitForResult();
3360 EXPECT_EQ(OK, rv);
3361
3362 const HttpResponseInfo* response = trans->GetResponseInfo();
3363
3364 EXPECT_FALSE(response == NULL);
3365 EXPECT_EQ(100, response->headers->GetContentLength());
3366 }
3367}
3368
[email protected]1c773ea12009-04-28 19:58:423369TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593370 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403371 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433372 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423373
3374 HttpRequestInfo request;
3375 request.method = "GET";
3376 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433377 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3378 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423379
3380 MockWrite data_writes[] = {
3381 MockWrite("GET / HTTP/1.1\r\n"
3382 "Host: www.google.com\r\n"
3383 "Connection: keep-alive\r\n"
3384 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3385 };
3386
3387 // Lastly, the server responds with the actual content.
3388 MockRead data_reads[] = {
3389 MockRead("HTTP/1.0 200 OK\r\n"),
3390 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3391 MockRead("Content-Length: 100\r\n\r\n"),
3392 MockRead(false, OK),
3393 };
3394
[email protected]31a2bfe2010-02-09 08:03:393395 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3396 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593397 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423398
3399 TestCompletionCallback callback;
3400
[email protected]5a1d7ca2010-04-28 20:12:273401 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423402 EXPECT_EQ(ERR_IO_PENDING, rv);
3403
3404 rv = callback.WaitForResult();
3405 EXPECT_EQ(OK, rv);
3406}
3407
3408TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593409 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403410 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433411 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423412
3413 HttpRequestInfo request;
3414 request.method = "GET";
3415 request.url = GURL("http://www.google.com/");
3416 request.load_flags = 0;
3417 request.referrer = GURL("http://the.previous.site.com/");
3418
3419 MockWrite data_writes[] = {
3420 MockWrite("GET / HTTP/1.1\r\n"
3421 "Host: www.google.com\r\n"
3422 "Connection: keep-alive\r\n"
3423 "Referer: http://the.previous.site.com/\r\n\r\n"),
3424 };
3425
3426 // Lastly, the server responds with the actual content.
3427 MockRead data_reads[] = {
3428 MockRead("HTTP/1.0 200 OK\r\n"),
3429 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3430 MockRead("Content-Length: 100\r\n\r\n"),
3431 MockRead(false, OK),
3432 };
3433
[email protected]31a2bfe2010-02-09 08:03:393434 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3435 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593436 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423437
3438 TestCompletionCallback callback;
3439
[email protected]5a1d7ca2010-04-28 20:12:273440 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423441 EXPECT_EQ(ERR_IO_PENDING, rv);
3442
3443 rv = callback.WaitForResult();
3444 EXPECT_EQ(OK, rv);
3445}
3446
3447TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593448 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403449 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433450 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423451
3452 HttpRequestInfo request;
3453 request.method = "POST";
3454 request.url = GURL("http://www.google.com/");
3455
3456 MockWrite data_writes[] = {
3457 MockWrite("POST / HTTP/1.1\r\n"
3458 "Host: www.google.com\r\n"
3459 "Connection: keep-alive\r\n"
3460 "Content-Length: 0\r\n\r\n"),
3461 };
3462
3463 // Lastly, the server responds with the actual content.
3464 MockRead data_reads[] = {
3465 MockRead("HTTP/1.0 200 OK\r\n"),
3466 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3467 MockRead("Content-Length: 100\r\n\r\n"),
3468 MockRead(false, OK),
3469 };
3470
[email protected]31a2bfe2010-02-09 08:03:393471 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3472 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593473 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423474
3475 TestCompletionCallback callback;
3476
[email protected]5a1d7ca2010-04-28 20:12:273477 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423478 EXPECT_EQ(ERR_IO_PENDING, rv);
3479
3480 rv = callback.WaitForResult();
3481 EXPECT_EQ(OK, rv);
3482}
3483
3484TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593485 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403486 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433487 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423488
3489 HttpRequestInfo request;
3490 request.method = "PUT";
3491 request.url = GURL("http://www.google.com/");
3492
3493 MockWrite data_writes[] = {
3494 MockWrite("PUT / HTTP/1.1\r\n"
3495 "Host: www.google.com\r\n"
3496 "Connection: keep-alive\r\n"
3497 "Content-Length: 0\r\n\r\n"),
3498 };
3499
3500 // Lastly, the server responds with the actual content.
3501 MockRead data_reads[] = {
3502 MockRead("HTTP/1.0 200 OK\r\n"),
3503 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3504 MockRead("Content-Length: 100\r\n\r\n"),
3505 MockRead(false, OK),
3506 };
3507
[email protected]31a2bfe2010-02-09 08:03:393508 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3509 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593510 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423511
3512 TestCompletionCallback callback;
3513
[email protected]5a1d7ca2010-04-28 20:12:273514 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423515 EXPECT_EQ(ERR_IO_PENDING, rv);
3516
3517 rv = callback.WaitForResult();
3518 EXPECT_EQ(OK, rv);
3519}
3520
3521TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593522 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403523 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433524 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423525
3526 HttpRequestInfo request;
3527 request.method = "HEAD";
3528 request.url = GURL("http://www.google.com/");
3529
3530 MockWrite data_writes[] = {
3531 MockWrite("HEAD / HTTP/1.1\r\n"
3532 "Host: www.google.com\r\n"
3533 "Connection: keep-alive\r\n"
3534 "Content-Length: 0\r\n\r\n"),
3535 };
3536
3537 // Lastly, the server responds with the actual content.
3538 MockRead data_reads[] = {
3539 MockRead("HTTP/1.0 200 OK\r\n"),
3540 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3541 MockRead("Content-Length: 100\r\n\r\n"),
3542 MockRead(false, OK),
3543 };
3544
[email protected]31a2bfe2010-02-09 08:03:393545 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3546 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593547 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423548
3549 TestCompletionCallback callback;
3550
[email protected]5a1d7ca2010-04-28 20:12:273551 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423552 EXPECT_EQ(ERR_IO_PENDING, rv);
3553
3554 rv = callback.WaitForResult();
3555 EXPECT_EQ(OK, rv);
3556}
3557
3558TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593559 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403560 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433561 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423562
3563 HttpRequestInfo request;
3564 request.method = "GET";
3565 request.url = GURL("http://www.google.com/");
3566 request.load_flags = LOAD_BYPASS_CACHE;
3567
3568 MockWrite data_writes[] = {
3569 MockWrite("GET / HTTP/1.1\r\n"
3570 "Host: www.google.com\r\n"
3571 "Connection: keep-alive\r\n"
3572 "Pragma: no-cache\r\n"
3573 "Cache-Control: no-cache\r\n\r\n"),
3574 };
3575
3576 // Lastly, the server responds with the actual content.
3577 MockRead data_reads[] = {
3578 MockRead("HTTP/1.0 200 OK\r\n"),
3579 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3580 MockRead("Content-Length: 100\r\n\r\n"),
3581 MockRead(false, OK),
3582 };
3583
[email protected]31a2bfe2010-02-09 08:03:393584 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3585 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593586 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423587
3588 TestCompletionCallback callback;
3589
[email protected]5a1d7ca2010-04-28 20:12:273590 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423591 EXPECT_EQ(ERR_IO_PENDING, rv);
3592
3593 rv = callback.WaitForResult();
3594 EXPECT_EQ(OK, rv);
3595}
3596
3597TEST_F(HttpNetworkTransactionTest,
3598 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593599 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403600 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433601 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423602
3603 HttpRequestInfo request;
3604 request.method = "GET";
3605 request.url = GURL("http://www.google.com/");
3606 request.load_flags = LOAD_VALIDATE_CACHE;
3607
3608 MockWrite data_writes[] = {
3609 MockWrite("GET / HTTP/1.1\r\n"
3610 "Host: www.google.com\r\n"
3611 "Connection: keep-alive\r\n"
3612 "Cache-Control: max-age=0\r\n\r\n"),
3613 };
3614
3615 // Lastly, the server responds with the actual content.
3616 MockRead data_reads[] = {
3617 MockRead("HTTP/1.0 200 OK\r\n"),
3618 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3619 MockRead("Content-Length: 100\r\n\r\n"),
3620 MockRead(false, OK),
3621 };
3622
[email protected]31a2bfe2010-02-09 08:03:393623 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3624 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593625 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423626
3627 TestCompletionCallback callback;
3628
[email protected]5a1d7ca2010-04-28 20:12:273629 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423630 EXPECT_EQ(ERR_IO_PENDING, rv);
3631
3632 rv = callback.WaitForResult();
3633 EXPECT_EQ(OK, rv);
3634}
3635
3636TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593637 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403638 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433639 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423640
3641 HttpRequestInfo request;
3642 request.method = "GET";
3643 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433644 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423645
3646 MockWrite data_writes[] = {
3647 MockWrite("GET / HTTP/1.1\r\n"
3648 "Host: www.google.com\r\n"
3649 "Connection: keep-alive\r\n"
3650 "FooHeader: Bar\r\n\r\n"),
3651 };
3652
3653 // Lastly, the server responds with the actual content.
3654 MockRead data_reads[] = {
3655 MockRead("HTTP/1.0 200 OK\r\n"),
3656 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3657 MockRead("Content-Length: 100\r\n\r\n"),
3658 MockRead(false, OK),
3659 };
3660
[email protected]31a2bfe2010-02-09 08:03:393661 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3662 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593663 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423664
3665 TestCompletionCallback callback;
3666
[email protected]5a1d7ca2010-04-28 20:12:273667 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423668 EXPECT_EQ(ERR_IO_PENDING, rv);
3669
3670 rv = callback.WaitForResult();
3671 EXPECT_EQ(OK, rv);
3672}
3673
[email protected]270c6412010-03-29 22:02:473674TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3675 SessionDependencies session_deps;
3676 scoped_ptr<HttpTransaction> trans(
3677 new HttpNetworkTransaction(CreateSession(&session_deps)));
3678
3679 HttpRequestInfo request;
3680 request.method = "GET";
3681 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433682 request.extra_headers.SetHeader("referer", "www.foo.com");
3683 request.extra_headers.SetHeader("hEllo", "Kitty");
3684 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473685
3686 MockWrite data_writes[] = {
3687 MockWrite("GET / HTTP/1.1\r\n"
3688 "Host: www.google.com\r\n"
3689 "Connection: keep-alive\r\n"
3690 "hEllo: Kitty\r\n"
3691 "FoO: bar\r\n\r\n"),
3692 };
3693
3694 // Lastly, the server responds with the actual content.
3695 MockRead data_reads[] = {
3696 MockRead("HTTP/1.0 200 OK\r\n"),
3697 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3698 MockRead("Content-Length: 100\r\n\r\n"),
3699 MockRead(false, OK),
3700 };
3701
3702 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3703 data_writes, arraysize(data_writes));
3704 session_deps.socket_factory.AddSocketDataProvider(&data);
3705
3706 TestCompletionCallback callback;
3707
[email protected]5a1d7ca2010-04-28 20:12:273708 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473709 EXPECT_EQ(ERR_IO_PENDING, rv);
3710
3711 rv = callback.WaitForResult();
3712 EXPECT_EQ(OK, rv);
3713}
3714
[email protected]3cd17242009-06-23 02:59:023715TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093716 SessionDependencies session_deps(
3717 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023718
3719 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433720 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023721
3722 HttpRequestInfo request;
3723 request.method = "GET";
3724 request.url = GURL("http://www.google.com/");
3725 request.load_flags = 0;
3726
3727 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3728 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3729
3730 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353731 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023732 MockWrite("GET / HTTP/1.1\r\n"
3733 "Host: www.google.com\r\n"
3734 "Connection: keep-alive\r\n\r\n")
3735 };
3736
3737 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593738 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023739 MockRead("HTTP/1.0 200 OK\r\n"),
3740 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3741 MockRead("Payload"),
3742 MockRead(false, OK)
3743 };
3744
[email protected]31a2bfe2010-02-09 08:03:393745 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3746 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593747 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023748
3749 TestCompletionCallback callback;
3750
[email protected]5a1d7ca2010-04-28 20:12:273751 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023752 EXPECT_EQ(ERR_IO_PENDING, rv);
3753
3754 rv = callback.WaitForResult();
3755 EXPECT_EQ(OK, rv);
3756
3757 const HttpResponseInfo* response = trans->GetResponseInfo();
3758 EXPECT_FALSE(response == NULL);
3759
3760 std::string response_text;
3761 rv = ReadTransaction(trans.get(), &response_text);
3762 EXPECT_EQ(OK, rv);
3763 EXPECT_EQ("Payload", response_text);
3764}
3765
3766TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093767 SessionDependencies session_deps(
3768 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023769
3770 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433771 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023772
3773 HttpRequestInfo request;
3774 request.method = "GET";
3775 request.url = GURL("https://www.google.com/");
3776 request.load_flags = 0;
3777
3778 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3779 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3780
3781 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353782 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3783 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023784 MockWrite("GET / HTTP/1.1\r\n"
3785 "Host: www.google.com\r\n"
3786 "Connection: keep-alive\r\n\r\n")
3787 };
3788
3789 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353790 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3791 arraysize(read_buffer)),
3792 MockRead("HTTP/1.0 200 OK\r\n"),
3793 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3794 MockRead("Payload"),
3795 MockRead(false, OK)
3796 };
3797
[email protected]31a2bfe2010-02-09 08:03:393798 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3799 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593800 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353801
[email protected]5ecc992a42009-11-11 01:41:593802 SSLSocketDataProvider ssl(true, OK);
3803 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353804
3805 TestCompletionCallback callback;
3806
[email protected]5a1d7ca2010-04-28 20:12:273807 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353808 EXPECT_EQ(ERR_IO_PENDING, rv);
3809
3810 rv = callback.WaitForResult();
3811 EXPECT_EQ(OK, rv);
3812
3813 const HttpResponseInfo* response = trans->GetResponseInfo();
3814 EXPECT_FALSE(response == NULL);
3815
3816 std::string response_text;
3817 rv = ReadTransaction(trans.get(), &response_text);
3818 EXPECT_EQ(OK, rv);
3819 EXPECT_EQ("Payload", response_text);
3820}
3821
3822TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093823 SessionDependencies session_deps(
3824 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353825
3826 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433827 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353828
3829 HttpRequestInfo request;
3830 request.method = "GET";
3831 request.url = GURL("http://www.google.com/");
3832 request.load_flags = 0;
3833
3834 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3835 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373836 const char kSOCKS5OkRequest[] = {
3837 0x05, // Version
3838 0x01, // Command (CONNECT)
3839 0x00, // Reserved.
3840 0x03, // Address type (DOMAINNAME).
3841 0x0E, // Length of domain (14)
3842 // Domain string:
3843 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3844 0x00, 0x50, // 16-bit port (80)
3845 };
[email protected]e0c27be2009-07-15 13:09:353846 const char kSOCKS5OkResponse[] =
3847 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3848
3849 MockWrite data_writes[] = {
3850 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3851 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3852 MockWrite("GET / HTTP/1.1\r\n"
3853 "Host: www.google.com\r\n"
3854 "Connection: keep-alive\r\n\r\n")
3855 };
3856
3857 MockRead data_reads[] = {
3858 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3859 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3860 MockRead("HTTP/1.0 200 OK\r\n"),
3861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3862 MockRead("Payload"),
3863 MockRead(false, OK)
3864 };
3865
[email protected]31a2bfe2010-02-09 08:03:393866 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3867 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593868 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353869
3870 TestCompletionCallback callback;
3871
[email protected]5a1d7ca2010-04-28 20:12:273872 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353873 EXPECT_EQ(ERR_IO_PENDING, rv);
3874
3875 rv = callback.WaitForResult();
3876 EXPECT_EQ(OK, rv);
3877
3878 const HttpResponseInfo* response = trans->GetResponseInfo();
3879 EXPECT_FALSE(response == NULL);
3880
3881 std::string response_text;
3882 rv = ReadTransaction(trans.get(), &response_text);
3883 EXPECT_EQ(OK, rv);
3884 EXPECT_EQ("Payload", response_text);
3885}
3886
3887TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093888 SessionDependencies session_deps(
3889 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353890
3891 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433892 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353893
3894 HttpRequestInfo request;
3895 request.method = "GET";
3896 request.url = GURL("https://www.google.com/");
3897 request.load_flags = 0;
3898
3899 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3900 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373901 const unsigned char kSOCKS5OkRequest[] = {
3902 0x05, // Version
3903 0x01, // Command (CONNECT)
3904 0x00, // Reserved.
3905 0x03, // Address type (DOMAINNAME).
3906 0x0E, // Length of domain (14)
3907 // Domain string:
3908 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3909 0x01, 0xBB, // 16-bit port (443)
3910 };
3911
[email protected]e0c27be2009-07-15 13:09:353912 const char kSOCKS5OkResponse[] =
3913 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3914
3915 MockWrite data_writes[] = {
3916 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3917 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3918 arraysize(kSOCKS5OkRequest)),
3919 MockWrite("GET / HTTP/1.1\r\n"
3920 "Host: www.google.com\r\n"
3921 "Connection: keep-alive\r\n\r\n")
3922 };
3923
3924 MockRead data_reads[] = {
3925 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3926 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023927 MockRead("HTTP/1.0 200 OK\r\n"),
3928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3929 MockRead("Payload"),
3930 MockRead(false, OK)
3931 };
3932
[email protected]31a2bfe2010-02-09 08:03:393933 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3934 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593935 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023936
[email protected]5ecc992a42009-11-11 01:41:593937 SSLSocketDataProvider ssl(true, OK);
3938 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023939
3940 TestCompletionCallback callback;
3941
[email protected]5a1d7ca2010-04-28 20:12:273942 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023943 EXPECT_EQ(ERR_IO_PENDING, rv);
3944
3945 rv = callback.WaitForResult();
3946 EXPECT_EQ(OK, rv);
3947
3948 const HttpResponseInfo* response = trans->GetResponseInfo();
3949 EXPECT_FALSE(response == NULL);
3950
3951 std::string response_text;
3952 rv = ReadTransaction(trans.get(), &response_text);
3953 EXPECT_EQ(OK, rv);
3954 EXPECT_EQ("Payload", response_text);
3955}
3956
[email protected]04e5be32009-06-26 20:00:313957// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063958
3959struct GroupNameTest {
3960 std::string proxy_server;
3961 std::string url;
3962 std::string expected_group_name;
3963};
3964
3965scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3966 const std::string& proxy_server) {
3967 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3969
3970 HttpAlternateProtocols* alternate_protocols =
3971 session->mutable_alternate_protocols();
3972 alternate_protocols->SetAlternateProtocolFor(
3973 HostPortPair("host.with.alternate", 80), 443,
3974 HttpAlternateProtocols::NPN_SPDY_1);
3975
3976 return session;
3977}
3978
3979int GroupNameTransactionHelper(
3980 const std::string& url,
3981 const scoped_refptr<HttpNetworkSession>& session) {
3982 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3983
3984 HttpRequestInfo request;
3985 request.method = "GET";
3986 request.url = GURL(url);
3987 request.load_flags = 0;
3988
3989 TestCompletionCallback callback;
3990
3991 // We do not complete this request, the dtor will clean the transaction up.
3992 return trans->Start(&request, &callback, BoundNetLog());
3993}
3994
3995TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
3996 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:313997 {
[email protected]2d731a32010-04-29 01:04:063998 "", // unused
[email protected]04e5be32009-06-26 20:00:313999 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544000 "www.google.com:80",
4001 },
4002 {
[email protected]2d731a32010-04-29 01:04:064003 "", // unused
[email protected]2ff8b312010-04-26 22:20:544004 "http://[2001:1418:13:1::25]/direct",
4005 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:314006 },
[email protected]04e5be32009-06-26 20:00:314007
4008 // SSL Tests
4009 {
[email protected]2d731a32010-04-29 01:04:064010 "", // unused
[email protected]04e5be32009-06-26 20:00:314011 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024012 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:314013 },
4014 {
[email protected]2d731a32010-04-29 01:04:064015 "", // unused
4016 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024017 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:314018 },
4019 {
[email protected]2d731a32010-04-29 01:04:064020 "", // unused
[email protected]2ff8b312010-04-26 22:20:544021 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024022 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:544023 },
[email protected]2d731a32010-04-29 01:04:064024 };
[email protected]2ff8b312010-04-26 22:20:544025
[email protected]2d731a32010-04-29 01:04:064026 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4027
4028 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4029 scoped_refptr<HttpNetworkSession> session(
4030 SetupSessionForGroupNameTests(tests[i].proxy_server));
4031
4032 HttpNetworkSessionPeer peer(session);
4033 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4034 new CaptureGroupNameTCPSocketPool(session.get()));
4035 peer.SetTCPSocketPool(tcp_conn_pool);
4036
4037 EXPECT_EQ(ERR_IO_PENDING,
4038 GroupNameTransactionHelper(tests[i].url, session));
4039 EXPECT_EQ(tests[i].expected_group_name,
4040 tcp_conn_pool->last_group_name_received());
4041 }
4042
4043 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4044}
4045
4046TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4047 const GroupNameTest tests[] = {
4048 {
4049 "http_proxy",
4050 "http://www.google.com/http_proxy_normal",
4051 "www.google.com:80",
4052 },
4053
4054 // SSL Tests
4055 {
4056 "http_proxy",
4057 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024058 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064059 },
4060
[email protected]9faeded92010-04-29 20:03:054061 {
4062 "http_proxy",
4063 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024064 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054065 },
[email protected]2d731a32010-04-29 01:04:064066 };
4067
4068 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4069
4070 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4071 scoped_refptr<HttpNetworkSession> session(
4072 SetupSessionForGroupNameTests(tests[i].proxy_server));
4073
4074 HttpNetworkSessionPeer peer(session);
4075
4076 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
4077 new CaptureGroupNameTCPSocketPool(session.get()));
4078 peer.SetSocketPoolForHTTPProxy(
4079 HostPortPair("http_proxy", 80), http_proxy_pool);
4080
4081 EXPECT_EQ(ERR_IO_PENDING,
4082 GroupNameTransactionHelper(tests[i].url, session));
4083 EXPECT_EQ(tests[i].expected_group_name,
4084 http_proxy_pool->last_group_name_received());
4085 }
4086
4087 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4088}
4089
4090TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4091 const GroupNameTest tests[] = {
4092 {
4093 "socks4://socks_proxy:1080",
4094 "http://www.google.com/socks4_direct",
4095 "socks4/www.google.com:80",
4096 },
4097 {
4098 "socks5://socks_proxy:1080",
4099 "http://www.google.com/socks5_direct",
4100 "socks5/www.google.com:80",
4101 },
4102
4103 // SSL Tests
4104 {
4105 "socks4://socks_proxy:1080",
4106 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024107 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064108 },
4109 {
4110 "socks5://socks_proxy:1080",
4111 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024112 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064113 },
4114
[email protected]9faeded92010-04-29 20:03:054115 {
4116 "socks4://socks_proxy:1080",
4117 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024118 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054119 },
[email protected]04e5be32009-06-26 20:00:314120 };
4121
[email protected]2ff8b312010-04-26 22:20:544122 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4123
[email protected]04e5be32009-06-26 20:00:314124 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064125 scoped_refptr<HttpNetworkSession> session(
4126 SetupSessionForGroupNameTests(tests[i].proxy_server));
4127 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314128
[email protected]a796bcec2010-03-22 17:17:264129 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064130 new CaptureGroupNameSOCKSSocketPool(session.get()));
4131 peer.SetSocketPoolForSOCKSProxy(
4132 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:314133
[email protected]5695b8c2009-09-30 21:36:434134 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314135
[email protected]2d731a32010-04-29 01:04:064136 EXPECT_EQ(ERR_IO_PENDING,
4137 GroupNameTransactionHelper(tests[i].url, session));
4138 EXPECT_EQ(tests[i].expected_group_name,
4139 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314140 }
[email protected]2ff8b312010-04-26 22:20:544141
4142 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314143}
4144
[email protected]9172a982009-06-06 00:30:254145TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544146 SessionDependencies session_deps(
4147 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324148
[email protected]69719062010-01-05 20:09:214149 // This simulates failure resolving all hostnames; that means we will fail
4150 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324151 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4152
[email protected]9172a982009-06-06 00:30:254153 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434154 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254155
4156 HttpRequestInfo request;
4157 request.method = "GET";
4158 request.url = GURL("http://www.google.com/");
4159
4160 TestCompletionCallback callback;
4161
[email protected]5a1d7ca2010-04-28 20:12:274162 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254163 EXPECT_EQ(ERR_IO_PENDING, rv);
4164
[email protected]9172a982009-06-06 00:30:254165 rv = callback.WaitForResult();
4166 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4167}
4168
[email protected]f3e6c1e2009-06-15 20:52:124169// Host resolution observer used by
4170// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4171// resovle requests are issued with a referrer of |expected_referrer|.
4172class ResolutionReferrerObserver : public HostResolver::Observer {
4173 public:
4174 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4175 : expected_referrer_(expected_referrer),
4176 called_start_with_referrer_(false),
4177 called_finish_with_referrer_(false) {
4178 }
4179
4180 virtual void OnStartResolution(int id,
4181 const HostResolver::RequestInfo& info) {
4182 if (info.referrer() == expected_referrer_)
4183 called_start_with_referrer_ = true;
4184 }
4185
4186 virtual void OnFinishResolutionWithStatus(
4187 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4188 if (info.referrer() == expected_referrer_)
4189 called_finish_with_referrer_ = true;
4190 }
4191
[email protected]eb255d32009-06-17 02:11:034192 virtual void OnCancelResolution(int id,
4193 const HostResolver::RequestInfo& info ) {
4194 FAIL() << "Should not be cancelling any requests!";
4195 }
4196
[email protected]f3e6c1e2009-06-15 20:52:124197 bool did_complete_with_expected_referrer() const {
4198 return called_start_with_referrer_ && called_finish_with_referrer_;
4199 }
4200
4201 private:
4202 GURL expected_referrer_;
4203 bool called_start_with_referrer_;
4204 bool called_finish_with_referrer_;
4205
4206 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4207};
4208
4209// Make sure that when HostResolver::Resolve() is invoked, it passes through
4210// the "referrer". This is depended on by the DNS prefetch observer.
4211TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4212 GURL referrer = GURL("http://expected-referrer/");
4213 EXPECT_TRUE(referrer.is_valid());
4214 ResolutionReferrerObserver resolution_observer(referrer);
4215
4216 SessionDependencies session_deps;
4217 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434218 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124219
4220 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144221 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124222
4223 // Connect up a mock socket which will fail when reading.
4224 MockRead data_reads[] = {
4225 MockRead(false, ERR_FAILED),
4226 };
[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]f3e6c1e2009-06-15 20:52:124229
4230 // Issue a request, containing an HTTP referrer.
4231 HttpRequestInfo request;
4232 request.method = "GET";
4233 request.referrer = referrer;
4234 request.url = GURL("http://www.google.com/");
4235
4236 // Run the request until it fails reading from the socket.
4237 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274238 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124239 EXPECT_EQ(ERR_IO_PENDING, rv);
4240 rv = callback.WaitForResult();
4241 EXPECT_EQ(ERR_FAILED, rv);
4242
4243 // Check that the host resolution observer saw |referrer|.
4244 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4245}
4246
[email protected]685af592010-05-11 19:31:244247// Base test to make sure that when the load flags for a request specify to
4248// bypass the cache, the DNS cache is not used.
4249void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284250 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324251
[email protected]a2c2fb92009-07-18 07:31:044252 // Select a host resolver that does caching.
4253 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324254
[email protected]3b9cca42009-06-16 01:08:284255 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434256 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284257
4258 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4259 // a synchronous lookup.)
4260 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144261 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464262 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274263 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284264 EXPECT_EQ(OK, rv);
4265
4266 // Verify that it was added to host cache, by doing a subsequent async lookup
4267 // and confirming it completes synchronously.
4268 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464269 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284270 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274271 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324272 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284273
4274 // Inject a failure the next time that "www.google.com" is resolved. This way
4275 // we can tell if the next lookup hit the cache, or the "network".
4276 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324277 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284278
4279 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4280 // first read -- this won't be reached as the host resolution will fail first.
4281 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394282 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594283 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284284
4285 // Issue a request, asking to bypass the cache(s).
4286 HttpRequestInfo request;
4287 request.method = "GET";
[email protected]685af592010-05-11 19:31:244288 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284289 request.url = GURL("http://www.google.com/");
4290
4291 // Run the request.
4292 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274293 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284294 ASSERT_EQ(ERR_IO_PENDING, rv);
4295 rv = callback.WaitForResult();
4296
4297 // If we bypassed the cache, we would have gotten a failure while resolving
4298 // "www.google.com".
4299 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4300}
4301
[email protected]685af592010-05-11 19:31:244302// There are multiple load flags that should trigger the host cache bypass.
4303// Test each in isolation:
4304TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4305 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4306}
4307
4308TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4309 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4310}
4311
4312TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4313 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4314}
4315
[email protected]0877e3d2009-10-17 22:29:574316// Make sure we can handle an error when writing the request.
4317TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4318 SessionDependencies session_deps;
4319 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4320
4321 HttpRequestInfo request;
4322 request.method = "GET";
4323 request.url = GURL("http://www.foo.com/");
4324 request.load_flags = 0;
4325
4326 MockWrite write_failure[] = {
4327 MockWrite(true, ERR_CONNECTION_RESET),
4328 };
[email protected]31a2bfe2010-02-09 08:03:394329 StaticSocketDataProvider data(NULL, 0,
4330 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594331 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574332
4333 TestCompletionCallback callback;
4334
4335 scoped_ptr<HttpTransaction> trans(
4336 new HttpNetworkTransaction(CreateSession(&session_deps)));
4337
[email protected]5a1d7ca2010-04-28 20:12:274338 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574339 EXPECT_EQ(ERR_IO_PENDING, rv);
4340
4341 rv = callback.WaitForResult();
4342 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4343}
4344
4345// Check that a connection closed after the start of the headers finishes ok.
4346TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4347 SessionDependencies session_deps;
4348 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4349
4350 HttpRequestInfo request;
4351 request.method = "GET";
4352 request.url = GURL("http://www.foo.com/");
4353 request.load_flags = 0;
4354
4355 MockRead data_reads[] = {
4356 MockRead("HTTP/1."),
4357 MockRead(false, OK),
4358 };
4359
[email protected]31a2bfe2010-02-09 08:03:394360 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594361 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574362
4363 TestCompletionCallback callback;
4364
4365 scoped_ptr<HttpTransaction> trans(
4366 new HttpNetworkTransaction(CreateSession(&session_deps)));
4367
[email protected]5a1d7ca2010-04-28 20:12:274368 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574369 EXPECT_EQ(ERR_IO_PENDING, rv);
4370
4371 rv = callback.WaitForResult();
4372 EXPECT_EQ(OK, rv);
4373
4374 const HttpResponseInfo* response = trans->GetResponseInfo();
4375 EXPECT_TRUE(response != NULL);
4376
4377 EXPECT_TRUE(response->headers != NULL);
4378 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4379
4380 std::string response_data;
4381 rv = ReadTransaction(trans.get(), &response_data);
4382 EXPECT_EQ(OK, rv);
4383 EXPECT_EQ("", response_data);
4384}
4385
4386// Make sure that a dropped connection while draining the body for auth
4387// restart does the right thing.
4388TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4389 SessionDependencies session_deps;
4390 scoped_ptr<HttpTransaction> trans(
4391 new HttpNetworkTransaction(CreateSession(&session_deps)));
4392
4393 HttpRequestInfo request;
4394 request.method = "GET";
4395 request.url = GURL("http://www.google.com/");
4396 request.load_flags = 0;
4397
4398 MockWrite data_writes1[] = {
4399 MockWrite("GET / HTTP/1.1\r\n"
4400 "Host: www.google.com\r\n"
4401 "Connection: keep-alive\r\n\r\n"),
4402 };
4403
4404 MockRead data_reads1[] = {
4405 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4406 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4408 MockRead("Content-Length: 14\r\n\r\n"),
4409 MockRead("Unauth"),
4410 MockRead(true, ERR_CONNECTION_RESET),
4411 };
4412
[email protected]31a2bfe2010-02-09 08:03:394413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4414 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594415 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574416
4417 // After calling trans->RestartWithAuth(), this is the request we should
4418 // be issuing -- the final header line contains the credentials.
4419 MockWrite data_writes2[] = {
4420 MockWrite("GET / HTTP/1.1\r\n"
4421 "Host: www.google.com\r\n"
4422 "Connection: keep-alive\r\n"
4423 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4424 };
4425
4426 // Lastly, the server responds with the actual content.
4427 MockRead data_reads2[] = {
4428 MockRead("HTTP/1.1 200 OK\r\n"),
4429 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4430 MockRead("Content-Length: 100\r\n\r\n"),
4431 MockRead(false, OK),
4432 };
4433
[email protected]31a2bfe2010-02-09 08:03:394434 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4435 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594436 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574437
4438 TestCompletionCallback callback1;
4439
[email protected]5a1d7ca2010-04-28 20:12:274440 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574441 EXPECT_EQ(ERR_IO_PENDING, rv);
4442
4443 rv = callback1.WaitForResult();
4444 EXPECT_EQ(OK, rv);
4445
4446 const HttpResponseInfo* response = trans->GetResponseInfo();
4447 EXPECT_FALSE(response == NULL);
4448
4449 // The password prompt info should have been set in response->auth_challenge.
4450 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4451
4452 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4453 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4454 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4455
4456 TestCompletionCallback callback2;
4457
4458 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4459 EXPECT_EQ(ERR_IO_PENDING, rv);
4460
4461 rv = callback2.WaitForResult();
4462 EXPECT_EQ(OK, rv);
4463
4464 response = trans->GetResponseInfo();
4465 EXPECT_FALSE(response == NULL);
4466 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4467 EXPECT_EQ(100, response->headers->GetContentLength());
4468}
4469
4470// Test HTTPS connections going through a proxy that sends extra data.
4471TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4472 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4473
4474 HttpRequestInfo request;
4475 request.method = "GET";
4476 request.url = GURL("https://www.google.com/");
4477 request.load_flags = 0;
4478
4479 MockRead proxy_reads[] = {
4480 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4481 MockRead(false, OK)
4482 };
4483
[email protected]31a2bfe2010-02-09 08:03:394484 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594485 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574486
[email protected]5ecc992a42009-11-11 01:41:594487 session_deps.socket_factory.AddSocketDataProvider(&data);
4488 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574489
4490 TestCompletionCallback callback;
4491
4492 session_deps.socket_factory.ResetNextMockIndexes();
4493
4494 scoped_ptr<HttpTransaction> trans(
4495 new HttpNetworkTransaction(CreateSession(&session_deps)));
4496
[email protected]5a1d7ca2010-04-28 20:12:274497 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574498 EXPECT_EQ(ERR_IO_PENDING, rv);
4499
4500 rv = callback.WaitForResult();
4501 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4502}
4503
[email protected]e22e1362009-11-23 21:31:124504TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464505 SessionDependencies session_deps;
4506 scoped_ptr<HttpTransaction> trans(
4507 new HttpNetworkTransaction(CreateSession(&session_deps)));
4508
4509 HttpRequestInfo request;
4510 request.method = "GET";
4511 request.url = GURL("http://www.google.com/");
4512 request.load_flags = 0;
4513
[email protected]e22e1362009-11-23 21:31:124514 MockRead data_reads[] = {
4515 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4516 MockRead(false, OK),
4517 };
[email protected]9492e4a2010-02-24 00:58:464518
4519 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4520 session_deps.socket_factory.AddSocketDataProvider(&data);
4521
4522 TestCompletionCallback callback;
4523
[email protected]5a1d7ca2010-04-28 20:12:274524 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464525 EXPECT_EQ(ERR_IO_PENDING, rv);
4526
4527 EXPECT_EQ(OK, callback.WaitForResult());
4528
4529 const HttpResponseInfo* response = trans->GetResponseInfo();
4530 EXPECT_TRUE(response != NULL);
4531
4532 EXPECT_TRUE(response->headers != NULL);
4533 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4534
4535 std::string response_data;
4536 rv = ReadTransaction(trans.get(), &response_data);
4537 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124538}
4539
[email protected]95d88ffe2010-02-04 21:25:334540TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4541 SessionDependencies session_deps;
4542 scoped_ptr<HttpTransaction> trans(
4543 new HttpNetworkTransaction(CreateSession(&session_deps)));
4544
4545 HttpRequestInfo request;
4546 request.method = "POST";
4547 request.url = GURL("http://www.google.com/upload");
4548 request.upload_data = new UploadData;
4549 request.load_flags = 0;
4550
4551 FilePath temp_file_path;
4552 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4553 const uint64 kFakeSize = 100000; // file is actually blank
4554
4555 std::vector<UploadData::Element> elements;
4556 UploadData::Element element;
4557 element.SetToFilePath(temp_file_path);
4558 element.SetContentLength(kFakeSize);
4559 elements.push_back(element);
4560 request.upload_data->set_elements(elements);
4561 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4562
4563 MockRead data_reads[] = {
4564 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4565 MockRead("hello world"),
4566 MockRead(false, OK),
4567 };
[email protected]31a2bfe2010-02-09 08:03:394568 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334569 session_deps.socket_factory.AddSocketDataProvider(&data);
4570
4571 TestCompletionCallback callback;
4572
[email protected]5a1d7ca2010-04-28 20:12:274573 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334574 EXPECT_EQ(ERR_IO_PENDING, rv);
4575
4576 rv = callback.WaitForResult();
4577 EXPECT_EQ(OK, rv);
4578
4579 const HttpResponseInfo* response = trans->GetResponseInfo();
4580 EXPECT_TRUE(response != NULL);
4581
4582 EXPECT_TRUE(response->headers != NULL);
4583 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4584
4585 std::string response_data;
4586 rv = ReadTransaction(trans.get(), &response_data);
4587 EXPECT_EQ(OK, rv);
4588 EXPECT_EQ("hello world", response_data);
4589
4590 file_util::Delete(temp_file_path, false);
4591}
4592
[email protected]6624b4622010-03-29 19:58:364593TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4594 // If we try to upload an unreadable file, the network stack should report
4595 // the file size as zero and upload zero bytes for that file.
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_content("Unreadable file.");
4603 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4604 temp_file_content.length()));
4605 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
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.0 200 OK\r\n\r\n"),
4621 MockRead(false, OK),
4622 };
4623 MockWrite data_writes[] = {
4624 MockWrite("POST /upload HTTP/1.1\r\n"
4625 "Host: www.google.com\r\n"
4626 "Connection: keep-alive\r\n"
4627 "Content-Length: 0\r\n\r\n"),
4628 MockWrite(false, OK),
4629 };
4630 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4631 arraysize(data_writes));
4632 session_deps.socket_factory.AddSocketDataProvider(&data);
4633
4634 TestCompletionCallback callback;
4635
[email protected]5a1d7ca2010-04-28 20:12:274636 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364637 EXPECT_EQ(ERR_IO_PENDING, rv);
4638
4639 rv = callback.WaitForResult();
4640 EXPECT_EQ(OK, rv);
4641
4642 const HttpResponseInfo* response = trans->GetResponseInfo();
4643 EXPECT_TRUE(response != NULL);
4644 EXPECT_TRUE(response->headers != NULL);
4645 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4646
4647 file_util::Delete(temp_file, false);
4648}
4649
4650TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4651 SessionDependencies session_deps;
4652 scoped_ptr<HttpTransaction> trans(
4653 new HttpNetworkTransaction(CreateSession(&session_deps)));
4654
4655 FilePath temp_file;
4656 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4657 std::string temp_file_contents("Unreadable file.");
4658 std::string unreadable_contents(temp_file_contents.length(), '\0');
4659 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4660 temp_file_contents.length()));
4661
4662 HttpRequestInfo request;
4663 request.method = "POST";
4664 request.url = GURL("http://www.google.com/upload");
4665 request.upload_data = new UploadData;
4666 request.load_flags = 0;
4667
4668 std::vector<UploadData::Element> elements;
4669 UploadData::Element element;
4670 element.SetToFilePath(temp_file);
4671 elements.push_back(element);
4672 request.upload_data->set_elements(elements);
4673
4674 MockRead data_reads[] = {
4675 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4676 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4677 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4678
4679 MockRead("HTTP/1.1 200 OK\r\n"),
4680 MockRead("Content-Length: 0\r\n\r\n"),
4681 MockRead(false, OK),
4682 };
4683 MockWrite data_writes[] = {
4684 MockWrite("POST /upload HTTP/1.1\r\n"
4685 "Host: www.google.com\r\n"
4686 "Connection: keep-alive\r\n"
4687 "Content-Length: 16\r\n\r\n"),
4688 MockWrite(false, temp_file_contents.c_str()),
4689
4690 MockWrite("POST /upload HTTP/1.1\r\n"
4691 "Host: www.google.com\r\n"
4692 "Connection: keep-alive\r\n"
4693 "Content-Length: 16\r\n"
4694 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4695 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4696 MockWrite(false, OK),
4697 };
4698 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4699 arraysize(data_writes));
4700 session_deps.socket_factory.AddSocketDataProvider(&data);
4701
4702 TestCompletionCallback callback1;
4703
[email protected]5a1d7ca2010-04-28 20:12:274704 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364705 EXPECT_EQ(ERR_IO_PENDING, rv);
4706
4707 rv = callback1.WaitForResult();
4708 EXPECT_EQ(OK, rv);
4709
4710 const HttpResponseInfo* response = trans->GetResponseInfo();
4711 EXPECT_TRUE(response != NULL);
4712 EXPECT_TRUE(response->headers != NULL);
4713 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4714
4715 // The password prompt info should have been set in response->auth_challenge.
4716 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4717 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4718 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4719 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4720
4721 // Now make the file unreadable and try again.
4722 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4723
4724 TestCompletionCallback callback2;
4725
4726 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4727 EXPECT_EQ(ERR_IO_PENDING, rv);
4728
4729 rv = callback2.WaitForResult();
4730 EXPECT_EQ(OK, rv);
4731
4732 response = trans->GetResponseInfo();
4733 EXPECT_TRUE(response != NULL);
4734 EXPECT_TRUE(response->headers != NULL);
4735 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4736 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4737
4738 file_util::Delete(temp_file, false);
4739}
4740
[email protected]aeefc9e82010-02-19 16:18:274741// Tests that changes to Auth realms are treated like auth rejections.
4742TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4743 SessionDependencies session_deps;
4744 scoped_ptr<HttpTransaction> trans(
4745 new HttpNetworkTransaction(CreateSession(&session_deps)));
4746
4747 HttpRequestInfo request;
4748 request.method = "GET";
4749 request.url = GURL("http://www.google.com/");
4750 request.load_flags = 0;
4751
4752 // First transaction will request a resource and receive a Basic challenge
4753 // with realm="first_realm".
4754 MockWrite data_writes1[] = {
4755 MockWrite("GET / HTTP/1.1\r\n"
4756 "Host: www.google.com\r\n"
4757 "Connection: keep-alive\r\n"
4758 "\r\n"),
4759 };
4760 MockRead data_reads1[] = {
4761 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4762 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4763 "\r\n"),
4764 };
4765
4766 // After calling trans->RestartWithAuth(), provide an Authentication header
4767 // for first_realm. The server will reject and provide a challenge with
4768 // second_realm.
4769 MockWrite data_writes2[] = {
4770 MockWrite("GET / HTTP/1.1\r\n"
4771 "Host: www.google.com\r\n"
4772 "Connection: keep-alive\r\n"
4773 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4774 "\r\n"),
4775 };
4776 MockRead data_reads2[] = {
4777 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4778 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4779 "\r\n"),
4780 };
4781
4782 // This again fails, and goes back to first_realm. Make sure that the
4783 // entry is removed from cache.
4784 MockWrite data_writes3[] = {
4785 MockWrite("GET / HTTP/1.1\r\n"
4786 "Host: www.google.com\r\n"
4787 "Connection: keep-alive\r\n"
4788 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4789 "\r\n"),
4790 };
4791 MockRead data_reads3[] = {
4792 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4793 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4794 "\r\n"),
4795 };
4796
4797 // Try one last time (with the correct password) and get the resource.
4798 MockWrite data_writes4[] = {
4799 MockWrite("GET / HTTP/1.1\r\n"
4800 "Host: www.google.com\r\n"
4801 "Connection: keep-alive\r\n"
4802 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4803 "\r\n"),
4804 };
4805 MockRead data_reads4[] = {
4806 MockRead("HTTP/1.1 200 OK\r\n"
4807 "Content-Type: text/html; charset=iso-8859-1\r\n"
4808 "Content-Length: 100\r\n"
4809 "\r\n"),
4810 };
4811
4812 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4813 data_writes1, arraysize(data_writes1));
4814 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4815 data_writes2, arraysize(data_writes2));
4816 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4817 data_writes3, arraysize(data_writes3));
4818 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4819 data_writes4, arraysize(data_writes4));
4820 session_deps.socket_factory.AddSocketDataProvider(&data1);
4821 session_deps.socket_factory.AddSocketDataProvider(&data2);
4822 session_deps.socket_factory.AddSocketDataProvider(&data3);
4823 session_deps.socket_factory.AddSocketDataProvider(&data4);
4824
4825 TestCompletionCallback callback1;
4826
4827 // Issue the first request with Authorize headers. There should be a
4828 // password prompt for first_realm waiting to be filled in after the
4829 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274830 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274831 EXPECT_EQ(ERR_IO_PENDING, rv);
4832 rv = callback1.WaitForResult();
4833 EXPECT_EQ(OK, rv);
4834 const HttpResponseInfo* response = trans->GetResponseInfo();
4835 ASSERT_FALSE(response == NULL);
4836 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4837 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4838 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4839 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4840
4841 // Issue the second request with an incorrect password. There should be a
4842 // password prompt for second_realm waiting to be filled in after the
4843 // transaction completes.
4844 TestCompletionCallback callback2;
4845 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4846 EXPECT_EQ(ERR_IO_PENDING, rv);
4847 rv = callback2.WaitForResult();
4848 EXPECT_EQ(OK, rv);
4849 response = trans->GetResponseInfo();
4850 ASSERT_FALSE(response == NULL);
4851 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4852 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4853 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4854 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4855
4856 // Issue the third request with another incorrect password. There should be
4857 // a password prompt for first_realm waiting to be filled in. If the password
4858 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4859 // first_realm was not correctly removed.
4860 TestCompletionCallback callback3;
4861 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4862 EXPECT_EQ(ERR_IO_PENDING, rv);
4863 rv = callback3.WaitForResult();
4864 EXPECT_EQ(OK, rv);
4865 response = trans->GetResponseInfo();
4866 ASSERT_FALSE(response == NULL);
4867 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4868 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4869 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4870 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4871
4872 // Issue the fourth request with the correct password and username.
4873 TestCompletionCallback callback4;
4874 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4875 EXPECT_EQ(ERR_IO_PENDING, rv);
4876 rv = callback4.WaitForResult();
4877 EXPECT_EQ(OK, rv);
4878 response = trans->GetResponseInfo();
4879 ASSERT_FALSE(response == NULL);
4880 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4881}
4882
[email protected]564b4912010-03-09 16:30:424883TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424884 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064885 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424886
[email protected]564b4912010-03-09 16:30:424887 SessionDependencies session_deps;
4888
4889 MockRead data_reads[] = {
4890 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064891 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424892 MockRead("hello world"),
4893 MockRead(false, OK),
4894 };
4895
4896 HttpRequestInfo request;
4897 request.method = "GET";
4898 request.url = GURL("http://www.google.com/");
4899 request.load_flags = 0;
4900
4901 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4902
4903 session_deps.socket_factory.AddSocketDataProvider(&data);
4904
4905 TestCompletionCallback callback;
4906
4907 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4908 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4909
[email protected]5a1d7ca2010-04-28 20:12:274910 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534912
[email protected]564b4912010-03-09 16:30:424913 HostPortPair http_host_port_pair;
4914 http_host_port_pair.host = "www.google.com";
4915 http_host_port_pair.port = 80;
4916 const HttpAlternateProtocols& alternate_protocols =
4917 session->alternate_protocols();
4918 EXPECT_FALSE(
4919 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4920
4921 EXPECT_EQ(OK, callback.WaitForResult());
4922
4923 const HttpResponseInfo* response = trans->GetResponseInfo();
4924 ASSERT_TRUE(response != NULL);
4925 ASSERT_TRUE(response->headers != NULL);
4926 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:534927 EXPECT_FALSE(response->was_fetched_via_spdy);
4928 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:424929
4930 std::string response_data;
4931 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4932 EXPECT_EQ("hello world", response_data);
4933
4934 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4935 const HttpAlternateProtocols::PortProtocolPair alternate =
4936 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4937 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4938 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064939 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424940 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424941
[email protected]31e2c69e2010-04-15 18:06:064942 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424943 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424944}
4945
4946TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064947 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424948 SessionDependencies session_deps;
4949
4950 HttpRequestInfo request;
4951 request.method = "GET";
4952 request.url = GURL("http://www.google.com/");
4953 request.load_flags = 0;
4954
4955 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4956 StaticSocketDataProvider first_data;
4957 first_data.set_connect_data(mock_connect);
4958 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4959
4960 MockRead data_reads[] = {
4961 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4962 MockRead("hello world"),
4963 MockRead(true, OK),
4964 };
4965 StaticSocketDataProvider second_data(
4966 data_reads, arraysize(data_reads), NULL, 0);
4967 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4968
4969 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4970 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4971 // http://crbug.com/37454.
4972 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4973
4974 TestCompletionCallback callback;
4975
4976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4977
4978 HostPortPair http_host_port_pair;
4979 http_host_port_pair.host = "www.google.com";
4980 http_host_port_pair.port = 80;
4981 HttpAlternateProtocols* alternate_protocols =
4982 session->mutable_alternate_protocols();
4983 alternate_protocols->SetAlternateProtocolFor(
4984 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064985 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424986
4987 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4988
[email protected]5a1d7ca2010-04-28 20:12:274989 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424990 EXPECT_EQ(ERR_IO_PENDING, rv);
4991 EXPECT_EQ(OK, callback.WaitForResult());
4992
4993 const HttpResponseInfo* response = trans->GetResponseInfo();
4994 ASSERT_TRUE(response != NULL);
4995 ASSERT_TRUE(response->headers != NULL);
4996 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4997
4998 std::string response_data;
4999 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5000 EXPECT_EQ("hello world", response_data);
5001
5002 ASSERT_TRUE(
5003 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5004 const HttpAlternateProtocols::PortProtocolPair alternate =
5005 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5006 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065007 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425008}
5009
5010// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5011// says that it does SPDY, but it just does the TLS handshake, but the NPN
5012// response does not indicate SPDY, so we just do standard HTTPS over the port.
5013// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5014// on the original port.
[email protected]a2cb8122010-03-10 17:22:425015// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5016// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535017//
[email protected]a2cb8122010-03-10 17:22:425018// HttpRequestInfo request;
5019// request.method = "GET";
5020// request.url = GURL("http://www.google.com/");
5021// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535022//
[email protected]a2cb8122010-03-10 17:22:425023// MockRead data_reads[] = {
5024// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5025// MockRead("hello world"),
5026// MockRead(true, OK),
5027// };
5028// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5029// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535030//
[email protected]a2cb8122010-03-10 17:22:425031// SSLSocketDataProvider ssl(true, OK);
5032// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535033//
[email protected]a2cb8122010-03-10 17:22:425034// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535035//
[email protected]a2cb8122010-03-10 17:22:425036// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535037//
[email protected]a2cb8122010-03-10 17:22:425038// 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]9e743cd2010-03-16 07:03:535046//
[email protected]a2cb8122010-03-10 17:22:425047// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535048//
[email protected]5a1d7ca2010-04-28 20:12:275049// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425050// EXPECT_EQ(ERR_IO_PENDING, rv);
5051// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535052//
[email protected]a2cb8122010-03-10 17:22:425053// 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());
[email protected]9e743cd2010-03-16 07:03:535057//
[email protected]a2cb8122010-03-10 17:22:425058// std::string response_data;
5059// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5060// EXPECT_EQ("hello world", response_data);
5061// }
5062
5063TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065064 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545065 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115066 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425067 SessionDependencies session_deps;
5068
5069 HttpRequestInfo request;
5070 request.method = "GET";
5071 request.url = GURL("http://www.google.com/");
5072 request.load_flags = 0;
5073
[email protected]a2cb8122010-03-10 17:22:425074 StaticSocketDataProvider first_tcp_connect;
5075 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5076
5077 SSLSocketDataProvider ssl(true, OK);
5078 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5079
[email protected]564b4912010-03-09 16:30:425080 MockRead data_reads[] = {
5081 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5082 MockRead("hello world"),
5083 MockRead(true, OK),
5084 };
[email protected]a2cb8122010-03-10 17:22:425085 StaticSocketDataProvider fallback_data(
5086 data_reads, arraysize(data_reads), NULL, 0);
5087 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425088
5089 TestCompletionCallback callback;
5090
5091 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5092
5093 HostPortPair http_host_port_pair;
5094 http_host_port_pair.host = "www.google.com";
5095 http_host_port_pair.port = 80;
5096 HttpAlternateProtocols* alternate_protocols =
5097 session->mutable_alternate_protocols();
5098 alternate_protocols->SetAlternateProtocolFor(
5099 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065100 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425101
5102 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5103
[email protected]5a1d7ca2010-04-28 20:12:275104 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425105 EXPECT_EQ(ERR_IO_PENDING, rv);
5106 EXPECT_EQ(OK, callback.WaitForResult());
5107
5108 const HttpResponseInfo* response = trans->GetResponseInfo();
5109 ASSERT_TRUE(response != NULL);
5110 ASSERT_TRUE(response->headers != NULL);
5111 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5112
5113 std::string response_data;
5114 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5115 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545116 HttpNetworkTransaction::SetNextProtos("");
5117 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5118}
5119
5120TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5121 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5122 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115123 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545124 SessionDependencies session_deps;
5125
5126 HttpRequestInfo request;
5127 request.method = "GET";
5128 request.url = GURL("http://www.google.com/");
5129 request.load_flags = 0;
5130
5131 MockRead data_reads[] = {
5132 MockRead("HTTP/1.1 200 OK\r\n"),
5133 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5134 MockRead("hello world"),
5135 MockRead(true, OK),
5136 };
5137
5138 StaticSocketDataProvider first_transaction(
5139 data_reads, arraysize(data_reads), NULL, 0);
5140 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5141
5142 SSLSocketDataProvider ssl(true, OK);
5143 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5144 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535145 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545146 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5147
5148 MockWrite spdy_writes[] = {
5149 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5150 arraysize(kGetSyn)),
5151 };
5152
5153 MockRead spdy_reads[] = {
5154 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5155 arraysize(kGetSynReply)),
5156 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5157 arraysize(kGetBodyFrame)),
5158 MockRead(true, 0, 0),
5159 };
5160
5161 scoped_refptr<DelayedSocketData> spdy_data(
5162 new DelayedSocketData(
5163 1, // wait for one write to finish before reading.
5164 spdy_reads, arraysize(spdy_reads),
5165 spdy_writes, arraysize(spdy_writes)));
5166 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5167
5168 TestCompletionCallback callback;
5169
5170 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5171 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5172
[email protected]5a1d7ca2010-04-28 20:12:275173 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545174 EXPECT_EQ(ERR_IO_PENDING, rv);
5175 EXPECT_EQ(OK, callback.WaitForResult());
5176
5177 const HttpResponseInfo* response = trans->GetResponseInfo();
5178 ASSERT_TRUE(response != NULL);
5179 ASSERT_TRUE(response->headers != NULL);
5180 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5181
5182 std::string response_data;
5183 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5184 EXPECT_EQ("hello world", response_data);
5185
5186 trans.reset(new HttpNetworkTransaction(session));
5187
[email protected]5a1d7ca2010-04-28 20:12:275188 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545189 EXPECT_EQ(ERR_IO_PENDING, rv);
5190 EXPECT_EQ(OK, callback.WaitForResult());
5191
5192 response = trans->GetResponseInfo();
5193 ASSERT_TRUE(response != NULL);
5194 ASSERT_TRUE(response->headers != NULL);
5195 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535196 EXPECT_TRUE(response->was_fetched_via_spdy);
5197 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:545198
5199 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5200 EXPECT_EQ("hello!", response_data);
5201
5202 HttpNetworkTransaction::SetNextProtos("");
5203 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5204}
5205
[email protected]631f1322010-04-30 17:59:115206class CapturingProxyResolver : public ProxyResolver {
5207 public:
5208 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5209 virtual ~CapturingProxyResolver() {}
5210
5211 virtual int GetProxyForURL(const GURL& url,
5212 ProxyInfo* results,
5213 CompletionCallback* callback,
5214 RequestHandle* request,
5215 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425216 ProxyServer proxy_server(
5217 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5218 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115219 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425220 return OK;
[email protected]631f1322010-04-30 17:59:115221 }
5222
5223 virtual void CancelRequest(RequestHandle request) {
5224 NOTREACHED();
5225 }
5226
5227 const std::vector<GURL>& resolved() const { return resolved_; }
5228
5229 private:
5230 virtual int SetPacScript(const GURL& /*pac_url*/,
5231 const std::string& /*pac_bytes*/,
5232 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425233 return OK;
[email protected]631f1322010-04-30 17:59:115234 }
5235
5236 std::vector<GURL> resolved_;
5237
5238 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5239};
5240
[email protected]631f1322010-04-30 17:59:115241TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5242 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5243 HttpNetworkTransaction::SetNextProtos(
5244 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5245
5246 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425247 proxy_config.set_auto_detect(true);
5248 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115249
[email protected]631f1322010-04-30 17:59:115250 CapturingProxyResolver* capturing_proxy_resolver =
5251 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385252 SessionDependencies session_deps(new ProxyService(
5253 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5254 NULL));
[email protected]631f1322010-04-30 17:59:115255
5256 HttpRequestInfo request;
5257 request.method = "GET";
5258 request.url = GURL("http://www.google.com/");
5259 request.load_flags = 0;
5260
5261 MockRead data_reads[] = {
5262 MockRead("HTTP/1.1 200 OK\r\n"),
5263 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5264 MockRead("hello world"),
5265 MockRead(true, OK),
5266 };
5267
5268 StaticSocketDataProvider first_transaction(
5269 data_reads, arraysize(data_reads), NULL, 0);
5270 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5271
5272 SSLSocketDataProvider ssl(true, OK);
5273 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5274 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535275 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115276 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5277
5278 MockWrite spdy_writes[] = {
5279 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5280 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425281 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]631f1322010-04-30 17:59:115282 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
[email protected]d911f1b2010-05-05 22:39:425283 arraysize(kGetSyn)), // 3
[email protected]631f1322010-04-30 17:59:115284 };
5285
[email protected]d911f1b2010-05-05 22:39:425286 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5287
[email protected]631f1322010-04-30 17:59:115288 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425289 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
5290 MockRead(true, reinterpret_cast<const char*>(kGetSynReply), // 2, 4
5291 arraysize(kGetSynReply), 4),
5292 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame), // 5
5293 arraysize(kGetBodyFrame), 4),
5294 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115295 };
5296
[email protected]d911f1b2010-05-05 22:39:425297 scoped_refptr<OrderedSocketData> spdy_data(
5298 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115299 spdy_reads, arraysize(spdy_reads),
5300 spdy_writes, arraysize(spdy_writes)));
5301 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5302
5303 TestCompletionCallback callback;
5304
5305 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5306 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5307
5308 int rv = trans->Start(&request, &callback, BoundNetLog());
5309 EXPECT_EQ(ERR_IO_PENDING, rv);
5310 EXPECT_EQ(OK, callback.WaitForResult());
5311
5312 const HttpResponseInfo* response = trans->GetResponseInfo();
5313 ASSERT_TRUE(response != NULL);
5314 ASSERT_TRUE(response->headers != NULL);
5315 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535316 EXPECT_FALSE(response->was_fetched_via_spdy);
5317 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115318
5319 std::string response_data;
5320 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5321 EXPECT_EQ("hello world", response_data);
5322
5323 trans.reset(new HttpNetworkTransaction(session));
5324
5325 rv = trans->Start(&request, &callback, BoundNetLog());
5326 EXPECT_EQ(ERR_IO_PENDING, rv);
5327 EXPECT_EQ(OK, callback.WaitForResult());
5328
5329 response = trans->GetResponseInfo();
5330 ASSERT_TRUE(response != NULL);
5331 ASSERT_TRUE(response->headers != NULL);
5332 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535333 EXPECT_TRUE(response->was_fetched_via_spdy);
5334 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115335
5336 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5337 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425338 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5339 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115340 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425341 EXPECT_EQ("https://www.google.com/",
5342 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115343
5344 HttpNetworkTransaction::SetNextProtos("");
5345 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5346}
[email protected]631f1322010-04-30 17:59:115347
[email protected]2ff8b312010-04-26 22:20:545348TEST_F(HttpNetworkTransactionTest,
5349 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5350 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5351 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115352 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545353 SessionDependencies session_deps;
5354
5355 HttpRequestInfo request;
5356 request.method = "GET";
5357 request.url = GURL("http://www.google.com/");
5358 request.load_flags = 0;
5359
5360 MockRead data_reads[] = {
5361 MockRead("HTTP/1.1 200 OK\r\n"),
5362 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5363 MockRead("hello world"),
5364 MockRead(true, OK),
5365 };
5366
5367 StaticSocketDataProvider first_transaction(
5368 data_reads, arraysize(data_reads), NULL, 0);
5369 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5370
5371 SSLSocketDataProvider ssl(true, OK);
5372 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5373 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535374 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545375 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535376 // Make sure we use ssl for spdy here.
5377 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545378
5379 MockWrite spdy_writes[] = {
5380 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5381 arraysize(kGetSyn)),
5382 };
5383
5384 MockRead spdy_reads[] = {
5385 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5386 arraysize(kGetSynReply)),
5387 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5388 arraysize(kGetBodyFrame)),
5389 MockRead(true, 0, 0),
5390 };
5391
5392 scoped_refptr<DelayedSocketData> spdy_data(
5393 new DelayedSocketData(
5394 1, // wait for one write to finish before reading.
5395 spdy_reads, arraysize(spdy_reads),
5396 spdy_writes, arraysize(spdy_writes)));
5397 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5398
5399 TestCompletionCallback callback;
5400
5401 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5402
5403 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5404
[email protected]5a1d7ca2010-04-28 20:12:275405 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545406 EXPECT_EQ(ERR_IO_PENDING, rv);
5407 EXPECT_EQ(OK, callback.WaitForResult());
5408
5409 const HttpResponseInfo* response = trans->GetResponseInfo();
5410 ASSERT_TRUE(response != NULL);
5411 ASSERT_TRUE(response->headers != NULL);
5412 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5413
5414 std::string response_data;
5415 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5416 EXPECT_EQ("hello world", response_data);
5417
5418 // Set up an initial SpdySession in the pool to reuse.
5419 scoped_refptr<SpdySession> spdy_session =
5420 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365421 session, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545422 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365423 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545424 trans.reset(new HttpNetworkTransaction(session));
5425
[email protected]5a1d7ca2010-04-28 20:12:275426 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545427 EXPECT_EQ(ERR_IO_PENDING, rv);
5428 EXPECT_EQ(OK, callback.WaitForResult());
5429
5430 response = trans->GetResponseInfo();
5431 ASSERT_TRUE(response != NULL);
5432 ASSERT_TRUE(response->headers != NULL);
5433 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535434 EXPECT_TRUE(response->was_fetched_via_spdy);
5435 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:545436
5437 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5438 EXPECT_EQ("hello!", response_data);
5439
5440 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065441 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425442}
5443
[email protected]e5ae96a2010-04-14 20:12:455444// Tests that ResolveCanonicalName is handled correctly by the
5445// HttpNetworkTransaction.
5446TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5447 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:005448 HttpAuthHandlerMock::Factory* auth_factory(
5449 new HttpAuthHandlerMock::Factory());
[email protected]e5ae96a2010-04-14 20:12:455450 session_deps.http_auth_handler_factory.reset(auth_factory);
5451
5452 for (int i = 0; i < 2; ++i) {
[email protected]3fd9dae2010-06-21 11:39:005453 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]bcc528e2010-06-10 15:03:245454 std::string auth_challenge = "Mock";
5455 GURL origin("http://www.example.com");
5456 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5457 auth_challenge.end());
5458 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5459 origin, BoundNetLog());
[email protected]044de0642010-06-17 10:42:155460 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]36c8e5f72010-06-07 14:17:145461
[email protected]e5ae96a2010-04-14 20:12:455462 scoped_ptr<HttpTransaction> trans(
5463 new HttpNetworkTransaction(CreateSession(&session_deps)));
5464
5465 // Set up expectations for this pass of the test. Many of the EXPECT calls
[email protected]3fd9dae2010-06-21 11:39:005466 // are contained inside the HttpAuthHandlerMock codebase in response to
[email protected]e5ae96a2010-04-14 20:12:455467 // the expectations.
[email protected]3fd9dae2010-06-21 11:39:005468 HttpAuthHandlerMock::Resolve resolve = ((i == 0) ?
5469 HttpAuthHandlerMock::RESOLVE_SYNC :
5470 HttpAuthHandlerMock::RESOLVE_ASYNC);
[email protected]e5ae96a2010-04-14 20:12:455471 auth_handler->SetResolveExpectation(resolve);
5472 HttpRequestInfo request;
5473 request.method = "GET";
5474 request.url = GURL("http://myserver/");
5475 request.load_flags = 0;
5476
5477 MockWrite data_writes1[] = {
5478 MockWrite("GET / HTTP/1.1\r\n"
5479 "Host: myserver\r\n"
5480 "Connection: keep-alive\r\n\r\n"),
5481 };
5482
5483 MockRead data_reads1[] = {
5484 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5485 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5487 MockRead("Content-Length: 14\r\n\r\n"),
5488 MockRead("Unauthorized\r\n"),
5489 };
5490
5491 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5492 data_writes1, arraysize(data_writes1));
5493 session_deps.socket_factory.AddSocketDataProvider(&data1);
5494
5495 TestCompletionCallback callback1;
5496
[email protected]5a1d7ca2010-04-28 20:12:275497 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455498 EXPECT_EQ(ERR_IO_PENDING, rv);
5499
5500 rv = callback1.WaitForResult();
5501 EXPECT_EQ(OK, rv);
5502
5503 const HttpResponseInfo* response = trans->GetResponseInfo();
5504 EXPECT_FALSE(response == NULL);
5505
5506 // The password prompt is set after the canonical name is resolved.
5507 // If it isn't present or is incorrect, it indicates that the scheme
5508 // did not complete correctly.
5509 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5510
5511 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5512 EXPECT_EQ(L"", response->auth_challenge->realm);
5513 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
[email protected]044de0642010-06-17 10:42:155514 }
5515}
5516
5517// GenerateAuthToken is a mighty big test.
5518// It tests all permutation of GenerateAuthToken behavior:
5519// - Synchronous and Asynchronous completion.
5520// - OK or error on completion.
5521// - Direct connection, non-authenticating proxy, and authenticating proxy.
5522// - HTTP or HTTPS backend (to include proxy tunneling).
5523// - Non-authenticating and authenticating backend.
5524//
5525// In all, there are 44 reasonable permuations (for example, if there are
5526// problems generating an auth token for an authenticating proxy, we don't
5527// need to test all permutations of the backend server).
5528//
5529// The test proceeds by going over each of the configuration cases, and
5530// potentially running up to three rounds in each of the tests. The TestConfig
5531// specifies both the configuration for the test as well as the expectations
5532// for the results.
5533TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5534 const char* kServer = "http://www.example.com";
5535 const char* kSecureServer = "https://www.example.com";
5536 const char* kProxy = "myproxy:70";
5537 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5538
5539 enum AuthTiming {
5540 AUTH_NONE,
5541 AUTH_SYNC,
5542 AUTH_ASYNC,
5543 };
5544
5545 const MockWrite kGet(
5546 "GET / HTTP/1.1\r\n"
5547 "Host: www.example.com\r\n"
5548 "Connection: keep-alive\r\n\r\n");
5549 const MockWrite kGetProxy(
5550 "GET http://www.example.com/ HTTP/1.1\r\n"
5551 "Host: www.example.com\r\n"
5552 "Proxy-Connection: keep-alive\r\n\r\n");
5553 const MockWrite kGetAuth(
5554 "GET / HTTP/1.1\r\n"
5555 "Host: www.example.com\r\n"
5556 "Connection: keep-alive\r\n"
5557 "Authorization: auth_token\r\n\r\n");
5558 const MockWrite kGetProxyAuth(
5559 "GET http://www.example.com/ HTTP/1.1\r\n"
5560 "Host: www.example.com\r\n"
5561 "Proxy-Connection: keep-alive\r\n"
5562 "Proxy-Authorization: auth_token\r\n\r\n");
5563 const MockWrite kGetAuthThroughProxy(
5564 "GET http://www.example.com/ HTTP/1.1\r\n"
5565 "Host: www.example.com\r\n"
5566 "Proxy-Connection: keep-alive\r\n"
5567 "Authorization: auth_token\r\n\r\n");
5568 const MockWrite kGetAuthWithProxyAuth(
5569 "GET http://www.example.com/ HTTP/1.1\r\n"
5570 "Host: www.example.com\r\n"
5571 "Proxy-Connection: keep-alive\r\n"
5572 "Proxy-Authorization: auth_token\r\n"
5573 "Authorization: auth_token\r\n\r\n");
5574 const MockWrite kConnect(
5575 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5576 "Host: www.example.com\r\n"
5577 "Proxy-Connection: keep-alive\r\n\r\n");
5578 const MockWrite kConnectProxyAuth(
5579 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5580 "Host: www.example.com\r\n"
5581 "Proxy-Connection: keep-alive\r\n"
5582 "Proxy-Authorization: auth_token\r\n\r\n");
5583
5584 const MockRead kSuccess(
5585 "HTTP/1.1 200 OK\r\n"
5586 "Content-Type: text/html; charset=iso-8859-1\r\n"
5587 "Content-Length: 3\r\n\r\n"
5588 "Yes");
5589 const MockRead kFailure(
5590 "Should not be called.");
5591 const MockRead kServerChallenge(
5592 "HTTP/1.1 401 Unauthorized\r\n"
5593 "WWW-Authenticate: Mock realm=server\r\n"
5594 "Content-Type: text/html; charset=iso-8859-1\r\n"
5595 "Content-Length: 14\r\n\r\n"
5596 "Unauthorized\r\n");
5597 const MockRead kProxyChallenge(
5598 "HTTP/1.1 407 Unauthorized\r\n"
5599 "Proxy-Authenticate: Mock realm=proxy\r\n"
5600 "Proxy-Connection: close\r\n"
5601 "Content-Type: text/html; charset=iso-8859-1\r\n"
5602 "Content-Length: 14\r\n\r\n"
5603 "Unauthorized\r\n");
5604 const MockRead kProxyConnected(
5605 "HTTP/1.1 200 Connection Established\r\n\r\n");
5606
5607 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5608 // no constructors, but the C++ compiler on Windows warns about
5609 // unspecified data in compound literals. So, moved to using constructors,
5610 // and TestRound's created with the default constructor should not be used.
5611 struct TestRound {
5612 TestRound()
5613 : expected_rv(ERR_UNEXPECTED),
5614 extra_write(NULL),
5615 extra_read(NULL) {
5616 }
5617 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5618 int expected_rv_arg)
5619 : write(write_arg),
5620 read(read_arg),
5621 expected_rv(expected_rv_arg),
5622 extra_write(NULL),
5623 extra_read(NULL) {
5624 }
5625 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5626 int expected_rv_arg, const MockWrite* extra_write_arg,
5627 const MockWrite* extra_read_arg)
5628 : write(write_arg),
5629 read(read_arg),
5630 expected_rv(expected_rv_arg),
5631 extra_write(extra_write_arg),
5632 extra_read(extra_read_arg) {
5633 }
5634 MockWrite write;
5635 MockRead read;
5636 int expected_rv;
5637 const MockWrite* extra_write;
5638 const MockRead* extra_read;
5639 };
5640
5641 static const int kNoSSL = 500;
5642
5643 struct TestConfig {
5644 const char* proxy_url;
5645 AuthTiming proxy_auth_timing;
5646 int proxy_auth_rv;
5647 const char* server_url;
5648 AuthTiming server_auth_timing;
5649 int server_auth_rv;
5650 int num_auth_rounds;
5651 int first_ssl_round;
5652 TestRound rounds[3];
5653 } test_configs[] = {
5654 // Non-authenticating HTTP server with a direct connection.
5655 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5656 { TestRound(kGet, kSuccess, OK)}},
5657 // Authenticating HTTP server with a direct connection.
5658 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5659 { TestRound(kGet, kServerChallenge, OK),
5660 TestRound(kGetAuth, kSuccess, OK)}},
5661 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5662 { TestRound(kGet, kServerChallenge, OK),
5663 TestRound(kGetAuth, kFailure, kAuthErr)}},
5664 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5665 { TestRound(kGet, kServerChallenge, OK),
5666 TestRound(kGetAuth, kSuccess, OK)}},
5667 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5668 { TestRound(kGet, kServerChallenge, OK),
5669 TestRound(kGetAuth, kFailure, kAuthErr)}},
5670 // Non-authenticating HTTP server through a non-authenticating proxy.
5671 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5672 { TestRound(kGetProxy, kSuccess, OK)}},
5673 // Authenticating HTTP server through a non-authenticating proxy.
5674 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5675 { TestRound(kGetProxy, kServerChallenge, OK),
5676 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5677 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5678 { TestRound(kGetProxy, kServerChallenge, OK),
5679 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5680 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5681 { TestRound(kGetProxy, kServerChallenge, OK),
5682 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5683 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5684 { TestRound(kGetProxy, kServerChallenge, OK),
5685 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5686 // Non-authenticating HTTP server through an authenticating proxy.
5687 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5688 { TestRound(kGetProxy, kProxyChallenge, OK),
5689 TestRound(kGetProxyAuth, kSuccess, OK)}},
5690 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5691 { TestRound(kGetProxy, kProxyChallenge, OK),
5692 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5693 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5694 { TestRound(kGetProxy, kProxyChallenge, OK),
5695 TestRound(kGetProxyAuth, kSuccess, OK)}},
5696 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5697 { TestRound(kGetProxy, kProxyChallenge, OK),
5698 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5699 // Authenticating HTTP server through an authenticating proxy.
5700 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5701 { TestRound(kGetProxy, kProxyChallenge, OK),
5702 TestRound(kGetProxyAuth, kServerChallenge, OK),
5703 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5704 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5705 { TestRound(kGetProxy, kProxyChallenge, OK),
5706 TestRound(kGetProxyAuth, kServerChallenge, OK),
5707 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5708 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5709 { TestRound(kGetProxy, kProxyChallenge, OK),
5710 TestRound(kGetProxyAuth, kServerChallenge, OK),
5711 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5712 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5713 { TestRound(kGetProxy, kProxyChallenge, OK),
5714 TestRound(kGetProxyAuth, kServerChallenge, OK),
5715 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5716 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5717 { TestRound(kGetProxy, kProxyChallenge, OK),
5718 TestRound(kGetProxyAuth, kServerChallenge, OK),
5719 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5720 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5721 { TestRound(kGetProxy, kProxyChallenge, OK),
5722 TestRound(kGetProxyAuth, kServerChallenge, OK),
5723 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5724 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5725 { TestRound(kGetProxy, kProxyChallenge, OK),
5726 TestRound(kGetProxyAuth, kServerChallenge, OK),
5727 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5728 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5729 { TestRound(kGetProxy, kProxyChallenge, OK),
5730 TestRound(kGetProxyAuth, kServerChallenge, OK),
5731 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5732 // Non-authenticating HTTPS server with a direct connection.
5733 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5734 { TestRound(kGet, kSuccess, OK)}},
5735 // Authenticating HTTPS server with a direct connection.
5736 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5737 { TestRound(kGet, kServerChallenge, OK),
5738 TestRound(kGetAuth, kSuccess, OK)}},
5739 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5740 { TestRound(kGet, kServerChallenge, OK),
5741 TestRound(kGetAuth, kFailure, kAuthErr)}},
5742 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5743 { TestRound(kGet, kServerChallenge, OK),
5744 TestRound(kGetAuth, kSuccess, OK)}},
5745 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5746 { TestRound(kGet, kServerChallenge, OK),
5747 TestRound(kGetAuth, kFailure, kAuthErr)}},
5748 // Non-authenticating HTTPS server with a non-authenticating proxy.
5749 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5750 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5751 // Authenticating HTTPS server through a non-authenticating proxy.
5752 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5753 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5754 TestRound(kGetAuth, kSuccess, OK)}},
5755 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5756 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5757 TestRound(kGetAuth, kFailure, kAuthErr)}},
5758 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5759 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5760 TestRound(kGetAuth, kSuccess, OK)}},
5761 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5762 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5763 TestRound(kGetAuth, kFailure, kAuthErr)}},
5764 // Non-Authenticating HTTPS server through an authenticating proxy.
5765 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5766 { TestRound(kConnect, kProxyChallenge, OK),
5767 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5768 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5769 { TestRound(kConnect, kProxyChallenge, OK),
5770 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5771 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5772 { TestRound(kConnect, kProxyChallenge, OK),
5773 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5774 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5775 { TestRound(kConnect, kProxyChallenge, OK),
5776 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5777 // Authenticating HTTPS server through an authenticating proxy.
5778 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5779 { TestRound(kConnect, kProxyChallenge, OK),
5780 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5781 &kGet, &kServerChallenge),
5782 TestRound(kGetAuth, kSuccess, OK)}},
5783 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5784 { TestRound(kConnect, kProxyChallenge, OK),
5785 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5786 &kGet, &kServerChallenge),
5787 TestRound(kGetAuth, kFailure, kAuthErr)}},
5788 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5789 { TestRound(kConnect, kProxyChallenge, OK),
5790 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5791 &kGet, &kServerChallenge),
5792 TestRound(kGetAuth, kSuccess, OK)}},
5793 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5794 { TestRound(kConnect, kProxyChallenge, OK),
5795 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5796 &kGet, &kServerChallenge),
5797 TestRound(kGetAuth, kFailure, kAuthErr)}},
5798 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5799 { TestRound(kConnect, kProxyChallenge, OK),
5800 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5801 &kGet, &kServerChallenge),
5802 TestRound(kGetAuth, kSuccess, OK)}},
5803 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5804 { TestRound(kConnect, kProxyChallenge, OK),
5805 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5806 &kGet, &kServerChallenge),
5807 TestRound(kGetAuth, kFailure, kAuthErr)}},
5808 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5809 { TestRound(kConnect, kProxyChallenge, OK),
5810 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5811 &kGet, &kServerChallenge),
5812 TestRound(kGetAuth, kSuccess, OK)}},
5813 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5814 { TestRound(kConnect, kProxyChallenge, OK),
5815 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5816 &kGet, &kServerChallenge),
5817 TestRound(kGetAuth, kFailure, kAuthErr)}},
5818 };
5819
5820 SessionDependencies session_deps;
5821 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005822 HttpAuthHandlerMock::Factory* auth_factory(
5823 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155824 session_deps.http_auth_handler_factory.reset(auth_factory);
5825
5826 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5827 const TestConfig& test_config = test_configs[i];
5828 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005829 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155830 std::string auth_challenge = "Mock realm=proxy";
5831 GURL origin(test_config.proxy_url);
5832 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5833 auth_challenge.end());
5834 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5835 origin, BoundNetLog());
5836 auth_handler->SetGenerateExpectation(
5837 test_config.proxy_auth_timing == AUTH_ASYNC,
5838 test_config.proxy_auth_rv);
[email protected]3fd9dae2010-06-21 11:39:005839 auth_handler->SetResolveExpectation(HttpAuthHandlerMock::RESOLVE_SKIP);
[email protected]044de0642010-06-17 10:42:155840 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5841 }
5842 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005843 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155844 std::string auth_challenge = "Mock realm=server";
5845 GURL origin(test_config.server_url);
5846 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5847 auth_challenge.end());
5848 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5849 origin, BoundNetLog());
5850 auth_handler->SetGenerateExpectation(
5851 test_config.server_auth_timing == AUTH_ASYNC,
5852 test_config.server_auth_rv);
[email protected]3fd9dae2010-06-21 11:39:005853 auth_handler->SetResolveExpectation(HttpAuthHandlerMock::RESOLVE_SKIP);
[email protected]044de0642010-06-17 10:42:155854 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5855 }
5856 if (test_config.proxy_url) {
5857 session_deps.proxy_service =
5858 CreateFixedProxyService(test_config.proxy_url);
5859 } else {
5860 session_deps.proxy_service = ProxyService::CreateNull();
5861 }
5862
5863 HttpRequestInfo request;
5864 request.method = "GET";
5865 request.url = GURL(test_config.server_url);
5866 request.load_flags = 0;
5867
5868 scoped_ptr<HttpTransaction> trans(
5869 new HttpNetworkTransaction(CreateSession(&session_deps)));
5870
5871 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5872 const TestRound& read_write_round = test_config.rounds[round];
5873
5874 // Set up expected reads and writes.
5875 MockRead reads[2];
5876 reads[0] = read_write_round.read;
5877 size_t length_reads = 1;
5878 if (read_write_round.extra_read) {
5879 reads[1] = *read_write_round.extra_read;
5880 length_reads = 2;
5881 }
5882
5883 MockWrite writes[2];
5884 writes[0] = read_write_round.write;
5885 size_t length_writes = 1;
5886 if (read_write_round.extra_write) {
5887 writes[1] = *read_write_round.extra_write;
5888 length_writes = 2;
5889 }
5890 StaticSocketDataProvider data_provider(
5891 reads, length_reads, writes, length_writes);
5892 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
5893
5894 // Add an SSL sequence if necessary.
5895 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
5896 if (round >= test_config.first_ssl_round)
5897 session_deps.socket_factory.AddSSLSocketDataProvider(
5898 &ssl_socket_data_provider);
5899
5900 // Start or restart the transaction.
5901 TestCompletionCallback callback;
5902 int rv;
5903 if (round == 0) {
5904 rv = trans->Start(&request, &callback, BoundNetLog());
5905 } else {
5906 rv = trans->RestartWithAuth(L"foo", L"bar", &callback);
5907 }
5908 if (rv == ERR_IO_PENDING)
5909 rv = callback.WaitForResult();
5910
5911 // Compare results with expected data.
5912 EXPECT_EQ(read_write_round.expected_rv, rv);
5913 const HttpResponseInfo* response = trans->GetResponseInfo();
5914 if (read_write_round.expected_rv == OK) {
5915 EXPECT_FALSE(response == NULL);
5916 } else {
5917 EXPECT_TRUE(response == NULL);
5918 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
5919 continue;
5920 }
5921 if (round + 1 < test_config.num_auth_rounds) {
5922 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5923 } else {
5924 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5925 }
5926 }
[email protected]e5ae96a2010-04-14 20:12:455927 }
5928}
5929
[email protected]aeaca1f2010-04-20 22:05:215930class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5931 public:
[email protected]06650c52010-06-03 00:49:175932 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:215933 : fail_all_(fail_all) {
5934 }
5935
5936 virtual MockRead GetNextRead() {
5937 if (fail_all_)
5938 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5939
5940 return MockRead(false /* async */,
5941 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5942 }
5943
5944 virtual MockWriteResult OnWrite(const std::string& data) {
5945 return MockWriteResult(false /* async */, data.size());
5946 }
5947
5948 void Reset() {
5949 }
5950
5951 private:
5952 const bool fail_all_;
5953};
5954
5955// Test that we restart a connection when we see a decompression failure from
5956// the peer during the handshake. (In the real world we'll restart with SSLv3
5957// and we won't offer DEFLATE in that case.)
5958TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5959 HttpRequestInfo request;
5960 request.method = "GET";
5961 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5962 request.load_flags = 0;
5963
5964 SessionDependencies session_deps;
5965 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5966 false /* fail all reads */);
5967 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5968 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115969 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215970 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5971 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5972 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5973 session_deps.socket_factory.AddSSLSocketDataProvider(
5974 &ssl_socket_data_provider1);
5975 session_deps.socket_factory.AddSSLSocketDataProvider(
5976 &ssl_socket_data_provider2);
5977
5978 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5979 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5980 TestCompletionCallback callback;
5981
[email protected]5a1d7ca2010-04-28 20:12:275982 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215983 EXPECT_EQ(ERR_IO_PENDING, rv);
5984 EXPECT_EQ(OK, callback.WaitForResult());
5985
5986 const HttpResponseInfo* response = trans->GetResponseInfo();
5987 ASSERT_TRUE(response != NULL);
5988 ASSERT_TRUE(response->headers != NULL);
5989 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5990
5991 std::string response_data;
5992 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5993 EXPECT_EQ("ok.", response_data);
5994}
5995
5996// Test that we restart a connection if we get a decompression failure from the
5997// peer while reading the first bytes from the connection. This occurs when the
5998// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5999// in the handshake.
6000TEST_F(HttpNetworkTransactionTest,
6001 RestartAfterTLSDecompressionFailureWithFalseStart) {
6002 HttpRequestInfo request;
6003 request.method = "GET";
6004 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6005 request.load_flags = 0;
6006
6007 SessionDependencies session_deps;
6008 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6009 true /* fail all reads */);
6010 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6011 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6012 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6013 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6014 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6015 session_deps.socket_factory.AddSSLSocketDataProvider(
6016 &ssl_socket_data_provider1);
6017 session_deps.socket_factory.AddSSLSocketDataProvider(
6018 &ssl_socket_data_provider2);
6019
6020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6021 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6022 TestCompletionCallback callback;
6023
[email protected]5a1d7ca2010-04-28 20:12:276024 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216025 EXPECT_EQ(ERR_IO_PENDING, rv);
6026 EXPECT_EQ(OK, callback.WaitForResult());
6027
6028 const HttpResponseInfo* response = trans->GetResponseInfo();
6029 ASSERT_TRUE(response != NULL);
6030 ASSERT_TRUE(response->headers != NULL);
6031 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6032
6033 std::string response_data;
6034 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6035 EXPECT_EQ("ok.", response_data);
6036}
6037
[email protected]65041fa2010-05-21 06:56:536038// This tests the case that a request is issued via http instead of spdy after
6039// npn is negotiated.
6040TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6041 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6042 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6043 SessionDependencies session_deps;
6044 HttpRequestInfo request;
6045 request.method = "GET";
6046 request.url = GURL("https://www.google.com/");
6047 request.load_flags = 0;
6048
6049 MockWrite data_writes[] = {
6050 MockWrite("GET / HTTP/1.1\r\n"
6051 "Host: www.google.com\r\n"
6052 "Connection: keep-alive\r\n\r\n"),
6053 };
6054
6055 MockRead data_reads[] = {
6056 MockRead("HTTP/1.1 200 OK\r\n"),
6057 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
6058 MockRead("hello world"),
6059 MockRead(false, OK),
6060 };
6061
6062 SSLSocketDataProvider ssl(true, OK);
6063 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6064 ssl.next_proto = "http/1.1";
6065
6066 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6067
6068 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6069 data_writes, arraysize(data_writes));
6070 session_deps.socket_factory.AddSocketDataProvider(&data);
6071
6072 TestCompletionCallback callback;
6073
6074 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6075 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6076
6077 int rv = trans->Start(&request, &callback, BoundNetLog());
6078
6079 EXPECT_EQ(ERR_IO_PENDING, rv);
6080 EXPECT_EQ(OK, callback.WaitForResult());
6081
6082 const HttpResponseInfo* response = trans->GetResponseInfo();
6083 ASSERT_TRUE(response != NULL);
6084 ASSERT_TRUE(response->headers != NULL);
6085 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6086
6087 std::string response_data;
6088 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6089 EXPECT_EQ("hello world", response_data);
6090
6091 EXPECT_FALSE(response->was_fetched_via_spdy);
6092 EXPECT_TRUE(response->was_npn_negotiated);
6093
6094 HttpNetworkTransaction::SetNextProtos("");
6095 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6096}
[email protected]26ef6582010-06-24 02:30:476097
6098TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6099 // Simulate the SSL handshake completing with an NPN negotiation
6100 // followed by an immediate server closing of the socket.
6101 // Fix crash: http://crbug.com/46369
6102 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6103 HttpNetworkTransaction::SetNextProtos(
6104 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
6105 SessionDependencies session_deps;
6106
6107 HttpRequestInfo request;
6108 request.method = "GET";
6109 request.url = GURL("https://www.google.com/");
6110 request.load_flags = 0;
6111
6112 SSLSocketDataProvider ssl(true, OK);
6113 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6114 ssl.next_proto = "spdy/1";
6115 ssl.was_npn_negotiated = true;
6116 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6117
6118 MockWrite spdy_writes[] = {
6119 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
6120 arraysize(kGetSyn)),
6121 };
6122
6123 MockRead spdy_reads[] = {
6124 MockRead(false, 0, 0) // Not async - return 0 immediately.
6125 };
6126
6127 scoped_refptr<DelayedSocketData> spdy_data(
6128 new DelayedSocketData(
6129 0, // don't wait in this case, immediate hangup.
6130 spdy_reads, arraysize(spdy_reads),
6131 spdy_writes, arraysize(spdy_writes)));
6132 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6133
6134 TestCompletionCallback callback;
6135
6136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6137 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6138
6139 int rv = trans->Start(&request, &callback, BoundNetLog());
6140 EXPECT_EQ(ERR_IO_PENDING, rv);
6141 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6142
6143 HttpNetworkTransaction::SetNextProtos("");
6144 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6145}
[email protected]89ceba9a2009-03-21 03:46:066146} // namespace net