blob: 32656bf257e0fc097ddbaede71c83fbb843682a7 [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]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4031#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5633#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5734#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3835#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5337#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1138#include "net/proxy/proxy_resolver.h"
39#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4440#include "net/socket/client_socket_factory.h"
41#include "net/socket/socket_test_util.h"
42#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5443#include "net/spdy/spdy_framer.h"
44#include "net/spdy/spdy_session.h"
45#include "net/spdy/spdy_session_pool.h"
46#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5247#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1548#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5249
50//-----------------------------------------------------------------------------
51
[email protected]13c8a092010-07-29 06:15:4452namespace {
53
54const string16 kBar(ASCIIToUTF16("bar"));
55const string16 kBar2(ASCIIToUTF16("bar2"));
56const string16 kBar3(ASCIIToUTF16("bar3"));
57const string16 kBaz(ASCIIToUTF16("baz"));
58const string16 kFirst(ASCIIToUTF16("first"));
59const string16 kFoo(ASCIIToUTF16("foo"));
60const string16 kFoo2(ASCIIToUTF16("foo2"));
61const string16 kFoo3(ASCIIToUTF16("foo3"));
62const string16 kFou(ASCIIToUTF16("fou"));
63const string16 kSecond(ASCIIToUTF16("second"));
64const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
65const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
66
67} // namespace
68
[email protected]89ceba9a2009-03-21 03:46:0669namespace net {
70
[email protected]e44de5d2009-06-05 20:12:4571// Helper to manage the lifetimes of the dependencies for a
72// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4473struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5974 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4275 SessionDependencies()
76 : host_resolver(new MockHostResolver),
[email protected]ebeefff32010-09-15 05:10:0277 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1078 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0879 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5480 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5481 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5982
83 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4584 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4285 : host_resolver(new MockHostResolver),
86 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1087 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0888 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5489 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5490 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5991
[email protected]73c45322010-10-01 23:57:5492 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0993 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4294 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5995 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5096 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:5497 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:5998};
99
[email protected]228ff742009-06-05 01:19:59100HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54101 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]2db580532010-10-08 14:32:37102 NULL /* dnsrr_resolver */,
[email protected]7ab5bbd12010-10-19 13:33:21103 NULL /* ssl_host_info_factory */,
[email protected]80d6524d2009-08-18 03:58:09104 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42105 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10106 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56107 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17108 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44109 NULL,
[email protected]a7ea8832010-07-12 17:54:54110 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14111}
112
[email protected]89836e22008-09-25 20:33:42113class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52114 public:
[email protected]2ff8b312010-04-26 22:20:54115 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50116 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
117 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54118 spdy::SpdyFramer::set_enable_compression_default(false);
119 }
120
[email protected]0e75a732008-10-16 20:36:09121 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50122 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
123 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54124 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09125 // Empty the current queue.
126 MessageLoop::current()->RunAllPending();
127 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50128 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
129 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09130 }
131
[email protected]3d2a59b2008-09-26 19:44:25132 protected:
133 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52134
[email protected]ff007e162009-05-23 09:13:15135 struct SimpleGetHelperResult {
136 int rv;
137 std::string status_line;
138 std::string response_data;
139 };
initial.commit586acc5fe2008-07-26 22:42:52140
[email protected]31a2bfe2010-02-09 08:03:39141 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
142 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15143 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52144
[email protected]228ff742009-06-05 01:19:59145 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40146 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43147 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52148
[email protected]ff007e162009-05-23 09:13:15149 HttpRequestInfo request;
150 request.method = "GET";
151 request.url = GURL("http://www.google.com/");
152 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]31a2bfe2010-02-09 08:03:39154 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59155 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52156
[email protected]ff007e162009-05-23 09:13:15157 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]169d0012010-05-10 23:20:12159 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40160 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12161 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15162 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]ff007e162009-05-23 09:13:15164 out.rv = callback.WaitForResult();
165 if (out.rv != OK)
166 return out;
167
168 const HttpResponseInfo* response = trans->GetResponseInfo();
169 EXPECT_TRUE(response != NULL);
170
171 EXPECT_TRUE(response->headers != NULL);
172 out.status_line = response->headers->GetStatusLine();
173
174 rv = ReadTransaction(trans.get(), &out.response_data);
175 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39176 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12177 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
178 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39179 ExpectLogContainsSomewhere(
180 log.entries(), pos,
181 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
182 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15183
[email protected]3deb9a52010-11-11 00:24:40184 CapturingNetLog::Entry entry = log.entries()[pos];
185 NetLogHttpRequestParameter* request_params =
186 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
187 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
188 EXPECT_EQ("Host: www.google.com\r\n"
189 "Connection: keep-alive\r\n\r\n",
190 request_params->GetHeaders().ToString());
191
[email protected]aecfbf22008-10-16 02:02:47192 return out;
[email protected]ff007e162009-05-23 09:13:15193 }
initial.commit586acc5fe2008-07-26 22:42:52194
[email protected]ff007e162009-05-23 09:13:15195 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
196 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52197
[email protected]ff007e162009-05-23 09:13:15198 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15199};
[email protected]231d5a32008-09-13 00:45:27200
[email protected]15a5ccf82008-10-23 19:57:43201// Fill |str| with a long header list that consumes >= |size| bytes.
202void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19203 const char* row =
204 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
205 const int sizeof_row = strlen(row);
206 const int num_rows = static_cast<int>(
207 ceil(static_cast<float>(size) / sizeof_row));
208 const int sizeof_data = num_rows * sizeof_row;
209 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43210 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51211
[email protected]4ddaf2502008-10-23 18:26:19212 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43213 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19214}
215
[email protected]385a4672009-03-11 22:21:29216// Alternative functions that eliminate randomness and dependency on the local
217// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20218void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29219 static const uint8 bytes[] = {
220 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
221 };
222 static size_t current_byte = 0;
223 for (size_t i = 0; i < n; ++i) {
224 output[i] = bytes[current_byte++];
225 current_byte %= arraysize(bytes);
226 }
227}
228
[email protected]fe2bc6a2009-03-23 16:52:20229void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29230 static const uint8 bytes[] = {
231 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
232 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
233 };
234 static size_t current_byte = 0;
235 for (size_t i = 0; i < n; ++i) {
236 output[i] = bytes[current_byte++];
237 current_byte %= arraysize(bytes);
238 }
239}
240
[email protected]fe2bc6a2009-03-23 16:52:20241std::string MockGetHostName() {
242 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29243}
244
[email protected]e60e47a2010-07-14 03:37:18245template<typename ParentPool>
246class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31247 public:
[email protected]e60e47a2010-07-14 03:37:18248 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
249
[email protected]d80a4322009-08-14 07:07:49250 const std::string last_group_name_received() const {
251 return last_group_name_;
252 }
253
[email protected]684970b2009-08-14 04:54:46254 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49255 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31256 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31257 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46258 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53259 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31260 last_group_name_ = group_name;
261 return ERR_IO_PENDING;
262 }
[email protected]04e5be32009-06-26 20:00:31263 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21264 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31265 virtual void ReleaseSocket(const std::string& group_name,
266 ClientSocket* socket) {}
267 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31268 virtual int IdleSocketCount() const {
269 return 0;
270 }
271 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
272 return 0;
273 }
274 virtual LoadState GetLoadState(const std::string& group_name,
275 const ClientSocketHandle* handle) const {
276 return LOAD_STATE_IDLE;
277 }
[email protected]a796bcec2010-03-22 17:17:26278 virtual base::TimeDelta ConnectionTimeout() const {
279 return base::TimeDelta();
280 }
[email protected]d80a4322009-08-14 07:07:49281
282 private:
[email protected]04e5be32009-06-26 20:00:31283 std::string last_group_name_;
284};
285
[email protected]2d731a32010-04-29 01:04:06286typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11287CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13288typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
289CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06290typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11291CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18292typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
293CaptureGroupNameSSLSocketPool;
294
295template<typename ParentPool>
296CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
297 HttpNetworkSession* session)
298 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
299
300template<>
[email protected]2df19bb2010-08-25 20:13:46301CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
302 HttpNetworkSession* session)
303 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
304 NULL, NULL) {}
305
306template<>
[email protected]e60e47a2010-07-14 03:37:18307CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
308 HttpNetworkSession* session)
309 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
[email protected]7ab5bbd12010-10-19 13:33:21310 NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11311
[email protected]231d5a32008-09-13 00:45:27312//-----------------------------------------------------------------------------
313
[email protected]dae22c52010-07-30 02:16:35314// This is the expected list of advertised protocols from the browser's NPN
315// list.
316static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
317
318// This is the expected return from a current server advertising SPDY.
319static const char kAlternateProtocolHttpHeader[] =
320 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
321
[email protected]231d5a32008-09-13 00:45:27322TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59323 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40324 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43325 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27326}
327
328TEST_F(HttpNetworkTransactionTest, SimpleGET) {
329 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35330 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
331 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42332 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27333 };
[email protected]31a2bfe2010-02-09 08:03:39334 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
335 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42336 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27337 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
338 EXPECT_EQ("hello world", out.response_data);
339}
340
341// Response with no status line.
342TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42345 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27346 };
[email protected]31a2bfe2010-02-09 08:03:39347 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
348 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42349 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27350 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
351 EXPECT_EQ("hello world", out.response_data);
352}
353
354// Allow up to 4 bytes of junk to precede status line.
355TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
356 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35357 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42358 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27359 };
[email protected]31a2bfe2010-02-09 08:03:39360 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
361 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42362 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27363 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
364 EXPECT_EQ("DATA", out.response_data);
365}
366
367// Allow up to 4 bytes of junk to precede status line.
368TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
369 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35370 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42371 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27372 };
[email protected]31a2bfe2010-02-09 08:03:39373 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
374 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42375 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27376 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
377 EXPECT_EQ("DATA", out.response_data);
378}
379
380// Beyond 4 bytes of slop and it should fail to find a status line.
381TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
382 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35383 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42384 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27385 };
[email protected]31a2bfe2010-02-09 08:03:39386 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
387 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42388 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25389 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
390 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27391}
392
393// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
394TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
395 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35396 MockRead("\n"),
397 MockRead("\n"),
398 MockRead("Q"),
399 MockRead("J"),
400 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42401 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27402 };
[email protected]31a2bfe2010-02-09 08:03:39403 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
404 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42405 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27406 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
407 EXPECT_EQ("DATA", out.response_data);
408}
409
410// Close the connection before enough bytes to have a status line.
411TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
412 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35413 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42414 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27415 };
[email protected]31a2bfe2010-02-09 08:03:39416 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
417 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42418 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27419 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
420 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52421}
422
[email protected]f9d44aa2008-09-23 23:57:17423// Simulate a 204 response, lacking a Content-Length header, sent over a
424// persistent connection. The response should still terminate since a 204
425// cannot have a response body.
426TEST_F(HttpNetworkTransactionTest, StopsReading204) {
427 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35428 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
429 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42430 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17431 };
[email protected]31a2bfe2010-02-09 08:03:39432 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
433 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42434 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17435 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
436 EXPECT_EQ("", out.response_data);
437}
438
[email protected]0877e3d2009-10-17 22:29:57439// A simple request using chunked encoding with some extra data after.
440// (Like might be seen in a pipelined response.)
441TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
442 MockRead data_reads[] = {
443 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
444 MockRead("5\r\nHello\r\n"),
445 MockRead("1\r\n"),
446 MockRead(" \r\n"),
447 MockRead("5\r\nworld\r\n"),
448 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
449 MockRead(false, OK),
450 };
[email protected]31a2bfe2010-02-09 08:03:39451 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
452 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57453 EXPECT_EQ(OK, out.rv);
454 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
455 EXPECT_EQ("Hello world", out.response_data);
456}
457
[email protected]9fe44f52010-09-23 18:36:00458// Next tests deal with http://crbug.com/56344.
459
460TEST_F(HttpNetworkTransactionTest,
461 MultipleContentLengthHeadersNoTransferEncoding) {
462 MockRead data_reads[] = {
463 MockRead("HTTP/1.1 200 OK\r\n"),
464 MockRead("Content-Length: 10\r\n"),
465 MockRead("Content-Length: 5\r\n\r\n"),
466 };
467 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
468 arraysize(data_reads));
469 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
470}
471
472TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04473 DuplicateContentLengthHeadersNoTransferEncoding) {
474 MockRead data_reads[] = {
475 MockRead("HTTP/1.1 200 OK\r\n"),
476 MockRead("Content-Length: 5\r\n"),
477 MockRead("Content-Length: 5\r\n\r\n"),
478 MockRead("Hello"),
479 };
480 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
481 arraysize(data_reads));
482 EXPECT_EQ(OK, out.rv);
483 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
484 EXPECT_EQ("Hello", out.response_data);
485}
486
487TEST_F(HttpNetworkTransactionTest,
488 ComplexContentLengthHeadersNoTransferEncoding) {
489 // More than 2 dupes.
490 {
491 MockRead data_reads[] = {
492 MockRead("HTTP/1.1 200 OK\r\n"),
493 MockRead("Content-Length: 5\r\n"),
494 MockRead("Content-Length: 5\r\n"),
495 MockRead("Content-Length: 5\r\n\r\n"),
496 MockRead("Hello"),
497 };
498 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
499 arraysize(data_reads));
500 EXPECT_EQ(OK, out.rv);
501 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
502 EXPECT_EQ("Hello", out.response_data);
503 }
504 // HTTP/1.0
505 {
506 MockRead data_reads[] = {
507 MockRead("HTTP/1.0 200 OK\r\n"),
508 MockRead("Content-Length: 5\r\n"),
509 MockRead("Content-Length: 5\r\n"),
510 MockRead("Content-Length: 5\r\n\r\n"),
511 MockRead("Hello"),
512 };
513 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
514 arraysize(data_reads));
515 EXPECT_EQ(OK, out.rv);
516 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
517 EXPECT_EQ("Hello", out.response_data);
518 }
519 // 2 dupes and one mismatched.
520 {
521 MockRead data_reads[] = {
522 MockRead("HTTP/1.1 200 OK\r\n"),
523 MockRead("Content-Length: 10\r\n"),
524 MockRead("Content-Length: 10\r\n"),
525 MockRead("Content-Length: 5\r\n\r\n"),
526 };
527 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
528 arraysize(data_reads));
529 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
530 }
531}
532
533TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00534 MultipleContentLengthHeadersTransferEncoding) {
535 MockRead data_reads[] = {
536 MockRead("HTTP/1.1 200 OK\r\n"),
537 MockRead("Content-Length: 666\r\n"),
538 MockRead("Content-Length: 1337\r\n"),
539 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
540 MockRead("5\r\nHello\r\n"),
541 MockRead("1\r\n"),
542 MockRead(" \r\n"),
543 MockRead("5\r\nworld\r\n"),
544 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
545 MockRead(false, OK),
546 };
547 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
548 arraysize(data_reads));
549 EXPECT_EQ(OK, out.rv);
550 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
551 EXPECT_EQ("Hello world", out.response_data);
552}
553
[email protected]ef0faf2e72009-03-05 23:27:23554// Do a request using the HEAD method. Verify that we don't try to read the
555// message body (since HEAD has none).
556TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59557 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40558 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43559 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23560
[email protected]1c773ea12009-04-28 19:58:42561 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23562 request.method = "HEAD";
563 request.url = GURL("http://www.google.com/");
564 request.load_flags = 0;
565
566 MockWrite data_writes1[] = {
567 MockWrite("HEAD / HTTP/1.1\r\n"
568 "Host: www.google.com\r\n"
569 "Connection: keep-alive\r\n"
570 "Content-Length: 0\r\n\r\n"),
571 };
572 MockRead data_reads1[] = {
573 MockRead("HTTP/1.1 404 Not Found\r\n"),
574 MockRead("Server: Blah\r\n"),
575 MockRead("Content-Length: 1234\r\n\r\n"),
576
577 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42578 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23579 };
580
[email protected]31a2bfe2010-02-09 08:03:39581 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
582 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59583 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23584
585 TestCompletionCallback callback1;
586
[email protected]5a1d7ca2010-04-28 20:12:27587 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42588 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23589
590 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42591 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23592
[email protected]1c773ea12009-04-28 19:58:42593 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23594 EXPECT_FALSE(response == NULL);
595
596 // Check that the headers got parsed.
597 EXPECT_TRUE(response->headers != NULL);
598 EXPECT_EQ(1234, response->headers->GetContentLength());
599 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
600
601 std::string server_header;
602 void* iter = NULL;
603 bool has_server_header = response->headers->EnumerateHeader(
604 &iter, "Server", &server_header);
605 EXPECT_TRUE(has_server_header);
606 EXPECT_EQ("Blah", server_header);
607
608 // Reading should give EOF right away, since there is no message body
609 // (despite non-zero content-length).
610 std::string response_data;
611 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42612 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23613 EXPECT_EQ("", response_data);
614}
615
initial.commit586acc5fe2008-07-26 22:42:52616TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59617 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52619
620 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35621 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
622 MockRead("hello"),
623 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
624 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42625 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52626 };
[email protected]31a2bfe2010-02-09 08:03:39627 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59628 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52629
[email protected]0b0bf032010-09-21 18:08:50630 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52631 "hello", "world"
632 };
633
634 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43635 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52636
[email protected]1c773ea12009-04-28 19:58:42637 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52638 request.method = "GET";
639 request.url = GURL("http://www.google.com/");
640 request.load_flags = 0;
641
642 TestCompletionCallback callback;
643
[email protected]5a1d7ca2010-04-28 20:12:27644 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42645 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52646
647 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42648 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52649
[email protected]1c773ea12009-04-28 19:58:42650 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52651 EXPECT_TRUE(response != NULL);
652
653 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25654 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52655
656 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57657 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42658 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25659 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52660 }
661}
662
663TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59664 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40665 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43666 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52667
[email protected]1c773ea12009-04-28 19:58:42668 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52669 request.method = "POST";
670 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42671 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52672 request.upload_data->AppendBytes("foo", 3);
673 request.load_flags = 0;
674
675 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35676 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
677 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
678 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42679 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52680 };
[email protected]31a2bfe2010-02-09 08:03:39681 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59682 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52683
684 TestCompletionCallback callback;
685
[email protected]5a1d7ca2010-04-28 20:12:27686 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42687 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52688
689 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42690 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52691
[email protected]1c773ea12009-04-28 19:58:42692 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52693 EXPECT_TRUE(response != NULL);
694
695 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25696 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52697
698 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57699 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25701 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52702}
703
[email protected]3a2d3662009-03-27 03:49:14704// This test is almost the same as Ignores100 above, but the response contains
705// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57706// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14707TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59708 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40709 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43710 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14711
[email protected]1c773ea12009-04-28 19:58:42712 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14713 request.method = "GET";
714 request.url = GURL("http://www.foo.com/");
715 request.load_flags = 0;
716
717 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57718 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
719 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14720 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42721 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14722 };
[email protected]31a2bfe2010-02-09 08:03:39723 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59724 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14725
726 TestCompletionCallback callback;
727
[email protected]5a1d7ca2010-04-28 20:12:27728 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42729 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14730
731 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42732 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14733
[email protected]1c773ea12009-04-28 19:58:42734 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14735 EXPECT_TRUE(response != NULL);
736
737 EXPECT_TRUE(response->headers != NULL);
738 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
739
740 std::string response_data;
741 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42742 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14743 EXPECT_EQ("hello world", response_data);
744}
745
[email protected]ee9410e72010-01-07 01:42:38746TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
747 SessionDependencies session_deps;
748 scoped_ptr<HttpTransaction> trans(
749 new HttpNetworkTransaction(CreateSession(&session_deps)));
750
751 HttpRequestInfo request;
752 request.method = "POST";
753 request.url = GURL("http://www.foo.com/");
754 request.load_flags = 0;
755
756 MockRead data_reads[] = {
757 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
758 MockRead(true, 0),
759 };
[email protected]31a2bfe2010-02-09 08:03:39760 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38761 session_deps.socket_factory.AddSocketDataProvider(&data);
762
763 TestCompletionCallback callback;
764
[email protected]5a1d7ca2010-04-28 20:12:27765 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38766 EXPECT_EQ(ERR_IO_PENDING, rv);
767
768 rv = callback.WaitForResult();
769 EXPECT_EQ(OK, rv);
770
771 std::string response_data;
772 rv = ReadTransaction(trans.get(), &response_data);
773 EXPECT_EQ(OK, rv);
774 EXPECT_EQ("", response_data);
775}
776
777TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
778 SessionDependencies session_deps;
779 scoped_ptr<HttpTransaction> trans(
780 new HttpNetworkTransaction(CreateSession(&session_deps)));
781
782 HttpRequestInfo request;
783 request.method = "POST";
784 request.url = GURL("http://www.foo.com/");
785 request.load_flags = 0;
786
787 MockRead data_reads[] = {
788 MockRead(true, 0),
789 };
[email protected]31a2bfe2010-02-09 08:03:39790 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38791 session_deps.socket_factory.AddSocketDataProvider(&data);
792
793 TestCompletionCallback callback;
794
[email protected]5a1d7ca2010-04-28 20:12:27795 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38796 EXPECT_EQ(ERR_IO_PENDING, rv);
797
798 rv = callback.WaitForResult();
799 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
800}
801
[email protected]3d2a59b2008-09-26 19:44:25802// read_failure specifies a read failure that should cause the network
803// transaction to resend the request.
804void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
805 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59806 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52808
[email protected]1c773ea12009-04-28 19:58:42809 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52810 request.method = "GET";
811 request.url = GURL("http://www.foo.com/");
812 request.load_flags = 0;
813
814 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35815 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
816 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25817 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52818 };
[email protected]31a2bfe2010-02-09 08:03:39819 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59820 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52821
822 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35823 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
824 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42825 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52826 };
[email protected]31a2bfe2010-02-09 08:03:39827 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59828 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52829
830 const char* kExpectedResponseData[] = {
831 "hello", "world"
832 };
833
834 for (int i = 0; i < 2; ++i) {
835 TestCompletionCallback callback;
836
[email protected]5695b8c2009-09-30 21:36:43837 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52838
[email protected]5a1d7ca2010-04-28 20:12:27839 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42840 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52841
842 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42843 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52844
[email protected]1c773ea12009-04-28 19:58:42845 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52846 EXPECT_TRUE(response != NULL);
847
848 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25849 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52850
851 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57852 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42853 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25854 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52855 }
856}
[email protected]3d2a59b2008-09-26 19:44:25857
858TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42859 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25860 KeepAliveConnectionResendRequestTest(read_failure);
861}
862
863TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42864 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25865 KeepAliveConnectionResendRequestTest(read_failure);
866}
867
868TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59869 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40870 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43871 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25872
[email protected]1c773ea12009-04-28 19:58:42873 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25874 request.method = "GET";
875 request.url = GURL("http://www.google.com/");
876 request.load_flags = 0;
877
878 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42879 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35880 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
881 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42882 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25883 };
[email protected]31a2bfe2010-02-09 08:03:39884 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59885 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25886
887 TestCompletionCallback callback;
888
[email protected]5a1d7ca2010-04-28 20:12:27889 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42890 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25891
892 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42893 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25894
[email protected]1c773ea12009-04-28 19:58:42895 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25896 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25897}
898
899// What do various browsers do when the server closes a non-keepalive
900// connection without sending any response header or body?
901//
902// IE7: error page
903// Safari 3.1.2 (Windows): error page
904// Firefox 3.0.1: blank page
905// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42906// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
907// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25908TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
909 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42910 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35911 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
912 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42913 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25914 };
[email protected]31a2bfe2010-02-09 08:03:39915 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
916 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42917 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25918}
[email protected]038e9a32008-10-08 22:40:16919
[email protected]0b0bf032010-09-21 18:08:50920// Test that we correctly reuse a keep-alive connection after not explicitly
921// reading the body.
922TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13923 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27924 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]fc31d6a42010-06-24 18:05:13925
926 HttpRequestInfo request;
927 request.method = "GET";
928 request.url = GURL("http://www.foo.com/");
929 request.load_flags = 0;
930
[email protected]0b0bf032010-09-21 18:08:50931 // Note that because all these reads happen in the same
932 // StaticSocketDataProvider, it shows that the same socket is being reused for
933 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13934 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50935 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
936 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13937 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50938 MockRead("HTTP/1.1 302 Found\r\n"
939 "Content-Length: 0\r\n\r\n"),
940 MockRead("HTTP/1.1 302 Found\r\n"
941 "Content-Length: 5\r\n\r\n"
942 "hello"),
943 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
944 "Content-Length: 0\r\n\r\n"),
945 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
946 "Content-Length: 5\r\n\r\n"
947 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13948 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
949 MockRead("hello"),
950 };
951 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
952 session_deps.socket_factory.AddSocketDataProvider(&data1);
953
954 MockRead data2_reads[] = {
955 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
956 };
957 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
958 session_deps.socket_factory.AddSocketDataProvider(&data2);
959
[email protected]0b0bf032010-09-21 18:08:50960 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
961 std::string response_lines[kNumUnreadBodies];
962
963 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13964 TestCompletionCallback callback;
965
966 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
967
968 int rv = trans->Start(&request, &callback, BoundNetLog());
969 EXPECT_EQ(ERR_IO_PENDING, rv);
970
971 rv = callback.WaitForResult();
972 EXPECT_EQ(OK, rv);
973
974 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50975 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13976
[email protected]0b0bf032010-09-21 18:08:50977 ASSERT_TRUE(response->headers != NULL);
978 response_lines[i] = response->headers->GetStatusLine();
979
980 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13981 }
[email protected]0b0bf032010-09-21 18:08:50982
983 const char* const kStatusLines[] = {
984 "HTTP/1.1 204 No Content",
985 "HTTP/1.1 205 Reset Content",
986 "HTTP/1.1 304 Not Modified",
987 "HTTP/1.1 302 Found",
988 "HTTP/1.1 302 Found",
989 "HTTP/1.1 301 Moved Permanently",
990 "HTTP/1.1 301 Moved Permanently",
991 };
992
993 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
994 forgot_to_update_kStatusLines);
995
996 for (int i = 0; i < kNumUnreadBodies; ++i)
997 EXPECT_EQ(kStatusLines[i], response_lines[i]);
998
999 TestCompletionCallback callback;
1000 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1001 int rv = trans->Start(&request, &callback, BoundNetLog());
1002 EXPECT_EQ(ERR_IO_PENDING, rv);
1003 rv = callback.WaitForResult();
1004 EXPECT_EQ(OK, rv);
1005 const HttpResponseInfo* response = trans->GetResponseInfo();
1006 ASSERT_TRUE(response != NULL);
1007 ASSERT_TRUE(response->headers != NULL);
1008 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1009 std::string response_data;
1010 rv = ReadTransaction(trans.get(), &response_data);
1011 EXPECT_EQ(OK, rv);
1012 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131013}
1014
[email protected]038e9a32008-10-08 22:40:161015// Test the request-challenge-retry sequence for basic auth.
1016// (basic auth is the easiest to mock, because it has no randomness).
1017TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:591018 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401019 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431020 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161021
[email protected]1c773ea12009-04-28 19:58:421022 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161023 request.method = "GET";
1024 request.url = GURL("http://www.google.com/");
1025 request.load_flags = 0;
1026
[email protected]f9ee6b52008-11-08 06:46:231027 MockWrite data_writes1[] = {
1028 MockWrite("GET / HTTP/1.1\r\n"
1029 "Host: www.google.com\r\n"
1030 "Connection: keep-alive\r\n\r\n"),
1031 };
1032
[email protected]038e9a32008-10-08 22:40:161033 MockRead data_reads1[] = {
1034 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1035 // Give a couple authenticate options (only the middle one is actually
1036 // supported).
[email protected]22927ad2009-09-21 19:56:191037 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161038 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1039 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1041 // Large content-length -- won't matter, as connection will be reset.
1042 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421043 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161044 };
1045
1046 // After calling trans->RestartWithAuth(), this is the request we should
1047 // be issuing -- the final header line contains the credentials.
1048 MockWrite data_writes2[] = {
1049 MockWrite("GET / HTTP/1.1\r\n"
1050 "Host: www.google.com\r\n"
1051 "Connection: keep-alive\r\n"
1052 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1053 };
1054
1055 // Lastly, the server responds with the actual content.
1056 MockRead data_reads2[] = {
1057 MockRead("HTTP/1.0 200 OK\r\n"),
1058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1059 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421060 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161061 };
1062
[email protected]31a2bfe2010-02-09 08:03:391063 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1064 data_writes1, arraysize(data_writes1));
1065 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1066 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591067 session_deps.socket_factory.AddSocketDataProvider(&data1);
1068 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161069
1070 TestCompletionCallback callback1;
1071
[email protected]5a1d7ca2010-04-28 20:12:271072 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421073 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161074
1075 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421076 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161077
[email protected]1c773ea12009-04-28 19:58:421078 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161079 EXPECT_FALSE(response == NULL);
1080
1081 // The password prompt info should have been set in response->auth_challenge.
1082 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1083
[email protected]71e4573a2009-05-21 22:03:001084 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161085 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1086 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1087
1088 TestCompletionCallback callback2;
1089
[email protected]13c8a092010-07-29 06:15:441090 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421091 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161092
1093 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421094 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161095
1096 response = trans->GetResponseInfo();
1097 EXPECT_FALSE(response == NULL);
1098 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1099 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161100}
1101
[email protected]861fcd52009-08-26 02:33:461102TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1103 SessionDependencies session_deps;
1104 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431105 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461106
1107 HttpRequestInfo request;
1108 request.method = "GET";
1109 request.url = GURL("http://www.google.com/");
1110 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1111
1112 MockWrite data_writes[] = {
1113 MockWrite("GET / HTTP/1.1\r\n"
1114 "Host: www.google.com\r\n"
1115 "Connection: keep-alive\r\n\r\n"),
1116 };
1117
1118 MockRead data_reads[] = {
1119 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1120 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1121 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1122 // Large content-length -- won't matter, as connection will be reset.
1123 MockRead("Content-Length: 10000\r\n\r\n"),
1124 MockRead(false, ERR_FAILED),
1125 };
1126
[email protected]31a2bfe2010-02-09 08:03:391127 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1128 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591129 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461130 TestCompletionCallback callback;
1131
[email protected]5a1d7ca2010-04-28 20:12:271132 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461133 EXPECT_EQ(ERR_IO_PENDING, rv);
1134
1135 rv = callback.WaitForResult();
1136 EXPECT_EQ(0, rv);
1137
1138 const HttpResponseInfo* response = trans->GetResponseInfo();
1139 ASSERT_FALSE(response == NULL);
1140 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1141}
1142
[email protected]2d2697f92009-02-18 21:00:321143// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1144// connection.
1145TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591146 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501147 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321148
[email protected]1c773ea12009-04-28 19:58:421149 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321150 request.method = "GET";
1151 request.url = GURL("http://www.google.com/");
1152 request.load_flags = 0;
1153
1154 MockWrite data_writes1[] = {
1155 MockWrite("GET / HTTP/1.1\r\n"
1156 "Host: www.google.com\r\n"
1157 "Connection: keep-alive\r\n\r\n"),
1158
1159 // After calling trans->RestartWithAuth(), this is the request we should
1160 // be issuing -- the final header line contains the credentials.
1161 MockWrite("GET / HTTP/1.1\r\n"
1162 "Host: www.google.com\r\n"
1163 "Connection: keep-alive\r\n"
1164 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1165 };
1166
1167 MockRead data_reads1[] = {
1168 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1169 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1171 MockRead("Content-Length: 14\r\n\r\n"),
1172 MockRead("Unauthorized\r\n"),
1173
1174 // Lastly, the server responds with the actual content.
1175 MockRead("HTTP/1.1 200 OK\r\n"),
1176 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501177 MockRead("Content-Length: 5\r\n\r\n"),
1178 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321179 };
1180
[email protected]31a2bfe2010-02-09 08:03:391181 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1182 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591183 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321184
1185 TestCompletionCallback callback1;
1186
[email protected]0b0bf032010-09-21 18:08:501187 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271188 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421189 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321190
1191 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421192 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321193
[email protected]1c773ea12009-04-28 19:58:421194 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321195 EXPECT_FALSE(response == NULL);
1196
1197 // The password prompt info should have been set in response->auth_challenge.
1198 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1199
[email protected]71e4573a2009-05-21 22:03:001200 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321201 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1202 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1203
1204 TestCompletionCallback callback2;
1205
[email protected]13c8a092010-07-29 06:15:441206 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421207 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321208
1209 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421210 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321211
1212 response = trans->GetResponseInfo();
1213 EXPECT_FALSE(response == NULL);
1214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501215 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321216}
1217
1218// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1219// connection and with no response body to drain.
1220TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591221 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321223
[email protected]1c773ea12009-04-28 19:58:421224 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321225 request.method = "GET";
1226 request.url = GURL("http://www.google.com/");
1227 request.load_flags = 0;
1228
1229 MockWrite data_writes1[] = {
1230 MockWrite("GET / HTTP/1.1\r\n"
1231 "Host: www.google.com\r\n"
1232 "Connection: keep-alive\r\n\r\n"),
1233
1234 // After calling trans->RestartWithAuth(), this is the request we should
1235 // be issuing -- the final header line contains the credentials.
1236 MockWrite("GET / HTTP/1.1\r\n"
1237 "Host: www.google.com\r\n"
1238 "Connection: keep-alive\r\n"
1239 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1240 };
1241
[email protected]2d2697f92009-02-18 21:00:321242 MockRead data_reads1[] = {
1243 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1244 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311245 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321246
1247 // Lastly, the server responds with the actual content.
1248 MockRead("HTTP/1.1 200 OK\r\n"),
1249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501250 MockRead("Content-Length: 5\r\n\r\n"),
1251 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321252 };
1253
[email protected]31a2bfe2010-02-09 08:03:391254 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1255 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591256 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321257
1258 TestCompletionCallback callback1;
1259
[email protected]0b0bf032010-09-21 18:08:501260 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271261 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421262 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321263
1264 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421265 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321266
[email protected]1c773ea12009-04-28 19:58:421267 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321268 EXPECT_FALSE(response == NULL);
1269
1270 // The password prompt info should have been set in response->auth_challenge.
1271 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1272
[email protected]71e4573a2009-05-21 22:03:001273 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321274 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1275 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1276
1277 TestCompletionCallback callback2;
1278
[email protected]13c8a092010-07-29 06:15:441279 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421280 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321281
1282 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421283 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321284
1285 response = trans->GetResponseInfo();
1286 EXPECT_FALSE(response == NULL);
1287 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501288 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321289}
1290
1291// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1292// connection and with a large response body to drain.
1293TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591294 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501295 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321296
[email protected]1c773ea12009-04-28 19:58:421297 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321298 request.method = "GET";
1299 request.url = GURL("http://www.google.com/");
1300 request.load_flags = 0;
1301
1302 MockWrite data_writes1[] = {
1303 MockWrite("GET / HTTP/1.1\r\n"
1304 "Host: www.google.com\r\n"
1305 "Connection: keep-alive\r\n\r\n"),
1306
1307 // After calling trans->RestartWithAuth(), this is the request we should
1308 // be issuing -- the final header line contains the credentials.
1309 MockWrite("GET / HTTP/1.1\r\n"
1310 "Host: www.google.com\r\n"
1311 "Connection: keep-alive\r\n"
1312 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1313 };
1314
1315 // Respond with 5 kb of response body.
1316 std::string large_body_string("Unauthorized");
1317 large_body_string.append(5 * 1024, ' ');
1318 large_body_string.append("\r\n");
1319
1320 MockRead data_reads1[] = {
1321 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1322 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1324 // 5134 = 12 + 5 * 1024 + 2
1325 MockRead("Content-Length: 5134\r\n\r\n"),
1326 MockRead(true, large_body_string.data(), large_body_string.size()),
1327
1328 // Lastly, the server responds with the actual content.
1329 MockRead("HTTP/1.1 200 OK\r\n"),
1330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501331 MockRead("Content-Length: 5\r\n\r\n"),
1332 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321333 };
1334
[email protected]31a2bfe2010-02-09 08:03:391335 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1336 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591337 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321338
1339 TestCompletionCallback callback1;
1340
[email protected]0b0bf032010-09-21 18:08:501341 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271342 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421343 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321344
1345 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421346 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321347
[email protected]1c773ea12009-04-28 19:58:421348 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321349 EXPECT_FALSE(response == NULL);
1350
1351 // The password prompt info should have been set in response->auth_challenge.
1352 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1353
[email protected]71e4573a2009-05-21 22:03:001354 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321355 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1356 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1357
1358 TestCompletionCallback callback2;
1359
[email protected]13c8a092010-07-29 06:15:441360 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421361 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321362
1363 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421364 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321365
1366 response = trans->GetResponseInfo();
1367 EXPECT_FALSE(response == NULL);
1368 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501369 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321370}
1371
1372// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311373// connection, but the server gets impatient and closes the connection.
1374TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1375 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501376 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311377
1378 HttpRequestInfo request;
1379 request.method = "GET";
1380 request.url = GURL("http://www.google.com/");
1381 request.load_flags = 0;
1382
1383 MockWrite data_writes1[] = {
1384 MockWrite("GET / HTTP/1.1\r\n"
1385 "Host: www.google.com\r\n"
1386 "Connection: keep-alive\r\n\r\n"),
1387 // This simulates the seemingly successful write to a closed connection
1388 // if the bug is not fixed.
1389 MockWrite("GET / HTTP/1.1\r\n"
1390 "Host: www.google.com\r\n"
1391 "Connection: keep-alive\r\n"
1392 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1393 };
1394
1395 MockRead data_reads1[] = {
1396 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1397 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1399 MockRead("Content-Length: 14\r\n\r\n"),
1400 // Tell MockTCPClientSocket to simulate the server closing the connection.
1401 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1402 MockRead("Unauthorized\r\n"),
1403 MockRead(false, OK), // The server closes the connection.
1404 };
1405
1406 // After calling trans->RestartWithAuth(), this is the request we should
1407 // be issuing -- the final header line contains the credentials.
1408 MockWrite data_writes2[] = {
1409 MockWrite("GET / HTTP/1.1\r\n"
1410 "Host: www.google.com\r\n"
1411 "Connection: keep-alive\r\n"
1412 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1413 };
1414
1415 // Lastly, the server responds with the actual content.
1416 MockRead data_reads2[] = {
1417 MockRead("HTTP/1.1 200 OK\r\n"),
1418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501419 MockRead("Content-Length: 5\r\n\r\n"),
1420 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311421 };
1422
[email protected]31a2bfe2010-02-09 08:03:391423 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1424 data_writes1, arraysize(data_writes1));
1425 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1426 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311427 session_deps.socket_factory.AddSocketDataProvider(&data1);
1428 session_deps.socket_factory.AddSocketDataProvider(&data2);
1429
1430 TestCompletionCallback callback1;
1431
[email protected]0b0bf032010-09-21 18:08:501432 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271433 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311434 EXPECT_EQ(ERR_IO_PENDING, rv);
1435
1436 rv = callback1.WaitForResult();
1437 EXPECT_EQ(OK, rv);
1438
1439 const HttpResponseInfo* response = trans->GetResponseInfo();
1440 EXPECT_FALSE(response == NULL);
1441
1442 // The password prompt info should have been set in response->auth_challenge.
1443 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1444
1445 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1446 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1447 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1448
1449 TestCompletionCallback callback2;
1450
[email protected]13c8a092010-07-29 06:15:441451 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311452 EXPECT_EQ(ERR_IO_PENDING, rv);
1453
1454 rv = callback2.WaitForResult();
1455 EXPECT_EQ(OK, rv);
1456
1457 response = trans->GetResponseInfo();
1458 ASSERT_FALSE(response == NULL);
1459 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501460 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311461}
1462
[email protected]394816e92010-08-03 07:38:591463// Test the request-challenge-retry sequence for basic auth, over a connection
1464// that requires a restart when setting up an SSL tunnel.
1465TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1466 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001467 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]394816e92010-08-03 07:38:591468 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1469 session_deps.net_log = log.bound().net_log();
1470 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1471
[email protected]394816e92010-08-03 07:38:591472 HttpRequestInfo request;
1473 request.method = "GET";
1474 request.url = GURL("https://www.google.com/");
1475 // when the no authentication data flag is set.
1476 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1477
1478 // Since we have proxy, should try to establish tunnel.
1479 MockWrite data_writes1[] = {
1480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1481 "Host: www.google.com\r\n"
1482 "Proxy-Connection: keep-alive\r\n\r\n"),
1483
1484 // After calling trans->RestartWithAuth(), this is the request we should
1485 // be issuing -- the final header line contains the credentials.
1486 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1487 "Host: www.google.com\r\n"
1488 "Proxy-Connection: keep-alive\r\n"
1489 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1490
1491 MockWrite("GET / HTTP/1.1\r\n"
1492 "Host: www.google.com\r\n"
1493 "Connection: keep-alive\r\n\r\n"),
1494 };
1495
1496 // The proxy responds to the connect with a 407, using a persistent
1497 // connection.
1498 MockRead data_reads1[] = {
1499 // No credentials.
1500 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1501 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1502 MockRead("Proxy-Connection: close\r\n\r\n"),
1503
1504 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1505
1506 MockRead("HTTP/1.1 200 OK\r\n"),
1507 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501508 MockRead("Content-Length: 5\r\n\r\n"),
1509 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591510 };
1511
1512 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1513 data_writes1, arraysize(data_writes1));
1514 session_deps.socket_factory.AddSocketDataProvider(&data1);
1515 SSLSocketDataProvider ssl(true, OK);
1516 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1517
1518 TestCompletionCallback callback1;
1519
[email protected]0b0bf032010-09-21 18:08:501520 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1521
[email protected]394816e92010-08-03 07:38:591522 int rv = trans->Start(&request, &callback1, log.bound());
1523 EXPECT_EQ(ERR_IO_PENDING, rv);
1524
1525 rv = callback1.WaitForResult();
1526 EXPECT_EQ(OK, rv);
1527 size_t pos = ExpectLogContainsSomewhere(
1528 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1529 NetLog::PHASE_NONE);
1530 ExpectLogContainsSomewhere(
1531 log.entries(), pos,
1532 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1533 NetLog::PHASE_NONE);
1534
1535 const HttpResponseInfo* response = trans->GetResponseInfo();
1536 ASSERT_FALSE(response == NULL);
1537
1538 EXPECT_EQ(407, response->headers->response_code());
1539 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1540
1541 // The password prompt info should have been set in response->auth_challenge.
1542 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1543
1544 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1545 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1546 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1547
1548 TestCompletionCallback callback2;
1549
1550 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1551 EXPECT_EQ(ERR_IO_PENDING, rv);
1552
1553 rv = callback2.WaitForResult();
1554 EXPECT_EQ(OK, rv);
1555
1556 response = trans->GetResponseInfo();
1557 ASSERT_FALSE(response == NULL);
1558
1559 EXPECT_TRUE(response->headers->IsKeepAlive());
1560 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501561 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591562 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1563
1564 // The password prompt info should not be set.
1565 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501566
1567 trans.reset();
1568 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591569}
1570
[email protected]11203f012009-11-12 23:02:311571// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321572// proxy connection, when setting up an SSL tunnel.
1573TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1574 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001575 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541576 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1577 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591578 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321579
[email protected]5695b8c2009-09-30 21:36:431580 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321581
[email protected]1c773ea12009-04-28 19:58:421582 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321583 request.method = "GET";
1584 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461585 // Ensure that proxy authentication is attempted even
1586 // when the no authentication data flag is set.
1587 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321588
1589 // Since we have proxy, should try to establish tunnel.
1590 MockWrite data_writes1[] = {
1591 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451592 "Host: www.google.com\r\n"
1593 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321594
1595 // After calling trans->RestartWithAuth(), this is the request we should
1596 // be issuing -- the final header line contains the credentials.
1597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1598 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451599 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321600 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1601 };
1602
1603 // The proxy responds to the connect with a 407, using a persistent
1604 // connection.
1605 MockRead data_reads1[] = {
1606 // No credentials.
1607 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1608 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1609 MockRead("Content-Length: 10\r\n\r\n"),
1610 MockRead("0123456789"),
1611
1612 // Wrong credentials (wrong password).
1613 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1614 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1615 MockRead("Content-Length: 10\r\n\r\n"),
1616 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421617 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321618 };
1619
[email protected]31a2bfe2010-02-09 08:03:391620 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1621 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591622 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321623
1624 TestCompletionCallback callback1;
1625
[email protected]dbb83db2010-05-11 18:13:391626 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421627 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321628
1629 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421630 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391631 size_t pos = ExpectLogContainsSomewhere(
1632 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1633 NetLog::PHASE_NONE);
1634 ExpectLogContainsSomewhere(
1635 log.entries(), pos,
1636 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1637 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321638
[email protected]1c773ea12009-04-28 19:58:421639 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321640 EXPECT_FALSE(response == NULL);
1641
1642 EXPECT_TRUE(response->headers->IsKeepAlive());
1643 EXPECT_EQ(407, response->headers->response_code());
1644 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421645 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321646
1647 // The password prompt info should have been set in response->auth_challenge.
1648 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1649
[email protected]71e4573a2009-05-21 22:03:001650 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321651 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1652 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1653
1654 TestCompletionCallback callback2;
1655
1656 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441657 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321659
1660 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421661 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321662
1663 response = trans->GetResponseInfo();
1664 EXPECT_FALSE(response == NULL);
1665
1666 EXPECT_TRUE(response->headers->IsKeepAlive());
1667 EXPECT_EQ(407, response->headers->response_code());
1668 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421669 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321670
1671 // The password prompt info should have been set in response->auth_challenge.
1672 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1673
[email protected]71e4573a2009-05-21 22:03:001674 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321675 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1676 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131677
[email protected]e60e47a2010-07-14 03:37:181678 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1679 // out of scope.
1680 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321681}
1682
[email protected]a8e9b162009-03-12 00:06:441683// Test that we don't read the response body when we fail to establish a tunnel,
1684// even if the user cancels the proxy's auth attempt.
1685TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1686 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001687 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441688
[email protected]e44de5d2009-06-05 20:12:451689 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441690
[email protected]5695b8c2009-09-30 21:36:431691 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441692
[email protected]1c773ea12009-04-28 19:58:421693 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441694 request.method = "GET";
1695 request.url = GURL("https://www.google.com/");
1696 request.load_flags = 0;
1697
1698 // Since we have proxy, should try to establish tunnel.
1699 MockWrite data_writes[] = {
1700 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451701 "Host: www.google.com\r\n"
1702 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441703 };
1704
1705 // The proxy responds to the connect with a 407.
1706 MockRead data_reads[] = {
1707 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1708 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1709 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421710 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441711 };
1712
[email protected]31a2bfe2010-02-09 08:03:391713 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1714 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591715 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441716
1717 TestCompletionCallback callback;
1718
[email protected]5a1d7ca2010-04-28 20:12:271719 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421720 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441721
1722 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421723 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441724
[email protected]1c773ea12009-04-28 19:58:421725 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441726 EXPECT_FALSE(response == NULL);
1727
1728 EXPECT_TRUE(response->headers->IsKeepAlive());
1729 EXPECT_EQ(407, response->headers->response_code());
1730 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421731 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441732
1733 std::string response_data;
1734 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421735 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181736
1737 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1738 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441739}
1740
[email protected]8fdbcd22010-05-05 02:54:521741// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1742// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1743TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1744 // We are using a DIRECT connection (i.e. no proxy) for this session.
1745 SessionDependencies session_deps;
1746 scoped_ptr<HttpTransaction> trans(
1747 new HttpNetworkTransaction(CreateSession(&session_deps)));
1748
1749 HttpRequestInfo request;
1750 request.method = "GET";
1751 request.url = GURL("http://www.google.com/");
1752 request.load_flags = 0;
1753
1754 MockWrite data_writes1[] = {
1755 MockWrite("GET / HTTP/1.1\r\n"
1756 "Host: www.google.com\r\n"
1757 "Connection: keep-alive\r\n\r\n"),
1758 };
1759
1760 MockRead data_reads1[] = {
1761 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1762 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1763 // Large content-length -- won't matter, as connection will be reset.
1764 MockRead("Content-Length: 10000\r\n\r\n"),
1765 MockRead(false, ERR_FAILED),
1766 };
1767
1768 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1769 data_writes1, arraysize(data_writes1));
1770 session_deps.socket_factory.AddSocketDataProvider(&data1);
1771
1772 TestCompletionCallback callback;
1773
1774 int rv = trans->Start(&request, &callback, BoundNetLog());
1775 EXPECT_EQ(ERR_IO_PENDING, rv);
1776
1777 rv = callback.WaitForResult();
1778 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1779}
1780
[email protected]7a67a8152010-11-05 18:31:101781// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1782// through a non-authenticating proxy. The request should fail with
1783// ERR_UNEXPECTED_PROXY_AUTH.
1784// Note that it is impossible to detect if an HTTP server returns a 407 through
1785// a non-authenticating proxy - there is nothing to indicate whether the
1786// response came from the proxy or the server, so it is treated as if the proxy
1787// issued the challenge.
1788TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
1789 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1790 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1791 session_deps.net_log = log.bound().net_log();
1792 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1793
1794 HttpRequestInfo request;
1795 request.method = "GET";
1796 request.url = GURL("https://www.google.com/");
1797
1798 // Since we have proxy, should try to establish tunnel.
1799 MockWrite data_writes1[] = {
1800 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1801 "Host: www.google.com\r\n"
1802 "Proxy-Connection: keep-alive\r\n\r\n"),
1803
1804 MockWrite("GET / HTTP/1.1\r\n"
1805 "Host: www.google.com\r\n"
1806 "Connection: keep-alive\r\n\r\n"),
1807 };
1808
1809 MockRead data_reads1[] = {
1810 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1811
1812 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1813 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1814 MockRead("\r\n"),
1815 MockRead(false, OK),
1816 };
1817
1818 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1819 data_writes1, arraysize(data_writes1));
1820 session_deps.socket_factory.AddSocketDataProvider(&data1);
1821 SSLSocketDataProvider ssl(true, OK);
1822 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1823
1824 TestCompletionCallback callback1;
1825
1826 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1827
1828 int rv = trans->Start(&request, &callback1, log.bound());
1829 EXPECT_EQ(ERR_IO_PENDING, rv);
1830
1831 rv = callback1.WaitForResult();
1832 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1833 size_t pos = ExpectLogContainsSomewhere(
1834 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1835 NetLog::PHASE_NONE);
1836 ExpectLogContainsSomewhere(
1837 log.entries(), pos,
1838 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1839 NetLog::PHASE_NONE);
1840}
[email protected]2df19bb2010-08-25 20:13:461841
1842// Test a simple get through an HTTPS Proxy.
1843TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1844 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001845 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461846 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1847 session_deps.net_log = log.bound().net_log();
1848 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1849
[email protected]2df19bb2010-08-25 20:13:461850 HttpRequestInfo request;
1851 request.method = "GET";
1852 request.url = GURL("http://www.google.com/");
1853
1854 // Since we have proxy, should use full url
1855 MockWrite data_writes1[] = {
1856 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1857 "Host: www.google.com\r\n"
1858 "Proxy-Connection: keep-alive\r\n\r\n"),
1859 };
1860
1861 MockRead data_reads1[] = {
1862 MockRead("HTTP/1.1 200 OK\r\n"),
1863 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1864 MockRead("Content-Length: 100\r\n\r\n"),
1865 MockRead(false, OK),
1866 };
1867
1868 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1869 data_writes1, arraysize(data_writes1));
1870 session_deps.socket_factory.AddSocketDataProvider(&data1);
1871 SSLSocketDataProvider ssl(true, OK);
1872 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1873
1874 TestCompletionCallback callback1;
1875
[email protected]0b0bf032010-09-21 18:08:501876 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1877
[email protected]2df19bb2010-08-25 20:13:461878 int rv = trans->Start(&request, &callback1, log.bound());
1879 EXPECT_EQ(ERR_IO_PENDING, rv);
1880
1881 rv = callback1.WaitForResult();
1882 EXPECT_EQ(OK, rv);
1883
1884 const HttpResponseInfo* response = trans->GetResponseInfo();
1885 ASSERT_FALSE(response == NULL);
1886
1887 EXPECT_TRUE(response->headers->IsKeepAlive());
1888 EXPECT_EQ(200, response->headers->response_code());
1889 EXPECT_EQ(100, response->headers->GetContentLength());
1890 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1891
1892 // The password prompt info should not be set.
1893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1894}
1895
[email protected]7642b5ae2010-09-01 20:55:171896// Test a SPDY get through an HTTPS Proxy.
1897TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1898 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001899 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171900 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1901 session_deps.net_log = log.bound().net_log();
1902 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1903
[email protected]7642b5ae2010-09-01 20:55:171904 HttpRequestInfo request;
1905 request.method = "GET";
1906 request.url = GURL("http://www.google.com/");
1907 request.load_flags = 0;
1908
1909 // fetch http://www.google.com/ via SPDY
1910 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1911 false));
1912 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1913
1914 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1915 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1916 MockRead spdy_reads[] = {
1917 CreateMockRead(*resp),
1918 CreateMockRead(*data),
1919 MockRead(true, 0, 0),
1920 };
1921
1922 scoped_refptr<DelayedSocketData> spdy_data(
1923 new DelayedSocketData(
1924 1, // wait for one write to finish before reading.
1925 spdy_reads, arraysize(spdy_reads),
1926 spdy_writes, arraysize(spdy_writes)));
1927 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1928
1929 SSLSocketDataProvider ssl(true, OK);
1930 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1931 ssl.next_proto = "spdy/2";
1932 ssl.was_npn_negotiated = true;
1933 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1934
1935 TestCompletionCallback callback1;
1936
[email protected]0b0bf032010-09-21 18:08:501937 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1938
[email protected]7642b5ae2010-09-01 20:55:171939 int rv = trans->Start(&request, &callback1, log.bound());
1940 EXPECT_EQ(ERR_IO_PENDING, rv);
1941
1942 rv = callback1.WaitForResult();
1943 EXPECT_EQ(OK, rv);
1944
1945 const HttpResponseInfo* response = trans->GetResponseInfo();
1946 ASSERT_TRUE(response != NULL);
1947 ASSERT_TRUE(response->headers != NULL);
1948 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1949
1950 std::string response_data;
1951 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1952 EXPECT_EQ(net::kUploadData, response_data);
1953}
1954
[email protected]d9da5fe2010-10-13 22:37:161955// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
1956TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
1957 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001958 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:161959 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1960 session_deps.net_log = log.bound().net_log();
1961 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1962
1963 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1964
1965 HttpRequestInfo request;
1966 request.method = "GET";
1967 request.url = GURL("https://www.google.com/");
1968 request.load_flags = 0;
1969
1970 // CONNECT to www.google.com:443 via SPDY
1971 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
1972 // fetch https://www.google.com/ via HTTP
1973
1974 const char get[] = "GET / HTTP/1.1\r\n"
1975 "Host: www.google.com\r\n"
1976 "Connection: keep-alive\r\n\r\n";
1977 scoped_ptr<spdy::SpdyFrame> wrapped_get(
1978 ConstructSpdyBodyFrame(1, get, strlen(get), false));
1979 MockWrite spdy_writes[] = {
1980 CreateMockWrite(*connect, 1),
1981 CreateMockWrite(*wrapped_get, 3)
1982 };
1983
1984 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1985 const char resp[] = "HTTP/1.1 200 OK\r\n"
1986 "Content-Length: 10\r\n\r\n";
1987
1988 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
1989 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
1990 scoped_ptr<spdy::SpdyFrame> wrapped_body(
1991 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
1992 MockRead spdy_reads[] = {
1993 CreateMockRead(*conn_resp, 2, true),
1994 CreateMockRead(*wrapped_get_resp, 4, true),
1995 CreateMockRead(*wrapped_body, 5, true),
1996 CreateMockRead(*wrapped_body, 6, true),
1997 MockRead(true, 0, 7),
1998 };
1999
2000 scoped_refptr<OrderedSocketData> spdy_data(
2001 new OrderedSocketData(
2002 spdy_reads, arraysize(spdy_reads),
2003 spdy_writes, arraysize(spdy_writes)));
2004 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2005
2006 SSLSocketDataProvider ssl(true, OK);
2007 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2008 ssl.next_proto = "spdy/2";
2009 ssl.was_npn_negotiated = true;
2010 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2011 SSLSocketDataProvider ssl2(true, OK);
2012 ssl2.was_npn_negotiated = false;
2013 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2014
2015 TestCompletionCallback callback1;
2016
2017 int rv = trans->Start(&request, &callback1, log.bound());
2018 EXPECT_EQ(ERR_IO_PENDING, rv);
2019
2020 rv = callback1.WaitForResult();
2021 EXPECT_EQ(OK, rv);
2022
2023 const HttpResponseInfo* response = trans->GetResponseInfo();
2024 ASSERT_TRUE(response != NULL);
2025 ASSERT_TRUE(response->headers != NULL);
2026 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2027
2028 std::string response_data;
2029 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2030 EXPECT_EQ("1234567890", response_data);
2031}
2032
2033// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2034TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2035 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002036 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162037 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2038 session_deps.net_log = log.bound().net_log();
2039 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2040
2041 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2042
2043 HttpRequestInfo request;
2044 request.method = "GET";
2045 request.url = GURL("https://www.google.com/");
2046 request.load_flags = 0;
2047
2048 // CONNECT to www.google.com:443 via SPDY
2049 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2050 // fetch https://www.google.com/ via SPDY
2051 const char* const kMyUrl = "https://www.google.com/";
2052 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2053 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2054 MockWrite spdy_writes[] = {
2055 CreateMockWrite(*connect, 1),
2056 CreateMockWrite(*wrapped_get, 3)
2057 };
2058
2059 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2060 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2061 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2062 ConstructWrappedSpdyFrame(get_resp, 1));
2063 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2064 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2065 MockRead spdy_reads[] = {
2066 CreateMockRead(*conn_resp, 2, true),
2067 CreateMockRead(*wrapped_get_resp, 4, true),
2068 CreateMockRead(*wrapped_body, 5, true),
2069 MockRead(true, 0, 1),
2070 };
2071
2072 scoped_refptr<OrderedSocketData> spdy_data(
2073 new OrderedSocketData(
2074 spdy_reads, arraysize(spdy_reads),
2075 spdy_writes, arraysize(spdy_writes)));
2076 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2077
2078 SSLSocketDataProvider ssl(true, OK);
2079 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2080 ssl.next_proto = "spdy/2";
2081 ssl.was_npn_negotiated = true;
2082 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2083 SSLSocketDataProvider ssl2(true, OK);
2084 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2085 ssl2.next_proto = "spdy/2";
2086 ssl2.was_npn_negotiated = true;
2087 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2088
2089 TestCompletionCallback callback1;
2090
2091 int rv = trans->Start(&request, &callback1, log.bound());
2092 EXPECT_EQ(ERR_IO_PENDING, rv);
2093
2094 rv = callback1.WaitForResult();
2095 EXPECT_EQ(OK, rv);
2096
2097 const HttpResponseInfo* response = trans->GetResponseInfo();
2098 ASSERT_TRUE(response != NULL);
2099 ASSERT_TRUE(response->headers != NULL);
2100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2101
2102 std::string response_data;
2103 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2104 EXPECT_EQ(net::kUploadData, response_data);
2105}
2106
2107// Test a SPDY CONNECT failure through an HTTPS Proxy.
2108TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2109 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002110 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162111 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2112 session_deps.net_log = log.bound().net_log();
2113 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2114
2115 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2116
2117 HttpRequestInfo request;
2118 request.method = "GET";
2119 request.url = GURL("https://www.google.com/");
2120 request.load_flags = 0;
2121
2122 // CONNECT to www.google.com:443 via SPDY
2123 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2124 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2125
2126 MockWrite spdy_writes[] = {
2127 CreateMockWrite(*connect, 1),
2128 CreateMockWrite(*get, 3),
2129 };
2130
2131 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2132 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2133 MockRead spdy_reads[] = {
2134 CreateMockRead(*resp, 2, true),
2135 MockRead(true, 0, 4),
2136 };
2137
2138 scoped_refptr<OrderedSocketData> spdy_data(
2139 new OrderedSocketData(
2140 spdy_reads, arraysize(spdy_reads),
2141 spdy_writes, arraysize(spdy_writes)));
2142 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2143
2144 SSLSocketDataProvider ssl(true, OK);
2145 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2146 ssl.next_proto = "spdy/2";
2147 ssl.was_npn_negotiated = true;
2148 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2149 SSLSocketDataProvider ssl2(true, OK);
2150 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2151 ssl2.next_proto = "spdy/2";
2152 ssl2.was_npn_negotiated = true;
2153 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2154
2155 TestCompletionCallback callback1;
2156
2157 int rv = trans->Start(&request, &callback1, log.bound());
2158 EXPECT_EQ(ERR_IO_PENDING, rv);
2159
2160 rv = callback1.WaitForResult();
2161 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2162
2163 const HttpResponseInfo* response = trans->GetResponseInfo();
2164 ASSERT_TRUE(response == NULL);
2165}
2166
[email protected]2df19bb2010-08-25 20:13:462167// Test the challenge-response-retry sequence through an HTTPS Proxy
2168TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
2169 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002170 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462171 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2172 session_deps.net_log = log.bound().net_log();
2173 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2174
[email protected]2df19bb2010-08-25 20:13:462175 HttpRequestInfo request;
2176 request.method = "GET";
2177 request.url = GURL("http://www.google.com/");
2178 // when the no authentication data flag is set.
2179 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2180
2181 // Since we have proxy, should use full url
2182 MockWrite data_writes1[] = {
2183 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2184 "Host: www.google.com\r\n"
2185 "Proxy-Connection: keep-alive\r\n\r\n"),
2186
2187 // After calling trans->RestartWithAuth(), this is the request we should
2188 // be issuing -- the final header line contains the credentials.
2189 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2190 "Host: www.google.com\r\n"
2191 "Proxy-Connection: keep-alive\r\n"
2192 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2193 };
2194
2195 // The proxy responds to the GET with a 407, using a persistent
2196 // connection.
2197 MockRead data_reads1[] = {
2198 // No credentials.
2199 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2200 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2201 MockRead("Proxy-Connection: keep-alive\r\n"),
2202 MockRead("Content-Length: 0\r\n\r\n"),
2203
2204 MockRead("HTTP/1.1 200 OK\r\n"),
2205 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2206 MockRead("Content-Length: 100\r\n\r\n"),
2207 MockRead(false, OK),
2208 };
2209
2210 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2211 data_writes1, arraysize(data_writes1));
2212 session_deps.socket_factory.AddSocketDataProvider(&data1);
2213 SSLSocketDataProvider ssl(true, OK);
2214 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2215
2216 TestCompletionCallback callback1;
2217
[email protected]0b0bf032010-09-21 18:08:502218 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2219
[email protected]2df19bb2010-08-25 20:13:462220 int rv = trans->Start(&request, &callback1, log.bound());
2221 EXPECT_EQ(ERR_IO_PENDING, rv);
2222
2223 rv = callback1.WaitForResult();
2224 EXPECT_EQ(OK, rv);
2225
2226 const HttpResponseInfo* response = trans->GetResponseInfo();
2227 ASSERT_FALSE(response == NULL);
2228
2229 EXPECT_EQ(407, response->headers->response_code());
2230 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2231
2232 // The password prompt info should have been set in response->auth_challenge.
2233 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2234
2235 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2236 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2237 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2238
2239 TestCompletionCallback callback2;
2240
2241 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2242 EXPECT_EQ(ERR_IO_PENDING, rv);
2243
2244 rv = callback2.WaitForResult();
2245 EXPECT_EQ(OK, rv);
2246
2247 response = trans->GetResponseInfo();
2248 ASSERT_FALSE(response == NULL);
2249
2250 EXPECT_TRUE(response->headers->IsKeepAlive());
2251 EXPECT_EQ(200, response->headers->response_code());
2252 EXPECT_EQ(100, response->headers->GetContentLength());
2253 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2254
2255 // The password prompt info should not be set.
2256 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2257}
2258
[email protected]ff007e162009-05-23 09:13:152259void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082260 const MockRead& status, int expected_status) {
2261 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002262 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:082263
[email protected]228ff742009-06-05 01:19:592264 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:082265
[email protected]1c773ea12009-04-28 19:58:422266 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082267 request.method = "GET";
2268 request.url = GURL("https://www.google.com/");
2269 request.load_flags = 0;
2270
2271 // Since we have proxy, should try to establish tunnel.
2272 MockWrite data_writes[] = {
2273 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452274 "Host: www.google.com\r\n"
2275 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082276 };
2277
2278 MockRead data_reads[] = {
2279 status,
2280 MockRead("Content-Length: 10\r\n\r\n"),
2281 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422282 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082283 };
2284
[email protected]31a2bfe2010-02-09 08:03:392285 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2286 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592287 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082288
2289 TestCompletionCallback callback;
2290
[email protected]0b0bf032010-09-21 18:08:502291 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2292
[email protected]5a1d7ca2010-04-28 20:12:272293 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422294 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082295
2296 rv = callback.WaitForResult();
2297 EXPECT_EQ(expected_status, rv);
2298}
2299
[email protected]ff007e162009-05-23 09:13:152300void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082301 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422302 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082303}
2304
2305TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2306 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2307}
2308
2309TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2310 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2311}
2312
2313TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2314 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2315}
2316
2317TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2318 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2319}
2320
2321TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2322 ConnectStatusHelper(
2323 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2324}
2325
2326TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2327 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2328}
2329
2330TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2331 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2332}
2333
2334TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2335 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2336}
2337
2338TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2339 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2340}
2341
2342TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2343 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2344}
2345
2346TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2347 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2348}
2349
2350TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2351 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2352}
2353
2354TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2355 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2356}
2357
2358TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2359 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2360}
2361
2362TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2363 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2364}
2365
2366TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2367 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2368}
2369
2370TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2371 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2372}
2373
2374TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2375 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2376}
2377
2378TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2379 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2380}
2381
2382TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2383 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2384}
2385
2386TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2387 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2388}
2389
2390TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2391 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2392}
2393
2394TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2395 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2396}
2397
2398TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2399 ConnectStatusHelperWithExpectedStatus(
2400 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542401 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082402}
2403
2404TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2405 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2406}
2407
2408TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2409 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2410}
2411
2412TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2413 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2414}
2415
2416TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2417 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2418}
2419
2420TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2421 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2422}
2423
2424TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2425 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2426}
2427
2428TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2429 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2430}
2431
2432TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2433 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2434}
2435
2436TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2437 ConnectStatusHelper(
2438 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2439}
2440
2441TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2442 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2443}
2444
2445TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2446 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2447}
2448
2449TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2450 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2451}
2452
2453TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2454 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2455}
2456
2457TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2458 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2459}
2460
2461TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2462 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2463}
2464
2465TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2466 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2467}
2468
[email protected]038e9a32008-10-08 22:40:162469// Test the flow when both the proxy server AND origin server require
2470// authentication. Again, this uses basic auth for both since that is
2471// the simplest to mock.
2472TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]81cdfcd2010-10-16 00:49:002473 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012474
[email protected]038e9a32008-10-08 22:40:162475 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422476 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432477 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162478
[email protected]1c773ea12009-04-28 19:58:422479 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162480 request.method = "GET";
2481 request.url = GURL("http://www.google.com/");
2482 request.load_flags = 0;
2483
[email protected]f9ee6b52008-11-08 06:46:232484 MockWrite data_writes1[] = {
2485 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2486 "Host: www.google.com\r\n"
2487 "Proxy-Connection: keep-alive\r\n\r\n"),
2488 };
2489
[email protected]038e9a32008-10-08 22:40:162490 MockRead data_reads1[] = {
2491 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2492 // Give a couple authenticate options (only the middle one is actually
2493 // supported).
[email protected]22927ad2009-09-21 19:56:192494 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162495 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2496 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2497 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2498 // Large content-length -- won't matter, as connection will be reset.
2499 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422500 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162501 };
2502
2503 // After calling trans->RestartWithAuth() the first time, this is the
2504 // request we should be issuing -- the final header line contains the
2505 // proxy's credentials.
2506 MockWrite data_writes2[] = {
2507 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2508 "Host: www.google.com\r\n"
2509 "Proxy-Connection: keep-alive\r\n"
2510 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2511 };
2512
2513 // Now the proxy server lets the request pass through to origin server.
2514 // The origin server responds with a 401.
2515 MockRead data_reads2[] = {
2516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2517 // Note: We are using the same realm-name as the proxy server. This is
2518 // completely valid, as realms are unique across hosts.
2519 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2520 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2521 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422522 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162523 };
2524
2525 // After calling trans->RestartWithAuth() the second time, we should send
2526 // the credentials for both the proxy and origin server.
2527 MockWrite data_writes3[] = {
2528 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2529 "Host: www.google.com\r\n"
2530 "Proxy-Connection: keep-alive\r\n"
2531 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2532 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2533 };
2534
2535 // Lastly we get the desired content.
2536 MockRead data_reads3[] = {
2537 MockRead("HTTP/1.0 200 OK\r\n"),
2538 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2539 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422540 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162541 };
2542
[email protected]31a2bfe2010-02-09 08:03:392543 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2544 data_writes1, arraysize(data_writes1));
2545 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2546 data_writes2, arraysize(data_writes2));
2547 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2548 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592549 session_deps.socket_factory.AddSocketDataProvider(&data1);
2550 session_deps.socket_factory.AddSocketDataProvider(&data2);
2551 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162552
2553 TestCompletionCallback callback1;
2554
[email protected]5a1d7ca2010-04-28 20:12:272555 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422556 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162557
2558 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422559 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162560
[email protected]1c773ea12009-04-28 19:58:422561 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162562 EXPECT_FALSE(response == NULL);
2563
2564 // The password prompt info should have been set in response->auth_challenge.
2565 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2566
[email protected]71e4573a2009-05-21 22:03:002567 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162568 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2569 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2570
2571 TestCompletionCallback callback2;
2572
[email protected]13c8a092010-07-29 06:15:442573 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422574 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162575
2576 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422577 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162578
2579 response = trans->GetResponseInfo();
2580 EXPECT_FALSE(response == NULL);
2581 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2582
[email protected]71e4573a2009-05-21 22:03:002583 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162584 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2585 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2586
2587 TestCompletionCallback callback3;
2588
[email protected]13c8a092010-07-29 06:15:442589 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422590 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162591
2592 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422593 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162594
2595 response = trans->GetResponseInfo();
2596 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2597 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162598}
[email protected]4ddaf2502008-10-23 18:26:192599
[email protected]ea9dc9a2009-09-05 00:43:322600// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2601// can't hook into its internals to cause it to generate predictable NTLM
2602// authorization headers.
2603#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292604// The NTLM authentication unit tests were generated by capturing the HTTP
2605// requests and responses using Fiddler 2 and inspecting the generated random
2606// bytes in the debugger.
2607
2608// Enter the correct password and authenticate successfully.
2609TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422610 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112611 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592612 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502613 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242614
[email protected]1c773ea12009-04-28 19:58:422615 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242616 request.method = "GET";
2617 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2618 request.load_flags = 0;
2619
2620 MockWrite data_writes1[] = {
2621 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2622 "Host: 172.22.68.17\r\n"
2623 "Connection: keep-alive\r\n\r\n"),
2624 };
2625
2626 MockRead data_reads1[] = {
2627 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042628 // Negotiate and NTLM are often requested together. However, we only want
2629 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2630 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242631 MockRead("WWW-Authenticate: NTLM\r\n"),
2632 MockRead("Connection: close\r\n"),
2633 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362634 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242635 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422636 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242637 };
2638
2639 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222640 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242641 // request we should be issuing -- the final header line contains a Type
2642 // 1 message.
2643 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2644 "Host: 172.22.68.17\r\n"
2645 "Connection: keep-alive\r\n"
2646 "Authorization: NTLM "
2647 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2648
2649 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2650 // (the credentials for the origin server). The second request continues
2651 // on the same connection.
2652 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2653 "Host: 172.22.68.17\r\n"
2654 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292655 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2656 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2657 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2658 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2659 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242660 };
2661
2662 MockRead data_reads2[] = {
2663 // The origin server responds with a Type 2 message.
2664 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2665 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292666 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242667 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2668 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2669 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2670 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2671 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2672 "BtAAAAAAA=\r\n"),
2673 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362674 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242675 MockRead("You are not authorized to view this page\r\n"),
2676
2677 // Lastly we get the desired content.
2678 MockRead("HTTP/1.1 200 OK\r\n"),
2679 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2680 MockRead("Content-Length: 13\r\n\r\n"),
2681 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422682 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242683 };
2684
[email protected]31a2bfe2010-02-09 08:03:392685 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2686 data_writes1, arraysize(data_writes1));
2687 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2688 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592689 session_deps.socket_factory.AddSocketDataProvider(&data1);
2690 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242691
2692 TestCompletionCallback callback1;
2693
[email protected]0b0bf032010-09-21 18:08:502694 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2695
[email protected]5a1d7ca2010-04-28 20:12:272696 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242698
2699 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422700 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242701
[email protected]0757e7702009-03-27 04:00:222702 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2703 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442704 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422705 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222706 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422707 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222708 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2709
[email protected]1c773ea12009-04-28 19:58:422710 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042711 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242712
[email protected]aef04272010-06-28 18:03:042713 // The password prompt info should have been set in
2714 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242715 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2716
[email protected]71e4573a2009-05-21 22:03:002717 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242718 EXPECT_EQ(L"", response->auth_challenge->realm);
2719 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2720
[email protected]0757e7702009-03-27 04:00:222721 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242722
[email protected]13c8a092010-07-29 06:15:442723 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422724 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242725
[email protected]0757e7702009-03-27 04:00:222726 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422727 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242728
2729 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042730 ASSERT_FALSE(response == NULL);
2731
[email protected]3f918782009-02-28 01:29:242732 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2733 EXPECT_EQ(13, response->headers->GetContentLength());
2734}
2735
[email protected]385a4672009-03-11 22:21:292736// Enter a wrong password, and then the correct one.
2737TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422738 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112739 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592740 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292742
[email protected]1c773ea12009-04-28 19:58:422743 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292744 request.method = "GET";
2745 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2746 request.load_flags = 0;
2747
2748 MockWrite data_writes1[] = {
2749 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2750 "Host: 172.22.68.17\r\n"
2751 "Connection: keep-alive\r\n\r\n"),
2752 };
2753
2754 MockRead data_reads1[] = {
2755 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042756 // Negotiate and NTLM are often requested together. However, we only want
2757 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2758 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292759 MockRead("WWW-Authenticate: NTLM\r\n"),
2760 MockRead("Connection: close\r\n"),
2761 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362762 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292763 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422764 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292765 };
2766
2767 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222768 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292769 // request we should be issuing -- the final header line contains a Type
2770 // 1 message.
2771 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2772 "Host: 172.22.68.17\r\n"
2773 "Connection: keep-alive\r\n"
2774 "Authorization: NTLM "
2775 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2776
2777 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2778 // (the credentials for the origin server). The second request continues
2779 // on the same connection.
2780 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2781 "Host: 172.22.68.17\r\n"
2782 "Connection: keep-alive\r\n"
2783 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2784 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2785 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2786 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2787 "4Ww7b7E=\r\n\r\n"),
2788 };
2789
2790 MockRead data_reads2[] = {
2791 // The origin server responds with a Type 2 message.
2792 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2793 MockRead("WWW-Authenticate: NTLM "
2794 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2795 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2796 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2797 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2798 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2799 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2800 "BtAAAAAAA=\r\n"),
2801 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362802 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292803 MockRead("You are not authorized to view this page\r\n"),
2804
2805 // Wrong password.
2806 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292807 MockRead("WWW-Authenticate: NTLM\r\n"),
2808 MockRead("Connection: close\r\n"),
2809 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362810 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292811 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422812 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292813 };
2814
2815 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222816 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292817 // request we should be issuing -- the final header line contains a Type
2818 // 1 message.
2819 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2820 "Host: 172.22.68.17\r\n"
2821 "Connection: keep-alive\r\n"
2822 "Authorization: NTLM "
2823 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2824
2825 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2826 // (the credentials for the origin server). The second request continues
2827 // on the same connection.
2828 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2829 "Host: 172.22.68.17\r\n"
2830 "Connection: keep-alive\r\n"
2831 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2832 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2833 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2834 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2835 "+4MUm7c=\r\n\r\n"),
2836 };
2837
2838 MockRead data_reads3[] = {
2839 // The origin server responds with a Type 2 message.
2840 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2841 MockRead("WWW-Authenticate: NTLM "
2842 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2843 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2844 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2845 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2846 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2847 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2848 "BtAAAAAAA=\r\n"),
2849 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362850 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292851 MockRead("You are not authorized to view this page\r\n"),
2852
2853 // Lastly we get the desired content.
2854 MockRead("HTTP/1.1 200 OK\r\n"),
2855 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2856 MockRead("Content-Length: 13\r\n\r\n"),
2857 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422858 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292859 };
2860
[email protected]31a2bfe2010-02-09 08:03:392861 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2862 data_writes1, arraysize(data_writes1));
2863 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2864 data_writes2, arraysize(data_writes2));
2865 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2866 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592867 session_deps.socket_factory.AddSocketDataProvider(&data1);
2868 session_deps.socket_factory.AddSocketDataProvider(&data2);
2869 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292870
2871 TestCompletionCallback callback1;
2872
[email protected]0b0bf032010-09-21 18:08:502873 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2874
[email protected]5a1d7ca2010-04-28 20:12:272875 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422876 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292877
2878 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422879 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292880
[email protected]0757e7702009-03-27 04:00:222881 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292882 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442883 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422884 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292885 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422886 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222887 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292888
[email protected]1c773ea12009-04-28 19:58:422889 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292890 EXPECT_FALSE(response == NULL);
2891
2892 // The password prompt info should have been set in response->auth_challenge.
2893 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2894
[email protected]71e4573a2009-05-21 22:03:002895 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292896 EXPECT_EQ(L"", response->auth_challenge->realm);
2897 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2898
2899 TestCompletionCallback callback3;
2900
[email protected]0757e7702009-03-27 04:00:222901 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442902 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422903 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292904
2905 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422906 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292907
[email protected]0757e7702009-03-27 04:00:222908 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2909 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442910 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222912 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422913 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222914 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2915
2916 response = trans->GetResponseInfo();
2917 EXPECT_FALSE(response == NULL);
2918
2919 // The password prompt info should have been set in response->auth_challenge.
2920 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2921
[email protected]71e4573a2009-05-21 22:03:002922 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222923 EXPECT_EQ(L"", response->auth_challenge->realm);
2924 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2925
2926 TestCompletionCallback callback5;
2927
2928 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442929 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422930 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222931
2932 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422933 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222934
[email protected]385a4672009-03-11 22:21:292935 response = trans->GetResponseInfo();
2936 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2937 EXPECT_EQ(13, response->headers->GetContentLength());
2938}
[email protected]ea9dc9a2009-09-05 00:43:322939#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292940
[email protected]4ddaf2502008-10-23 18:26:192941// Test reading a server response which has only headers, and no body.
2942// After some maximum number of bytes is consumed, the transaction should
2943// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2944TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592945 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402946 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432947 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192948
[email protected]1c773ea12009-04-28 19:58:422949 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192950 request.method = "GET";
2951 request.url = GURL("http://www.google.com/");
2952 request.load_flags = 0;
2953
[email protected]b75b7b2f2009-10-06 00:54:532954 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432955 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532956 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192957
2958 MockRead data_reads[] = {
2959 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432960 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192961 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422962 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192963 };
[email protected]31a2bfe2010-02-09 08:03:392964 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592965 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192966
2967 TestCompletionCallback callback;
2968
[email protected]5a1d7ca2010-04-28 20:12:272969 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422970 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192971
2972 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422973 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192974
[email protected]1c773ea12009-04-28 19:58:422975 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192976 EXPECT_TRUE(response == NULL);
2977}
[email protected]f4e426b2008-11-05 00:24:492978
2979// Make sure that we don't try to reuse a TCPClientSocket when failing to
2980// establish tunnel.
2981// http://code.google.com/p/chromium/issues/detail?id=3772
2982TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2983 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002984 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012985
[email protected]228ff742009-06-05 01:19:592986 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492987
[email protected]5695b8c2009-09-30 21:36:432988 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492989
[email protected]1c773ea12009-04-28 19:58:422990 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492991 request.method = "GET";
2992 request.url = GURL("https://www.google.com/");
2993 request.load_flags = 0;
2994
2995 // Since we have proxy, should try to establish tunnel.
2996 MockWrite data_writes1[] = {
2997 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452998 "Host: www.google.com\r\n"
2999 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493000 };
3001
[email protected]77848d12008-11-14 00:00:223002 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493003 // connection. Usually a proxy would return 501 (not implemented),
3004 // or 200 (tunnel established).
3005 MockRead data_reads1[] = {
3006 MockRead("HTTP/1.1 404 Not Found\r\n"),
3007 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423008 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493009 };
3010
[email protected]31a2bfe2010-02-09 08:03:393011 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3012 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593013 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493014
3015 TestCompletionCallback callback1;
3016
[email protected]5a1d7ca2010-04-28 20:12:273017 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423018 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493019
3020 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423021 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493022
[email protected]1c773ea12009-04-28 19:58:423023 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083024 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493025
[email protected]b4404c02009-04-10 16:38:523026 // Empty the current queue. This is necessary because idle sockets are
3027 // added to the connection pool asynchronously with a PostTask.
3028 MessageLoop::current()->RunAllPending();
3029
[email protected]f4e426b2008-11-05 00:24:493030 // We now check to make sure the TCPClientSocket was not added back to
3031 // the pool.
[email protected]a937a06d2009-08-19 21:19:243032 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493033 trans.reset();
[email protected]b4404c02009-04-10 16:38:523034 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493035 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:243036 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493037}
[email protected]372d34a2008-11-05 21:30:513038
[email protected]1b157c02009-04-21 01:55:403039// Make sure that we recycle a socket after reading all of the response body.
3040TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:593041 SessionDependencies session_deps;
3042 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:403043
[email protected]5695b8c2009-09-30 21:36:433044 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:403045
[email protected]1c773ea12009-04-28 19:58:423046 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403047 request.method = "GET";
3048 request.url = GURL("http://www.google.com/");
3049 request.load_flags = 0;
3050
3051 MockRead data_reads[] = {
3052 // A part of the response body is received with the response headers.
3053 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3054 // The rest of the response body is received in two parts.
3055 MockRead("lo"),
3056 MockRead(" world"),
3057 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423058 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403059 };
3060
[email protected]31a2bfe2010-02-09 08:03:393061 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593062 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403063
3064 TestCompletionCallback callback;
3065
[email protected]5a1d7ca2010-04-28 20:12:273066 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423067 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403068
3069 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423070 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403071
[email protected]1c773ea12009-04-28 19:58:423072 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403073 EXPECT_TRUE(response != NULL);
3074
3075 EXPECT_TRUE(response->headers != NULL);
3076 std::string status_line = response->headers->GetStatusLine();
3077 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3078
[email protected]a937a06d2009-08-19 21:19:243079 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403080
3081 std::string response_data;
3082 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423083 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403084 EXPECT_EQ("hello world", response_data);
3085
3086 // Empty the current queue. This is necessary because idle sockets are
3087 // added to the connection pool asynchronously with a PostTask.
3088 MessageLoop::current()->RunAllPending();
3089
3090 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243091 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403092}
3093
[email protected]76a505b2010-08-25 06:23:003094// Make sure that we recycle a SSL socket after reading all of the response
3095// body.
3096TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3097 SessionDependencies session_deps;
3098 HttpRequestInfo request;
3099 request.method = "GET";
3100 request.url = GURL("https://www.google.com/");
3101 request.load_flags = 0;
3102
3103 MockWrite data_writes[] = {
3104 MockWrite("GET / HTTP/1.1\r\n"
3105 "Host: www.google.com\r\n"
3106 "Connection: keep-alive\r\n\r\n"),
3107 };
3108
3109 MockRead data_reads[] = {
3110 MockRead("HTTP/1.1 200 OK\r\n"),
3111 MockRead("Content-Length: 11\r\n\r\n"),
3112 MockRead("hello world"),
3113 MockRead(false, OK),
3114 };
3115
3116 SSLSocketDataProvider ssl(true, OK);
3117 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3118
3119 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3120 data_writes, arraysize(data_writes));
3121 session_deps.socket_factory.AddSocketDataProvider(&data);
3122
3123 TestCompletionCallback callback;
3124
3125 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3126 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3127
3128 int rv = trans->Start(&request, &callback, BoundNetLog());
3129
3130 EXPECT_EQ(ERR_IO_PENDING, rv);
3131 EXPECT_EQ(OK, callback.WaitForResult());
3132
3133 const HttpResponseInfo* response = trans->GetResponseInfo();
3134 ASSERT_TRUE(response != NULL);
3135 ASSERT_TRUE(response->headers != NULL);
3136 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3137
3138 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3139
3140 std::string response_data;
3141 rv = ReadTransaction(trans.get(), &response_data);
3142 EXPECT_EQ(OK, rv);
3143 EXPECT_EQ("hello world", response_data);
3144
3145 // Empty the current queue. This is necessary because idle sockets are
3146 // added to the connection pool asynchronously with a PostTask.
3147 MessageLoop::current()->RunAllPending();
3148
3149 // We now check to make sure the socket was added back to the pool.
3150 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3151}
3152
3153// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3154// from the pool and make sure that we recover okay.
3155TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3156 SessionDependencies session_deps;
3157 HttpRequestInfo request;
3158 request.method = "GET";
3159 request.url = GURL("https://www.google.com/");
3160 request.load_flags = 0;
3161
3162 MockWrite data_writes[] = {
3163 MockWrite("GET / HTTP/1.1\r\n"
3164 "Host: www.google.com\r\n"
3165 "Connection: keep-alive\r\n\r\n"),
3166 MockWrite("GET / HTTP/1.1\r\n"
3167 "Host: www.google.com\r\n"
3168 "Connection: keep-alive\r\n\r\n"),
3169 };
3170
3171 MockRead data_reads[] = {
3172 MockRead("HTTP/1.1 200 OK\r\n"),
3173 MockRead("Content-Length: 11\r\n\r\n"),
3174 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3175 MockRead("hello world"),
3176 MockRead(true, 0, 0) // EOF
3177 };
3178
3179 SSLSocketDataProvider ssl(true, OK);
3180 SSLSocketDataProvider ssl2(true, OK);
3181 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3182 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3183
3184 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3185 data_writes, arraysize(data_writes));
3186 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3187 data_writes, arraysize(data_writes));
3188 session_deps.socket_factory.AddSocketDataProvider(&data);
3189 session_deps.socket_factory.AddSocketDataProvider(&data2);
3190
3191 TestCompletionCallback callback;
3192
3193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3194 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3195
3196 int rv = trans->Start(&request, &callback, BoundNetLog());
3197
3198 EXPECT_EQ(ERR_IO_PENDING, rv);
3199 EXPECT_EQ(OK, callback.WaitForResult());
3200
3201 const HttpResponseInfo* response = trans->GetResponseInfo();
3202 ASSERT_TRUE(response != NULL);
3203 ASSERT_TRUE(response->headers != NULL);
3204 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3205
3206 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3207
3208 std::string response_data;
3209 rv = ReadTransaction(trans.get(), &response_data);
3210 EXPECT_EQ(OK, rv);
3211 EXPECT_EQ("hello world", response_data);
3212
3213 // Empty the current queue. This is necessary because idle sockets are
3214 // added to the connection pool asynchronously with a PostTask.
3215 MessageLoop::current()->RunAllPending();
3216
3217 // We now check to make sure the socket was added back to the pool.
3218 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3219
3220 // Now start the second transaction, which should reuse the previous socket.
3221
3222 trans.reset(new HttpNetworkTransaction(session));
3223
3224 rv = trans->Start(&request, &callback, BoundNetLog());
3225
3226 EXPECT_EQ(ERR_IO_PENDING, rv);
3227 EXPECT_EQ(OK, callback.WaitForResult());
3228
3229 response = trans->GetResponseInfo();
3230 ASSERT_TRUE(response != NULL);
3231 ASSERT_TRUE(response->headers != NULL);
3232 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3233
3234 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3235
3236 rv = ReadTransaction(trans.get(), &response_data);
3237 EXPECT_EQ(OK, rv);
3238 EXPECT_EQ("hello world", response_data);
3239
3240 // Empty the current queue. This is necessary because idle sockets are
3241 // added to the connection pool asynchronously with a PostTask.
3242 MessageLoop::current()->RunAllPending();
3243
3244 // We now check to make sure the socket was added back to the pool.
3245 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3246}
3247
[email protected]b4404c02009-04-10 16:38:523248// Make sure that we recycle a socket after a zero-length response.
3249// http://crbug.com/9880
3250TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:593251 SessionDependencies session_deps;
3252 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:523253
[email protected]5695b8c2009-09-30 21:36:433254 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:523255
[email protected]1c773ea12009-04-28 19:58:423256 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523257 request.method = "GET";
3258 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3259 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3260 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3261 "rt=prt.2642,ol.2649,xjs.2951");
3262 request.load_flags = 0;
3263
3264 MockRead data_reads[] = {
3265 MockRead("HTTP/1.1 204 No Content\r\n"
3266 "Content-Length: 0\r\n"
3267 "Content-Type: text/html\r\n\r\n"),
3268 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423269 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523270 };
3271
[email protected]31a2bfe2010-02-09 08:03:393272 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593273 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523274
3275 TestCompletionCallback callback;
3276
[email protected]5a1d7ca2010-04-28 20:12:273277 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423278 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523279
3280 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423281 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523282
[email protected]1c773ea12009-04-28 19:58:423283 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523284 EXPECT_TRUE(response != NULL);
3285
3286 EXPECT_TRUE(response->headers != NULL);
3287 std::string status_line = response->headers->GetStatusLine();
3288 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3289
[email protected]a937a06d2009-08-19 21:19:243290 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523291
3292 std::string response_data;
3293 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423294 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523295 EXPECT_EQ("", response_data);
3296
3297 // Empty the current queue. This is necessary because idle sockets are
3298 // added to the connection pool asynchronously with a PostTask.
3299 MessageLoop::current()->RunAllPending();
3300
3301 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243302 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523303}
3304
[email protected]372d34a2008-11-05 21:30:513305TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423306 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513307 // Transaction 1: a GET request that succeeds. The socket is recycled
3308 // after use.
3309 request[0].method = "GET";
3310 request[0].url = GURL("http://www.google.com/");
3311 request[0].load_flags = 0;
3312 // Transaction 2: a POST request. Reuses the socket kept alive from
3313 // transaction 1. The first attempts fails when writing the POST data.
3314 // This causes the transaction to retry with a new socket. The second
3315 // attempt succeeds.
3316 request[1].method = "POST";
3317 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423318 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513319 request[1].upload_data->AppendBytes("foo", 3);
3320 request[1].load_flags = 0;
3321
[email protected]228ff742009-06-05 01:19:593322 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273323 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513324
3325 // The first socket is used for transaction 1 and the first attempt of
3326 // transaction 2.
3327
3328 // The response of transaction 1.
3329 MockRead data_reads1[] = {
3330 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3331 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423332 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513333 };
3334 // The mock write results of transaction 1 and the first attempt of
3335 // transaction 2.
3336 MockWrite data_writes1[] = {
3337 MockWrite(false, 64), // GET
3338 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423339 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513340 };
[email protected]31a2bfe2010-02-09 08:03:393341 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3342 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513343
3344 // The second socket is used for the second attempt of transaction 2.
3345
3346 // The response of transaction 2.
3347 MockRead data_reads2[] = {
3348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3349 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423350 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513351 };
3352 // The mock write results of the second attempt of transaction 2.
3353 MockWrite data_writes2[] = {
3354 MockWrite(false, 93), // POST
3355 MockWrite(false, 3), // POST data
3356 };
[email protected]31a2bfe2010-02-09 08:03:393357 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3358 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513359
[email protected]5ecc992a42009-11-11 01:41:593360 session_deps.socket_factory.AddSocketDataProvider(&data1);
3361 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513362
3363 const char* kExpectedResponseData[] = {
3364 "hello world", "welcome"
3365 };
3366
3367 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423368 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433369 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513370
3371 TestCompletionCallback callback;
3372
[email protected]5a1d7ca2010-04-28 20:12:273373 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423374 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513375
3376 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423377 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513378
[email protected]1c773ea12009-04-28 19:58:423379 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513380 EXPECT_TRUE(response != NULL);
3381
3382 EXPECT_TRUE(response->headers != NULL);
3383 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3384
3385 std::string response_data;
3386 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423387 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513388 EXPECT_EQ(kExpectedResponseData[i], response_data);
3389 }
3390}
[email protected]f9ee6b52008-11-08 06:46:233391
3392// Test the request-challenge-retry sequence for basic auth when there is
3393// an identity in the URL. The request should be sent as normal, but when
3394// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323395TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593396 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403397 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433398 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233399
[email protected]1c773ea12009-04-28 19:58:423400 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233401 request.method = "GET";
3402 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293403 request.url = GURL("http://foo:b@[email protected]/");
3404
3405 // The password contains an escaped character -- for this test to pass it
3406 // will need to be unescaped by HttpNetworkTransaction.
3407 EXPECT_EQ("b%40r", request.url.password());
3408
[email protected]ea9dc9a2009-09-05 00:43:323409 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233410
3411 MockWrite data_writes1[] = {
3412 MockWrite("GET / HTTP/1.1\r\n"
3413 "Host: www.google.com\r\n"
3414 "Connection: keep-alive\r\n\r\n"),
3415 };
3416
3417 MockRead data_reads1[] = {
3418 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3419 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3420 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423421 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233422 };
3423
3424 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323425 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233426 MockWrite data_writes2[] = {
3427 MockWrite("GET / HTTP/1.1\r\n"
3428 "Host: www.google.com\r\n"
3429 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293430 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233431 };
3432
3433 MockRead data_reads2[] = {
3434 MockRead("HTTP/1.0 200 OK\r\n"),
3435 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423436 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233437 };
3438
[email protected]31a2bfe2010-02-09 08:03:393439 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3440 data_writes1, arraysize(data_writes1));
3441 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3442 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593443 session_deps.socket_factory.AddSocketDataProvider(&data1);
3444 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233445
3446 TestCompletionCallback callback1;
3447
[email protected]5a1d7ca2010-04-28 20:12:273448 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423449 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233450
3451 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423452 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233453
[email protected]0757e7702009-03-27 04:00:223454 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3455 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443456 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423457 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223458 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423459 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223460 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3461
[email protected]1c773ea12009-04-28 19:58:423462 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233463 EXPECT_FALSE(response == NULL);
3464
3465 // There is no challenge info, since the identity in URL worked.
3466 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3467
3468 EXPECT_EQ(100, response->headers->GetContentLength());
3469
3470 // Empty the current queue.
3471 MessageLoop::current()->RunAllPending();
3472}
3473
[email protected]ea9dc9a2009-09-05 00:43:323474// Test the request-challenge-retry sequence for basic auth when there is
3475// an incorrect identity in the URL. The identity from the URL should be used
3476// only once.
3477TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3478 SessionDependencies session_deps;
3479 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433480 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323481
3482 HttpRequestInfo request;
3483 request.method = "GET";
3484 // Note: the URL has a username:password in it. The password "baz" is
3485 // wrong (should be "bar").
3486 request.url = GURL("http://foo:[email protected]/");
3487
3488 request.load_flags = LOAD_NORMAL;
3489
3490 MockWrite data_writes1[] = {
3491 MockWrite("GET / HTTP/1.1\r\n"
3492 "Host: www.google.com\r\n"
3493 "Connection: keep-alive\r\n\r\n"),
3494 };
3495
3496 MockRead data_reads1[] = {
3497 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3498 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3499 MockRead("Content-Length: 10\r\n\r\n"),
3500 MockRead(false, ERR_FAILED),
3501 };
3502
3503 // After the challenge above, the transaction will be restarted using the
3504 // identity from the url (foo, baz) to answer the challenge.
3505 MockWrite data_writes2[] = {
3506 MockWrite("GET / HTTP/1.1\r\n"
3507 "Host: www.google.com\r\n"
3508 "Connection: keep-alive\r\n"
3509 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3510 };
3511
3512 MockRead data_reads2[] = {
3513 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3514 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3515 MockRead("Content-Length: 10\r\n\r\n"),
3516 MockRead(false, ERR_FAILED),
3517 };
3518
3519 // After the challenge above, the transaction will be restarted using the
3520 // identity supplied by the user (foo, bar) to answer the challenge.
3521 MockWrite data_writes3[] = {
3522 MockWrite("GET / HTTP/1.1\r\n"
3523 "Host: www.google.com\r\n"
3524 "Connection: keep-alive\r\n"
3525 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3526 };
3527
3528 MockRead data_reads3[] = {
3529 MockRead("HTTP/1.0 200 OK\r\n"),
3530 MockRead("Content-Length: 100\r\n\r\n"),
3531 MockRead(false, OK),
3532 };
3533
[email protected]31a2bfe2010-02-09 08:03:393534 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3535 data_writes1, arraysize(data_writes1));
3536 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3537 data_writes2, arraysize(data_writes2));
3538 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3539 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593540 session_deps.socket_factory.AddSocketDataProvider(&data1);
3541 session_deps.socket_factory.AddSocketDataProvider(&data2);
3542 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323543
3544 TestCompletionCallback callback1;
3545
[email protected]5a1d7ca2010-04-28 20:12:273546 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323547 EXPECT_EQ(ERR_IO_PENDING, rv);
3548
3549 rv = callback1.WaitForResult();
3550 EXPECT_EQ(OK, rv);
3551
3552 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3553 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443554 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323555 EXPECT_EQ(ERR_IO_PENDING, rv);
3556 rv = callback2.WaitForResult();
3557 EXPECT_EQ(OK, rv);
3558 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3559
3560 const HttpResponseInfo* response = trans->GetResponseInfo();
3561 EXPECT_FALSE(response == NULL);
3562 // The password prompt info should have been set in response->auth_challenge.
3563 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3564
3565 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3566 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3567 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3568
3569 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443570 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323571 EXPECT_EQ(ERR_IO_PENDING, rv);
3572 rv = callback3.WaitForResult();
3573 EXPECT_EQ(OK, rv);
3574 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3575
3576 response = trans->GetResponseInfo();
3577 EXPECT_FALSE(response == NULL);
3578
3579 // There is no challenge info, since the identity worked.
3580 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3581
3582 EXPECT_EQ(100, response->headers->GetContentLength());
3583
3584 // Empty the current queue.
3585 MessageLoop::current()->RunAllPending();
3586}
3587
[email protected]f9ee6b52008-11-08 06:46:233588// Test that previously tried username/passwords for a realm get re-used.
3589TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593590 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233592
3593 // Transaction 1: authenticate (foo, bar) on MyRealm1
3594 {
[email protected]5695b8c2009-09-30 21:36:433595 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233596
[email protected]1c773ea12009-04-28 19:58:423597 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233598 request.method = "GET";
3599 request.url = GURL("http://www.google.com/x/y/z");
3600 request.load_flags = 0;
3601
3602 MockWrite data_writes1[] = {
3603 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3604 "Host: www.google.com\r\n"
3605 "Connection: keep-alive\r\n\r\n"),
3606 };
3607
3608 MockRead data_reads1[] = {
3609 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3610 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3611 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423612 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233613 };
3614
3615 // Resend with authorization (username=foo, password=bar)
3616 MockWrite data_writes2[] = {
3617 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3618 "Host: www.google.com\r\n"
3619 "Connection: keep-alive\r\n"
3620 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3621 };
3622
3623 // Sever accepts the authorization.
3624 MockRead data_reads2[] = {
3625 MockRead("HTTP/1.0 200 OK\r\n"),
3626 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423627 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233628 };
3629
[email protected]31a2bfe2010-02-09 08:03:393630 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3631 data_writes1, arraysize(data_writes1));
3632 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3633 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593634 session_deps.socket_factory.AddSocketDataProvider(&data1);
3635 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233636
3637 TestCompletionCallback callback1;
3638
[email protected]5a1d7ca2010-04-28 20:12:273639 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423640 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233641
3642 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423643 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233644
[email protected]1c773ea12009-04-28 19:58:423645 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233646 EXPECT_FALSE(response == NULL);
3647
3648 // The password prompt info should have been set in
3649 // response->auth_challenge.
3650 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3651
[email protected]71e4573a2009-05-21 22:03:003652 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233653 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3654 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3655
3656 TestCompletionCallback callback2;
3657
[email protected]13c8a092010-07-29 06:15:443658 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423659 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233660
3661 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423662 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233663
3664 response = trans->GetResponseInfo();
3665 EXPECT_FALSE(response == NULL);
3666 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3667 EXPECT_EQ(100, response->headers->GetContentLength());
3668 }
3669
3670 // ------------------------------------------------------------------------
3671
3672 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3673 {
[email protected]5695b8c2009-09-30 21:36:433674 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233675
[email protected]1c773ea12009-04-28 19:58:423676 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233677 request.method = "GET";
3678 // Note that Transaction 1 was at /x/y/z, so this is in the same
3679 // protection space as MyRealm1.
3680 request.url = GURL("http://www.google.com/x/y/a/b");
3681 request.load_flags = 0;
3682
3683 MockWrite data_writes1[] = {
3684 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3685 "Host: www.google.com\r\n"
3686 "Connection: keep-alive\r\n"
3687 // Send preemptive authorization for MyRealm1
3688 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3689 };
3690
3691 // The server didn't like the preemptive authorization, and
3692 // challenges us for a different realm (MyRealm2).
3693 MockRead data_reads1[] = {
3694 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3695 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3696 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423697 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233698 };
3699
3700 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3701 MockWrite data_writes2[] = {
3702 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3703 "Host: www.google.com\r\n"
3704 "Connection: keep-alive\r\n"
3705 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3706 };
3707
3708 // Sever accepts the authorization.
3709 MockRead data_reads2[] = {
3710 MockRead("HTTP/1.0 200 OK\r\n"),
3711 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423712 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233713 };
3714
[email protected]31a2bfe2010-02-09 08:03:393715 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3716 data_writes1, arraysize(data_writes1));
3717 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3718 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593719 session_deps.socket_factory.AddSocketDataProvider(&data1);
3720 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233721
3722 TestCompletionCallback callback1;
3723
[email protected]5a1d7ca2010-04-28 20:12:273724 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423725 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233726
3727 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423728 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233729
[email protected]1c773ea12009-04-28 19:58:423730 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233731 EXPECT_FALSE(response == NULL);
3732
3733 // The password prompt info should have been set in
3734 // response->auth_challenge.
3735 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3736
[email protected]71e4573a2009-05-21 22:03:003737 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233738 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3739 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3740
3741 TestCompletionCallback callback2;
3742
[email protected]13c8a092010-07-29 06:15:443743 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233745
3746 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423747 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233748
3749 response = trans->GetResponseInfo();
3750 EXPECT_FALSE(response == NULL);
3751 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3752 EXPECT_EQ(100, response->headers->GetContentLength());
3753 }
3754
3755 // ------------------------------------------------------------------------
3756
3757 // Transaction 3: Resend a request in MyRealm's protection space --
3758 // succeed with preemptive authorization.
3759 {
[email protected]5695b8c2009-09-30 21:36:433760 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233761
[email protected]1c773ea12009-04-28 19:58:423762 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233763 request.method = "GET";
3764 request.url = GURL("http://www.google.com/x/y/z2");
3765 request.load_flags = 0;
3766
3767 MockWrite data_writes1[] = {
3768 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3769 "Host: www.google.com\r\n"
3770 "Connection: keep-alive\r\n"
3771 // The authorization for MyRealm1 gets sent preemptively
3772 // (since the url is in the same protection space)
3773 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3774 };
3775
3776 // Sever accepts the preemptive authorization
3777 MockRead data_reads1[] = {
3778 MockRead("HTTP/1.0 200 OK\r\n"),
3779 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423780 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233781 };
3782
[email protected]31a2bfe2010-02-09 08:03:393783 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3784 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593785 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233786
3787 TestCompletionCallback callback1;
3788
[email protected]5a1d7ca2010-04-28 20:12:273789 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423790 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233791
3792 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423793 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233794
[email protected]1c773ea12009-04-28 19:58:423795 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233796 EXPECT_FALSE(response == NULL);
3797
3798 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3799 EXPECT_EQ(100, response->headers->GetContentLength());
3800 }
3801
3802 // ------------------------------------------------------------------------
3803
3804 // Transaction 4: request another URL in MyRealm (however the
3805 // url is not known to belong to the protection space, so no pre-auth).
3806 {
[email protected]5695b8c2009-09-30 21:36:433807 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233808
[email protected]1c773ea12009-04-28 19:58:423809 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233810 request.method = "GET";
3811 request.url = GURL("http://www.google.com/x/1");
3812 request.load_flags = 0;
3813
3814 MockWrite data_writes1[] = {
3815 MockWrite("GET /x/1 HTTP/1.1\r\n"
3816 "Host: www.google.com\r\n"
3817 "Connection: keep-alive\r\n\r\n"),
3818 };
3819
3820 MockRead data_reads1[] = {
3821 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3822 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3823 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423824 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233825 };
3826
3827 // Resend with authorization from MyRealm's cache.
3828 MockWrite data_writes2[] = {
3829 MockWrite("GET /x/1 HTTP/1.1\r\n"
3830 "Host: www.google.com\r\n"
3831 "Connection: keep-alive\r\n"
3832 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3833 };
3834
3835 // Sever accepts the authorization.
3836 MockRead data_reads2[] = {
3837 MockRead("HTTP/1.0 200 OK\r\n"),
3838 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423839 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233840 };
3841
[email protected]31a2bfe2010-02-09 08:03:393842 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3843 data_writes1, arraysize(data_writes1));
3844 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3845 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593846 session_deps.socket_factory.AddSocketDataProvider(&data1);
3847 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233848
3849 TestCompletionCallback callback1;
3850
[email protected]5a1d7ca2010-04-28 20:12:273851 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423852 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233853
3854 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423855 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233856
[email protected]0757e7702009-03-27 04:00:223857 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3858 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443859 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423860 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223861 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423862 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223863 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3864
[email protected]1c773ea12009-04-28 19:58:423865 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233866 EXPECT_FALSE(response == NULL);
3867 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3868 EXPECT_EQ(100, response->headers->GetContentLength());
3869 }
3870
3871 // ------------------------------------------------------------------------
3872
3873 // Transaction 5: request a URL in MyRealm, but the server rejects the
3874 // cached identity. Should invalidate and re-prompt.
3875 {
[email protected]5695b8c2009-09-30 21:36:433876 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233877
[email protected]1c773ea12009-04-28 19:58:423878 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233879 request.method = "GET";
3880 request.url = GURL("http://www.google.com/p/q/t");
3881 request.load_flags = 0;
3882
3883 MockWrite data_writes1[] = {
3884 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3885 "Host: www.google.com\r\n"
3886 "Connection: keep-alive\r\n\r\n"),
3887 };
3888
3889 MockRead data_reads1[] = {
3890 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3891 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3892 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423893 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233894 };
3895
3896 // Resend with authorization from cache for MyRealm.
3897 MockWrite data_writes2[] = {
3898 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3899 "Host: www.google.com\r\n"
3900 "Connection: keep-alive\r\n"
3901 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3902 };
3903
3904 // Sever rejects the authorization.
3905 MockRead data_reads2[] = {
3906 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3907 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3908 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423909 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233910 };
3911
3912 // At this point we should prompt for new credentials for MyRealm.
3913 // Restart with username=foo3, password=foo4.
3914 MockWrite data_writes3[] = {
3915 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3916 "Host: www.google.com\r\n"
3917 "Connection: keep-alive\r\n"
3918 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3919 };
3920
3921 // Sever accepts the authorization.
3922 MockRead data_reads3[] = {
3923 MockRead("HTTP/1.0 200 OK\r\n"),
3924 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423925 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233926 };
3927
[email protected]31a2bfe2010-02-09 08:03:393928 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3929 data_writes1, arraysize(data_writes1));
3930 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3931 data_writes2, arraysize(data_writes2));
3932 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3933 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593934 session_deps.socket_factory.AddSocketDataProvider(&data1);
3935 session_deps.socket_factory.AddSocketDataProvider(&data2);
3936 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233937
3938 TestCompletionCallback callback1;
3939
[email protected]5a1d7ca2010-04-28 20:12:273940 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423941 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233942
3943 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423944 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233945
[email protected]0757e7702009-03-27 04:00:223946 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3947 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443948 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423949 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223950 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423951 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223952 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3953
[email protected]1c773ea12009-04-28 19:58:423954 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233955 EXPECT_FALSE(response == NULL);
3956
3957 // The password prompt info should have been set in
3958 // response->auth_challenge.
3959 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3960
[email protected]71e4573a2009-05-21 22:03:003961 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233962 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3963 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3964
[email protected]0757e7702009-03-27 04:00:223965 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233966
[email protected]13c8a092010-07-29 06:15:443967 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423968 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233969
[email protected]0757e7702009-03-27 04:00:223970 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423971 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233972
3973 response = trans->GetResponseInfo();
3974 EXPECT_FALSE(response == NULL);
3975 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3976 EXPECT_EQ(100, response->headers->GetContentLength());
3977 }
3978}
[email protected]89ceba9a2009-03-21 03:46:063979
[email protected]3c32c5f2010-05-18 15:18:123980// Tests that nonce count increments when multiple auth attempts
3981// are started with the same nonce.
3982TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3983 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273984 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:123985 HttpAuthHandlerDigest::SetFixedCnonce(true);
3986
3987 // Transaction 1: authenticate (foo, bar) on MyRealm1
3988 {
3989 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3990
3991 HttpRequestInfo request;
3992 request.method = "GET";
3993 request.url = GURL("http://www.google.com/x/y/z");
3994 request.load_flags = 0;
3995
3996 MockWrite data_writes1[] = {
3997 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3998 "Host: www.google.com\r\n"
3999 "Connection: keep-alive\r\n\r\n"),
4000 };
4001
4002 MockRead data_reads1[] = {
4003 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4004 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4005 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4006 MockRead(false, OK),
4007 };
4008
4009 // Resend with authorization (username=foo, password=bar)
4010 MockWrite data_writes2[] = {
4011 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4012 "Host: www.google.com\r\n"
4013 "Connection: keep-alive\r\n"
4014 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4015 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4016 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4017 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4018 };
4019
4020 // Sever accepts the authorization.
4021 MockRead data_reads2[] = {
4022 MockRead("HTTP/1.0 200 OK\r\n"),
4023 MockRead(false, OK),
4024 };
4025
4026 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4027 data_writes1, arraysize(data_writes1));
4028 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4029 data_writes2, arraysize(data_writes2));
4030 session_deps.socket_factory.AddSocketDataProvider(&data1);
4031 session_deps.socket_factory.AddSocketDataProvider(&data2);
4032
4033 TestCompletionCallback callback1;
4034
4035 int rv = trans->Start(&request, &callback1, BoundNetLog());
4036 EXPECT_EQ(ERR_IO_PENDING, rv);
4037
4038 rv = callback1.WaitForResult();
4039 EXPECT_EQ(OK, rv);
4040
4041 const HttpResponseInfo* response = trans->GetResponseInfo();
4042 ASSERT_FALSE(response == NULL);
4043
4044 // The password prompt info should have been set in
4045 // response->auth_challenge.
4046 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4047
4048 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4049 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4050 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4051
4052 TestCompletionCallback callback2;
4053
[email protected]13c8a092010-07-29 06:15:444054 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124055 EXPECT_EQ(ERR_IO_PENDING, rv);
4056
4057 rv = callback2.WaitForResult();
4058 EXPECT_EQ(OK, rv);
4059
4060 response = trans->GetResponseInfo();
4061 ASSERT_FALSE(response == NULL);
4062 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4063 }
4064
4065 // ------------------------------------------------------------------------
4066
4067 // Transaction 2: Request another resource in digestive's protection space.
4068 // This will preemptively add an Authorization header which should have an
4069 // "nc" value of 2 (as compared to 1 in the first use.
4070 {
4071 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4072
4073 HttpRequestInfo request;
4074 request.method = "GET";
4075 // Note that Transaction 1 was at /x/y/z, so this is in the same
4076 // protection space as digest.
4077 request.url = GURL("http://www.google.com/x/y/a/b");
4078 request.load_flags = 0;
4079
4080 MockWrite data_writes1[] = {
4081 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4082 "Host: www.google.com\r\n"
4083 "Connection: keep-alive\r\n"
4084 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4085 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4086 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4087 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4088 };
4089
4090 // Sever accepts the authorization.
4091 MockRead data_reads1[] = {
4092 MockRead("HTTP/1.0 200 OK\r\n"),
4093 MockRead("Content-Length: 100\r\n\r\n"),
4094 MockRead(false, OK),
4095 };
4096
4097 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4098 data_writes1, arraysize(data_writes1));
4099 session_deps.socket_factory.AddSocketDataProvider(&data1);
4100
4101 TestCompletionCallback callback1;
4102
4103 int rv = trans->Start(&request, &callback1, BoundNetLog());
4104 EXPECT_EQ(ERR_IO_PENDING, rv);
4105
4106 rv = callback1.WaitForResult();
4107 EXPECT_EQ(OK, rv);
4108
4109 const HttpResponseInfo* response = trans->GetResponseInfo();
4110 ASSERT_FALSE(response == NULL);
4111 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4112 }
4113}
4114
[email protected]89ceba9a2009-03-21 03:46:064115// Test the ResetStateForRestart() private method.
4116TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4117 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594118 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404119 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434120 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064121
4122 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064123 trans->read_buf_ = new IOBuffer(15);
4124 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204125 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064126
4127 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144128 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574129 response->auth_challenge = new AuthChallengeInfo();
4130 response->ssl_info.cert_status = -15;
4131 response->response_time = base::Time::Now();
4132 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064133
4134 { // Setup state for response_.vary_data
4135 HttpRequestInfo request;
4136 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4137 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274138 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434139 request.extra_headers.SetHeader("Foo", "1");
4140 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574141 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064142 }
4143
4144 // Cause the above state to be reset.
4145 trans->ResetStateForRestart();
4146
4147 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074148 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064149 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204150 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574151 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4152 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044153 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574154 EXPECT_EQ(0, response->ssl_info.cert_status);
4155 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064156}
4157
[email protected]bacff652009-03-31 17:50:334158// Test HTTPS connections to a site with a bad certificate
4159TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:594160 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404161 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434162 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334163
4164 HttpRequestInfo request;
4165 request.method = "GET";
4166 request.url = GURL("https://www.google.com/");
4167 request.load_flags = 0;
4168
4169 MockWrite data_writes[] = {
4170 MockWrite("GET / HTTP/1.1\r\n"
4171 "Host: www.google.com\r\n"
4172 "Connection: keep-alive\r\n\r\n"),
4173 };
4174
4175 MockRead data_reads[] = {
4176 MockRead("HTTP/1.0 200 OK\r\n"),
4177 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4178 MockRead("Content-Length: 100\r\n\r\n"),
4179 MockRead(false, OK),
4180 };
4181
[email protected]5ecc992a42009-11-11 01:41:594182 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394183 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4184 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594185 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4186 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334187
[email protected]5ecc992a42009-11-11 01:41:594188 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4189 session_deps.socket_factory.AddSocketDataProvider(&data);
4190 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4191 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334192
4193 TestCompletionCallback callback;
4194
[email protected]5a1d7ca2010-04-28 20:12:274195 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334196 EXPECT_EQ(ERR_IO_PENDING, rv);
4197
4198 rv = callback.WaitForResult();
4199 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4200
4201 rv = trans->RestartIgnoringLastError(&callback);
4202 EXPECT_EQ(ERR_IO_PENDING, rv);
4203
4204 rv = callback.WaitForResult();
4205 EXPECT_EQ(OK, rv);
4206
4207 const HttpResponseInfo* response = trans->GetResponseInfo();
4208
4209 EXPECT_FALSE(response == NULL);
4210 EXPECT_EQ(100, response->headers->GetContentLength());
4211}
4212
4213// Test HTTPS connections to a site with a bad certificate, going through a
4214// proxy
4215TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004216 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334217
4218 HttpRequestInfo request;
4219 request.method = "GET";
4220 request.url = GURL("https://www.google.com/");
4221 request.load_flags = 0;
4222
4223 MockWrite proxy_writes[] = {
4224 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454225 "Host: www.google.com\r\n"
4226 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334227 };
4228
4229 MockRead proxy_reads[] = {
4230 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424231 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334232 };
4233
4234 MockWrite data_writes[] = {
4235 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454236 "Host: www.google.com\r\n"
4237 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334238 MockWrite("GET / HTTP/1.1\r\n"
4239 "Host: www.google.com\r\n"
4240 "Connection: keep-alive\r\n\r\n"),
4241 };
4242
4243 MockRead data_reads[] = {
4244 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4245 MockRead("HTTP/1.0 200 OK\r\n"),
4246 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4247 MockRead("Content-Length: 100\r\n\r\n"),
4248 MockRead(false, OK),
4249 };
4250
[email protected]31a2bfe2010-02-09 08:03:394251 StaticSocketDataProvider ssl_bad_certificate(
4252 proxy_reads, arraysize(proxy_reads),
4253 proxy_writes, arraysize(proxy_writes));
4254 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4255 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594256 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4257 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334258
[email protected]5ecc992a42009-11-11 01:41:594259 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4260 session_deps.socket_factory.AddSocketDataProvider(&data);
4261 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4262 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334263
4264 TestCompletionCallback callback;
4265
4266 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594267 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334268
[email protected]d207a5f2009-06-04 05:28:404269 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434270 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334271
[email protected]5a1d7ca2010-04-28 20:12:274272 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334273 EXPECT_EQ(ERR_IO_PENDING, rv);
4274
4275 rv = callback.WaitForResult();
4276 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4277
4278 rv = trans->RestartIgnoringLastError(&callback);
4279 EXPECT_EQ(ERR_IO_PENDING, rv);
4280
4281 rv = callback.WaitForResult();
4282 EXPECT_EQ(OK, rv);
4283
4284 const HttpResponseInfo* response = trans->GetResponseInfo();
4285
4286 EXPECT_FALSE(response == NULL);
4287 EXPECT_EQ(100, response->headers->GetContentLength());
4288 }
4289}
4290
[email protected]2df19bb2010-08-25 20:13:464291
4292// Test HTTPS connections to a site, going through an HTTPS proxy
4293TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004294 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464295
4296 HttpRequestInfo request;
4297 request.method = "GET";
4298 request.url = GURL("https://www.google.com/");
4299 request.load_flags = 0;
4300
4301 MockWrite data_writes[] = {
4302 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4303 "Host: www.google.com\r\n"
4304 "Proxy-Connection: keep-alive\r\n\r\n"),
4305 MockWrite("GET / HTTP/1.1\r\n"
4306 "Host: www.google.com\r\n"
4307 "Connection: keep-alive\r\n\r\n"),
4308 };
4309
4310 MockRead data_reads[] = {
4311 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4312 MockRead("HTTP/1.1 200 OK\r\n"),
4313 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4314 MockRead("Content-Length: 100\r\n\r\n"),
4315 MockRead(false, OK),
4316 };
4317
4318 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4319 data_writes, arraysize(data_writes));
4320 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4321 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4322
4323 session_deps.socket_factory.AddSocketDataProvider(&data);
4324 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4325 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4326
4327 TestCompletionCallback callback;
4328
4329 scoped_ptr<HttpTransaction> trans(
4330 new HttpNetworkTransaction(CreateSession(&session_deps)));
4331
4332 int rv = trans->Start(&request, &callback, BoundNetLog());
4333 EXPECT_EQ(ERR_IO_PENDING, rv);
4334
4335 rv = callback.WaitForResult();
4336 EXPECT_EQ(OK, rv);
4337 const HttpResponseInfo* response = trans->GetResponseInfo();
4338
4339 ASSERT_FALSE(response == NULL);
4340
4341 EXPECT_TRUE(response->headers->IsKeepAlive());
4342 EXPECT_EQ(200, response->headers->response_code());
4343 EXPECT_EQ(100, response->headers->GetContentLength());
4344 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4345}
4346
4347// Test HTTPS connections to a site with a bad certificate, going through an
4348// HTTPS proxy
4349TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004350 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464351
4352 HttpRequestInfo request;
4353 request.method = "GET";
4354 request.url = GURL("https://www.google.com/");
4355 request.load_flags = 0;
4356
4357 // Attempt to fetch the URL from a server with a bad cert
4358 MockWrite bad_cert_writes[] = {
4359 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4360 "Host: www.google.com\r\n"
4361 "Proxy-Connection: keep-alive\r\n\r\n"),
4362 };
4363
4364 MockRead bad_cert_reads[] = {
4365 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4366 MockRead(false, OK)
4367 };
4368
4369 // Attempt to fetch the URL with a good cert
4370 MockWrite good_data_writes[] = {
4371 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4372 "Host: www.google.com\r\n"
4373 "Proxy-Connection: keep-alive\r\n\r\n"),
4374 MockWrite("GET / HTTP/1.1\r\n"
4375 "Host: www.google.com\r\n"
4376 "Connection: keep-alive\r\n\r\n"),
4377 };
4378
4379 MockRead good_cert_reads[] = {
4380 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4381 MockRead("HTTP/1.0 200 OK\r\n"),
4382 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4383 MockRead("Content-Length: 100\r\n\r\n"),
4384 MockRead(false, OK),
4385 };
4386
4387 StaticSocketDataProvider ssl_bad_certificate(
4388 bad_cert_reads, arraysize(bad_cert_reads),
4389 bad_cert_writes, arraysize(bad_cert_writes));
4390 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4391 good_data_writes, arraysize(good_data_writes));
4392 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4393 SSLSocketDataProvider ssl(true, OK);
4394
4395 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4396 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4397 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4398 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4399
4400 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4401 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4402 session_deps.socket_factory.AddSocketDataProvider(&data);
4403 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4404
4405 TestCompletionCallback callback;
4406
4407 scoped_ptr<HttpTransaction> trans(
4408 new HttpNetworkTransaction(CreateSession(&session_deps)));
4409
4410 int rv = trans->Start(&request, &callback, BoundNetLog());
4411 EXPECT_EQ(ERR_IO_PENDING, rv);
4412
4413 rv = callback.WaitForResult();
4414 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4415
4416 rv = trans->RestartIgnoringLastError(&callback);
4417 EXPECT_EQ(ERR_IO_PENDING, rv);
4418
4419 rv = callback.WaitForResult();
4420 EXPECT_EQ(OK, rv);
4421
4422 const HttpResponseInfo* response = trans->GetResponseInfo();
4423
4424 EXPECT_FALSE(response == NULL);
4425 EXPECT_EQ(100, response->headers->GetContentLength());
4426}
4427
[email protected]1c773ea12009-04-28 19:58:424428TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594429 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404430 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434431 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424432
4433 HttpRequestInfo request;
4434 request.method = "GET";
4435 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434436 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4437 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424438
4439 MockWrite data_writes[] = {
4440 MockWrite("GET / HTTP/1.1\r\n"
4441 "Host: www.google.com\r\n"
4442 "Connection: keep-alive\r\n"
4443 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4444 };
4445
4446 // Lastly, the server responds with the actual content.
4447 MockRead data_reads[] = {
4448 MockRead("HTTP/1.0 200 OK\r\n"),
4449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4450 MockRead("Content-Length: 100\r\n\r\n"),
4451 MockRead(false, OK),
4452 };
4453
[email protected]31a2bfe2010-02-09 08:03:394454 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4455 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594456 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424457
4458 TestCompletionCallback callback;
4459
[email protected]5a1d7ca2010-04-28 20:12:274460 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424461 EXPECT_EQ(ERR_IO_PENDING, rv);
4462
4463 rv = callback.WaitForResult();
4464 EXPECT_EQ(OK, rv);
4465}
4466
[email protected]da81f132010-08-18 23:39:294467TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]81cdfcd2010-10-16 00:49:004468 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]da81f132010-08-18 23:39:294469 scoped_ptr<HttpTransaction> trans(
4470 new HttpNetworkTransaction(CreateSession(&session_deps)));
4471
4472 HttpRequestInfo request;
4473 request.method = "GET";
4474 request.url = GURL("https://www.google.com/");
4475 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4476 "Chromium Ultra Awesome X Edition");
4477
4478 MockWrite data_writes[] = {
4479 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4480 "Host: www.google.com\r\n"
4481 "Proxy-Connection: keep-alive\r\n"
4482 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4483 };
4484 MockRead data_reads[] = {
4485 // Return an error, so the transaction stops here (this test isn't
4486 // interested in the rest).
4487 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4488 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4489 MockRead("Proxy-Connection: close\r\n\r\n"),
4490 };
4491
4492 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4493 data_writes, arraysize(data_writes));
4494 session_deps.socket_factory.AddSocketDataProvider(&data);
4495
4496 TestCompletionCallback callback;
4497
4498 int rv = trans->Start(&request, &callback, BoundNetLog());
4499 EXPECT_EQ(ERR_IO_PENDING, rv);
4500
4501 rv = callback.WaitForResult();
4502 EXPECT_EQ(OK, rv);
4503}
4504
[email protected]1c773ea12009-04-28 19:58:424505TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594506 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404507 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434508 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424509
4510 HttpRequestInfo request;
4511 request.method = "GET";
4512 request.url = GURL("http://www.google.com/");
4513 request.load_flags = 0;
4514 request.referrer = GURL("http://the.previous.site.com/");
4515
4516 MockWrite data_writes[] = {
4517 MockWrite("GET / HTTP/1.1\r\n"
4518 "Host: www.google.com\r\n"
4519 "Connection: keep-alive\r\n"
4520 "Referer: http://the.previous.site.com/\r\n\r\n"),
4521 };
4522
4523 // Lastly, the server responds with the actual content.
4524 MockRead data_reads[] = {
4525 MockRead("HTTP/1.0 200 OK\r\n"),
4526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4527 MockRead("Content-Length: 100\r\n\r\n"),
4528 MockRead(false, OK),
4529 };
4530
[email protected]31a2bfe2010-02-09 08:03:394531 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4532 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594533 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424534
4535 TestCompletionCallback callback;
4536
[email protected]5a1d7ca2010-04-28 20:12:274537 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424538 EXPECT_EQ(ERR_IO_PENDING, rv);
4539
4540 rv = callback.WaitForResult();
4541 EXPECT_EQ(OK, rv);
4542}
4543
4544TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594545 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404546 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434547 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424548
4549 HttpRequestInfo request;
4550 request.method = "POST";
4551 request.url = GURL("http://www.google.com/");
4552
4553 MockWrite data_writes[] = {
4554 MockWrite("POST / HTTP/1.1\r\n"
4555 "Host: www.google.com\r\n"
4556 "Connection: keep-alive\r\n"
4557 "Content-Length: 0\r\n\r\n"),
4558 };
4559
4560 // Lastly, the server responds with the actual content.
4561 MockRead data_reads[] = {
4562 MockRead("HTTP/1.0 200 OK\r\n"),
4563 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4564 MockRead("Content-Length: 100\r\n\r\n"),
4565 MockRead(false, OK),
4566 };
4567
[email protected]31a2bfe2010-02-09 08:03:394568 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4569 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594570 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424571
4572 TestCompletionCallback callback;
4573
[email protected]5a1d7ca2010-04-28 20:12:274574 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424575 EXPECT_EQ(ERR_IO_PENDING, rv);
4576
4577 rv = callback.WaitForResult();
4578 EXPECT_EQ(OK, rv);
4579}
4580
4581TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594582 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404583 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434584 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424585
4586 HttpRequestInfo request;
4587 request.method = "PUT";
4588 request.url = GURL("http://www.google.com/");
4589
4590 MockWrite data_writes[] = {
4591 MockWrite("PUT / HTTP/1.1\r\n"
4592 "Host: www.google.com\r\n"
4593 "Connection: keep-alive\r\n"
4594 "Content-Length: 0\r\n\r\n"),
4595 };
4596
4597 // Lastly, the server responds with the actual content.
4598 MockRead data_reads[] = {
4599 MockRead("HTTP/1.0 200 OK\r\n"),
4600 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4601 MockRead("Content-Length: 100\r\n\r\n"),
4602 MockRead(false, OK),
4603 };
4604
[email protected]31a2bfe2010-02-09 08:03:394605 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4606 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594607 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424608
4609 TestCompletionCallback callback;
4610
[email protected]5a1d7ca2010-04-28 20:12:274611 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424612 EXPECT_EQ(ERR_IO_PENDING, rv);
4613
4614 rv = callback.WaitForResult();
4615 EXPECT_EQ(OK, rv);
4616}
4617
4618TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594619 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404620 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434621 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424622
4623 HttpRequestInfo request;
4624 request.method = "HEAD";
4625 request.url = GURL("http://www.google.com/");
4626
4627 MockWrite data_writes[] = {
4628 MockWrite("HEAD / HTTP/1.1\r\n"
4629 "Host: www.google.com\r\n"
4630 "Connection: keep-alive\r\n"
4631 "Content-Length: 0\r\n\r\n"),
4632 };
4633
4634 // Lastly, the server responds with the actual content.
4635 MockRead data_reads[] = {
4636 MockRead("HTTP/1.0 200 OK\r\n"),
4637 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4638 MockRead("Content-Length: 100\r\n\r\n"),
4639 MockRead(false, OK),
4640 };
4641
[email protected]31a2bfe2010-02-09 08:03:394642 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4643 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594644 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424645
4646 TestCompletionCallback callback;
4647
[email protected]5a1d7ca2010-04-28 20:12:274648 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424649 EXPECT_EQ(ERR_IO_PENDING, rv);
4650
4651 rv = callback.WaitForResult();
4652 EXPECT_EQ(OK, rv);
4653}
4654
4655TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594656 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404657 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434658 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424659
4660 HttpRequestInfo request;
4661 request.method = "GET";
4662 request.url = GURL("http://www.google.com/");
4663 request.load_flags = LOAD_BYPASS_CACHE;
4664
4665 MockWrite data_writes[] = {
4666 MockWrite("GET / HTTP/1.1\r\n"
4667 "Host: www.google.com\r\n"
4668 "Connection: keep-alive\r\n"
4669 "Pragma: no-cache\r\n"
4670 "Cache-Control: no-cache\r\n\r\n"),
4671 };
4672
4673 // Lastly, the server responds with the actual content.
4674 MockRead data_reads[] = {
4675 MockRead("HTTP/1.0 200 OK\r\n"),
4676 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4677 MockRead("Content-Length: 100\r\n\r\n"),
4678 MockRead(false, OK),
4679 };
4680
[email protected]31a2bfe2010-02-09 08:03:394681 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4682 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594683 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424684
4685 TestCompletionCallback callback;
4686
[email protected]5a1d7ca2010-04-28 20:12:274687 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424688 EXPECT_EQ(ERR_IO_PENDING, rv);
4689
4690 rv = callback.WaitForResult();
4691 EXPECT_EQ(OK, rv);
4692}
4693
4694TEST_F(HttpNetworkTransactionTest,
4695 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594696 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404697 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434698 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424699
4700 HttpRequestInfo request;
4701 request.method = "GET";
4702 request.url = GURL("http://www.google.com/");
4703 request.load_flags = LOAD_VALIDATE_CACHE;
4704
4705 MockWrite data_writes[] = {
4706 MockWrite("GET / HTTP/1.1\r\n"
4707 "Host: www.google.com\r\n"
4708 "Connection: keep-alive\r\n"
4709 "Cache-Control: max-age=0\r\n\r\n"),
4710 };
4711
4712 // Lastly, the server responds with the actual content.
4713 MockRead data_reads[] = {
4714 MockRead("HTTP/1.0 200 OK\r\n"),
4715 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4716 MockRead("Content-Length: 100\r\n\r\n"),
4717 MockRead(false, OK),
4718 };
4719
[email protected]31a2bfe2010-02-09 08:03:394720 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4721 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594722 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424723
4724 TestCompletionCallback callback;
4725
[email protected]5a1d7ca2010-04-28 20:12:274726 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424727 EXPECT_EQ(ERR_IO_PENDING, rv);
4728
4729 rv = callback.WaitForResult();
4730 EXPECT_EQ(OK, rv);
4731}
4732
4733TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594734 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404735 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434736 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424737
4738 HttpRequestInfo request;
4739 request.method = "GET";
4740 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434741 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424742
4743 MockWrite data_writes[] = {
4744 MockWrite("GET / HTTP/1.1\r\n"
4745 "Host: www.google.com\r\n"
4746 "Connection: keep-alive\r\n"
4747 "FooHeader: Bar\r\n\r\n"),
4748 };
4749
4750 // Lastly, the server responds with the actual content.
4751 MockRead data_reads[] = {
4752 MockRead("HTTP/1.0 200 OK\r\n"),
4753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4754 MockRead("Content-Length: 100\r\n\r\n"),
4755 MockRead(false, OK),
4756 };
4757
[email protected]31a2bfe2010-02-09 08:03:394758 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4759 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594760 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424761
4762 TestCompletionCallback callback;
4763
[email protected]5a1d7ca2010-04-28 20:12:274764 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424765 EXPECT_EQ(ERR_IO_PENDING, rv);
4766
4767 rv = callback.WaitForResult();
4768 EXPECT_EQ(OK, rv);
4769}
4770
[email protected]270c6412010-03-29 22:02:474771TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4772 SessionDependencies session_deps;
4773 scoped_ptr<HttpTransaction> trans(
4774 new HttpNetworkTransaction(CreateSession(&session_deps)));
4775
4776 HttpRequestInfo request;
4777 request.method = "GET";
4778 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434779 request.extra_headers.SetHeader("referer", "www.foo.com");
4780 request.extra_headers.SetHeader("hEllo", "Kitty");
4781 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474782
4783 MockWrite data_writes[] = {
4784 MockWrite("GET / HTTP/1.1\r\n"
4785 "Host: www.google.com\r\n"
4786 "Connection: keep-alive\r\n"
4787 "hEllo: Kitty\r\n"
4788 "FoO: bar\r\n\r\n"),
4789 };
4790
4791 // Lastly, the server responds with the actual content.
4792 MockRead data_reads[] = {
4793 MockRead("HTTP/1.0 200 OK\r\n"),
4794 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4795 MockRead("Content-Length: 100\r\n\r\n"),
4796 MockRead(false, OK),
4797 };
4798
4799 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4800 data_writes, arraysize(data_writes));
4801 session_deps.socket_factory.AddSocketDataProvider(&data);
4802
4803 TestCompletionCallback callback;
4804
[email protected]5a1d7ca2010-04-28 20:12:274805 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474806 EXPECT_EQ(ERR_IO_PENDING, rv);
4807
4808 rv = callback.WaitForResult();
4809 EXPECT_EQ(OK, rv);
4810}
4811
[email protected]3cd17242009-06-23 02:59:024812TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094813 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004814 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024815
4816 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434817 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024818
4819 HttpRequestInfo request;
4820 request.method = "GET";
4821 request.url = GURL("http://www.google.com/");
4822 request.load_flags = 0;
4823
4824 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4825 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4826
4827 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354828 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024829 MockWrite("GET / HTTP/1.1\r\n"
4830 "Host: www.google.com\r\n"
4831 "Connection: keep-alive\r\n\r\n")
4832 };
4833
4834 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594835 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024836 MockRead("HTTP/1.0 200 OK\r\n"),
4837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4838 MockRead("Payload"),
4839 MockRead(false, OK)
4840 };
4841
[email protected]31a2bfe2010-02-09 08:03:394842 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4843 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594844 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024845
4846 TestCompletionCallback callback;
4847
[email protected]5a1d7ca2010-04-28 20:12:274848 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024849 EXPECT_EQ(ERR_IO_PENDING, rv);
4850
4851 rv = callback.WaitForResult();
4852 EXPECT_EQ(OK, rv);
4853
4854 const HttpResponseInfo* response = trans->GetResponseInfo();
4855 EXPECT_FALSE(response == NULL);
4856
4857 std::string response_text;
4858 rv = ReadTransaction(trans.get(), &response_text);
4859 EXPECT_EQ(OK, rv);
4860 EXPECT_EQ("Payload", response_text);
4861}
4862
4863TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094864 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004865 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024866
4867 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434868 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024869
4870 HttpRequestInfo request;
4871 request.method = "GET";
4872 request.url = GURL("https://www.google.com/");
4873 request.load_flags = 0;
4874
4875 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4876 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4877
4878 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354879 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4880 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024881 MockWrite("GET / HTTP/1.1\r\n"
4882 "Host: www.google.com\r\n"
4883 "Connection: keep-alive\r\n\r\n")
4884 };
4885
4886 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354887 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4888 arraysize(read_buffer)),
4889 MockRead("HTTP/1.0 200 OK\r\n"),
4890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4891 MockRead("Payload"),
4892 MockRead(false, OK)
4893 };
4894
[email protected]31a2bfe2010-02-09 08:03:394895 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4896 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594897 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354898
[email protected]5ecc992a42009-11-11 01:41:594899 SSLSocketDataProvider ssl(true, OK);
4900 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354901
4902 TestCompletionCallback callback;
4903
[email protected]5a1d7ca2010-04-28 20:12:274904 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354905 EXPECT_EQ(ERR_IO_PENDING, rv);
4906
4907 rv = callback.WaitForResult();
4908 EXPECT_EQ(OK, rv);
4909
4910 const HttpResponseInfo* response = trans->GetResponseInfo();
4911 EXPECT_FALSE(response == NULL);
4912
4913 std::string response_text;
4914 rv = ReadTransaction(trans.get(), &response_text);
4915 EXPECT_EQ(OK, rv);
4916 EXPECT_EQ("Payload", response_text);
4917}
4918
4919TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094920 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004921 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354922
4923 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434924 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354925
4926 HttpRequestInfo request;
4927 request.method = "GET";
4928 request.url = GURL("http://www.google.com/");
4929 request.load_flags = 0;
4930
4931 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4932 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374933 const char kSOCKS5OkRequest[] = {
4934 0x05, // Version
4935 0x01, // Command (CONNECT)
4936 0x00, // Reserved.
4937 0x03, // Address type (DOMAINNAME).
4938 0x0E, // Length of domain (14)
4939 // Domain string:
4940 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4941 0x00, 0x50, // 16-bit port (80)
4942 };
[email protected]e0c27be2009-07-15 13:09:354943 const char kSOCKS5OkResponse[] =
4944 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4945
4946 MockWrite data_writes[] = {
4947 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4948 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4949 MockWrite("GET / HTTP/1.1\r\n"
4950 "Host: www.google.com\r\n"
4951 "Connection: keep-alive\r\n\r\n")
4952 };
4953
4954 MockRead data_reads[] = {
4955 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4956 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4957 MockRead("HTTP/1.0 200 OK\r\n"),
4958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4959 MockRead("Payload"),
4960 MockRead(false, OK)
4961 };
4962
[email protected]31a2bfe2010-02-09 08:03:394963 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4964 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594965 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354966
4967 TestCompletionCallback callback;
4968
[email protected]5a1d7ca2010-04-28 20:12:274969 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354970 EXPECT_EQ(ERR_IO_PENDING, rv);
4971
4972 rv = callback.WaitForResult();
4973 EXPECT_EQ(OK, rv);
4974
4975 const HttpResponseInfo* response = trans->GetResponseInfo();
4976 EXPECT_FALSE(response == NULL);
4977
4978 std::string response_text;
4979 rv = ReadTransaction(trans.get(), &response_text);
4980 EXPECT_EQ(OK, rv);
4981 EXPECT_EQ("Payload", response_text);
4982}
4983
4984TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094985 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004986 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354987
4988 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434989 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354990
4991 HttpRequestInfo request;
4992 request.method = "GET";
4993 request.url = GURL("https://www.google.com/");
4994 request.load_flags = 0;
4995
4996 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4997 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374998 const unsigned char kSOCKS5OkRequest[] = {
4999 0x05, // Version
5000 0x01, // Command (CONNECT)
5001 0x00, // Reserved.
5002 0x03, // Address type (DOMAINNAME).
5003 0x0E, // Length of domain (14)
5004 // Domain string:
5005 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5006 0x01, 0xBB, // 16-bit port (443)
5007 };
5008
[email protected]e0c27be2009-07-15 13:09:355009 const char kSOCKS5OkResponse[] =
5010 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5011
5012 MockWrite data_writes[] = {
5013 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5014 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5015 arraysize(kSOCKS5OkRequest)),
5016 MockWrite("GET / HTTP/1.1\r\n"
5017 "Host: www.google.com\r\n"
5018 "Connection: keep-alive\r\n\r\n")
5019 };
5020
5021 MockRead data_reads[] = {
5022 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5023 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025024 MockRead("HTTP/1.0 200 OK\r\n"),
5025 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5026 MockRead("Payload"),
5027 MockRead(false, OK)
5028 };
5029
[email protected]31a2bfe2010-02-09 08:03:395030 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5031 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595032 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025033
[email protected]5ecc992a42009-11-11 01:41:595034 SSLSocketDataProvider ssl(true, OK);
5035 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025036
5037 TestCompletionCallback callback;
5038
[email protected]5a1d7ca2010-04-28 20:12:275039 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025040 EXPECT_EQ(ERR_IO_PENDING, rv);
5041
5042 rv = callback.WaitForResult();
5043 EXPECT_EQ(OK, rv);
5044
5045 const HttpResponseInfo* response = trans->GetResponseInfo();
5046 EXPECT_FALSE(response == NULL);
5047
5048 std::string response_text;
5049 rv = ReadTransaction(trans.get(), &response_text);
5050 EXPECT_EQ(OK, rv);
5051 EXPECT_EQ("Payload", response_text);
5052}
5053
[email protected]04e5be32009-06-26 20:00:315054// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065055
5056struct GroupNameTest {
5057 std::string proxy_server;
5058 std::string url;
5059 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185060 bool ssl;
[email protected]2d731a32010-04-29 01:04:065061};
5062
5063scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5064 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:005065 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:065066 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5067
5068 HttpAlternateProtocols* alternate_protocols =
5069 session->mutable_alternate_protocols();
5070 alternate_protocols->SetAlternateProtocolFor(
5071 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355072 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065073
5074 return session;
5075}
5076
5077int GroupNameTransactionHelper(
5078 const std::string& url,
5079 const scoped_refptr<HttpNetworkSession>& session) {
5080 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5081
5082 HttpRequestInfo request;
5083 request.method = "GET";
5084 request.url = GURL(url);
5085 request.load_flags = 0;
5086
5087 TestCompletionCallback callback;
5088
5089 // We do not complete this request, the dtor will clean the transaction up.
5090 return trans->Start(&request, &callback, BoundNetLog());
5091}
5092
5093TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5094 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315095 {
[email protected]2d731a32010-04-29 01:04:065096 "", // unused
[email protected]04e5be32009-06-26 20:00:315097 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545098 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185099 false,
[email protected]2ff8b312010-04-26 22:20:545100 },
5101 {
[email protected]2d731a32010-04-29 01:04:065102 "", // unused
[email protected]2ff8b312010-04-26 22:20:545103 "http://[2001:1418:13:1::25]/direct",
5104 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185105 false,
[email protected]04e5be32009-06-26 20:00:315106 },
[email protected]04e5be32009-06-26 20:00:315107
5108 // SSL Tests
5109 {
[email protected]2d731a32010-04-29 01:04:065110 "", // unused
[email protected]04e5be32009-06-26 20:00:315111 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025112 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185113 true,
[email protected]04e5be32009-06-26 20:00:315114 },
5115 {
[email protected]2d731a32010-04-29 01:04:065116 "", // unused
5117 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025118 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185119 true,
[email protected]04e5be32009-06-26 20:00:315120 },
5121 {
[email protected]2d731a32010-04-29 01:04:065122 "", // unused
[email protected]2ff8b312010-04-26 22:20:545123 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025124 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185125 true,
[email protected]2ff8b312010-04-26 22:20:545126 },
[email protected]2d731a32010-04-29 01:04:065127 };
[email protected]2ff8b312010-04-26 22:20:545128
[email protected]8e6441ca2010-08-19 05:56:385129 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065130
5131 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5132 scoped_refptr<HttpNetworkSession> session(
5133 SetupSessionForGroupNameTests(tests[i].proxy_server));
5134
5135 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135136 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5137 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065138 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135139 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5140 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185141 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065142
5143 EXPECT_EQ(ERR_IO_PENDING,
5144 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185145 if (tests[i].ssl)
5146 EXPECT_EQ(tests[i].expected_group_name,
5147 ssl_conn_pool->last_group_name_received());
5148 else
5149 EXPECT_EQ(tests[i].expected_group_name,
5150 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065151 }
5152
[email protected]8e6441ca2010-08-19 05:56:385153 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065154}
5155
5156TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5157 const GroupNameTest tests[] = {
5158 {
5159 "http_proxy",
5160 "http://www.google.com/http_proxy_normal",
5161 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185162 false,
[email protected]2d731a32010-04-29 01:04:065163 },
5164
5165 // SSL Tests
5166 {
5167 "http_proxy",
5168 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025169 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185170 true,
[email protected]2d731a32010-04-29 01:04:065171 },
[email protected]af3490e2010-10-16 21:02:295172
[email protected]9faeded92010-04-29 20:03:055173 {
5174 "http_proxy",
5175 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025176 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185177 true,
[email protected]9faeded92010-04-29 20:03:055178 },
[email protected]2d731a32010-04-29 01:04:065179 };
5180
[email protected]8e6441ca2010-08-19 05:56:385181 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065182
5183 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5184 scoped_refptr<HttpNetworkSession> session(
5185 SetupSessionForGroupNameTests(tests[i].proxy_server));
5186
5187 HttpNetworkSessionPeer peer(session);
5188
[email protected]e60e47a2010-07-14 03:37:185189 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135190 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5191 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185192 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135193 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5194 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185195 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065196
5197 EXPECT_EQ(ERR_IO_PENDING,
5198 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185199 if (tests[i].ssl)
5200 EXPECT_EQ(tests[i].expected_group_name,
5201 ssl_conn_pool->last_group_name_received());
5202 else
5203 EXPECT_EQ(tests[i].expected_group_name,
5204 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065205 }
5206
[email protected]8e6441ca2010-08-19 05:56:385207 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065208}
5209
5210TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5211 const GroupNameTest tests[] = {
5212 {
5213 "socks4://socks_proxy:1080",
5214 "http://www.google.com/socks4_direct",
5215 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185216 false,
[email protected]2d731a32010-04-29 01:04:065217 },
5218 {
5219 "socks5://socks_proxy:1080",
5220 "http://www.google.com/socks5_direct",
5221 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185222 false,
[email protected]2d731a32010-04-29 01:04:065223 },
5224
5225 // SSL Tests
5226 {
5227 "socks4://socks_proxy:1080",
5228 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025229 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185230 true,
[email protected]2d731a32010-04-29 01:04:065231 },
5232 {
5233 "socks5://socks_proxy:1080",
5234 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025235 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185236 true,
[email protected]2d731a32010-04-29 01:04:065237 },
[email protected]af3490e2010-10-16 21:02:295238
[email protected]9faeded92010-04-29 20:03:055239 {
5240 "socks4://socks_proxy:1080",
5241 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025242 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185243 true,
[email protected]9faeded92010-04-29 20:03:055244 },
[email protected]04e5be32009-06-26 20:00:315245 };
5246
[email protected]8e6441ca2010-08-19 05:56:385247 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545248
[email protected]04e5be32009-06-26 20:00:315249 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065250 scoped_refptr<HttpNetworkSession> session(
5251 SetupSessionForGroupNameTests(tests[i].proxy_server));
5252 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315253
[email protected]e60e47a2010-07-14 03:37:185254 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135255 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5256 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185257 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135258 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5259 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185260 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315261
[email protected]5695b8c2009-09-30 21:36:435262 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315263
[email protected]2d731a32010-04-29 01:04:065264 EXPECT_EQ(ERR_IO_PENDING,
5265 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185266 if (tests[i].ssl)
5267 EXPECT_EQ(tests[i].expected_group_name,
5268 ssl_conn_pool->last_group_name_received());
5269 else
5270 EXPECT_EQ(tests[i].expected_group_name,
5271 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315272 }
[email protected]2ff8b312010-04-26 22:20:545273
[email protected]8e6441ca2010-08-19 05:56:385274 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315275}
5276
[email protected]9172a982009-06-06 00:30:255277TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545278 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005279 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325280
[email protected]69719062010-01-05 20:09:215281 // This simulates failure resolving all hostnames; that means we will fail
5282 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325283 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5284
[email protected]9172a982009-06-06 00:30:255285 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435286 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255287
5288 HttpRequestInfo request;
5289 request.method = "GET";
5290 request.url = GURL("http://www.google.com/");
5291
5292 TestCompletionCallback callback;
5293
[email protected]5a1d7ca2010-04-28 20:12:275294 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255295 EXPECT_EQ(ERR_IO_PENDING, rv);
5296
[email protected]9172a982009-06-06 00:30:255297 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015298 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255299}
5300
[email protected]f3e6c1e2009-06-15 20:52:125301// Host resolution observer used by
5302// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5303// resovle requests are issued with a referrer of |expected_referrer|.
5304class ResolutionReferrerObserver : public HostResolver::Observer {
5305 public:
5306 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5307 : expected_referrer_(expected_referrer),
5308 called_start_with_referrer_(false),
5309 called_finish_with_referrer_(false) {
5310 }
5311
5312 virtual void OnStartResolution(int id,
5313 const HostResolver::RequestInfo& info) {
5314 if (info.referrer() == expected_referrer_)
5315 called_start_with_referrer_ = true;
5316 }
5317
5318 virtual void OnFinishResolutionWithStatus(
5319 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5320 if (info.referrer() == expected_referrer_)
5321 called_finish_with_referrer_ = true;
5322 }
5323
[email protected]eb255d32009-06-17 02:11:035324 virtual void OnCancelResolution(int id,
5325 const HostResolver::RequestInfo& info ) {
5326 FAIL() << "Should not be cancelling any requests!";
5327 }
5328
[email protected]f3e6c1e2009-06-15 20:52:125329 bool did_complete_with_expected_referrer() const {
5330 return called_start_with_referrer_ && called_finish_with_referrer_;
5331 }
5332
5333 private:
5334 GURL expected_referrer_;
5335 bool called_start_with_referrer_;
5336 bool called_finish_with_referrer_;
5337
5338 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5339};
5340
5341// Make sure that when HostResolver::Resolve() is invoked, it passes through
5342// the "referrer". This is depended on by the DNS prefetch observer.
5343TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5344 GURL referrer = GURL("http://expected-referrer/");
5345 EXPECT_TRUE(referrer.is_valid());
5346 ResolutionReferrerObserver resolution_observer(referrer);
5347
5348 SessionDependencies session_deps;
5349 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435350 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125351
5352 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145353 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125354
5355 // Connect up a mock socket which will fail when reading.
5356 MockRead data_reads[] = {
5357 MockRead(false, ERR_FAILED),
5358 };
[email protected]31a2bfe2010-02-09 08:03:395359 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595360 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125361
5362 // Issue a request, containing an HTTP referrer.
5363 HttpRequestInfo request;
5364 request.method = "GET";
5365 request.referrer = referrer;
5366 request.url = GURL("http://www.google.com/");
5367
5368 // Run the request until it fails reading from the socket.
5369 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275370 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125371 EXPECT_EQ(ERR_IO_PENDING, rv);
5372 rv = callback.WaitForResult();
5373 EXPECT_EQ(ERR_FAILED, rv);
5374
5375 // Check that the host resolution observer saw |referrer|.
5376 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5377}
5378
[email protected]685af592010-05-11 19:31:245379// Base test to make sure that when the load flags for a request specify to
5380// bypass the cache, the DNS cache is not used.
5381void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285382 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325383
[email protected]a2c2fb92009-07-18 07:31:045384 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545385 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325386
[email protected]3b9cca42009-06-16 01:08:285387 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435388 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285389
5390 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5391 // a synchronous lookup.)
5392 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145393 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105394 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275395 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285396 EXPECT_EQ(OK, rv);
5397
5398 // Verify that it was added to host cache, by doing a subsequent async lookup
5399 // and confirming it completes synchronously.
5400 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465401 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105402 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275403 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325404 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285405
5406 // Inject a failure the next time that "www.google.com" is resolved. This way
5407 // we can tell if the next lookup hit the cache, or the "network".
5408 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325409 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285410
5411 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5412 // first read -- this won't be reached as the host resolution will fail first.
5413 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395414 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595415 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285416
5417 // Issue a request, asking to bypass the cache(s).
5418 HttpRequestInfo request;
5419 request.method = "GET";
[email protected]685af592010-05-11 19:31:245420 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285421 request.url = GURL("http://www.google.com/");
5422
5423 // Run the request.
5424 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275425 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285426 ASSERT_EQ(ERR_IO_PENDING, rv);
5427 rv = callback.WaitForResult();
5428
5429 // If we bypassed the cache, we would have gotten a failure while resolving
5430 // "www.google.com".
5431 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5432}
5433
[email protected]685af592010-05-11 19:31:245434// There are multiple load flags that should trigger the host cache bypass.
5435// Test each in isolation:
5436TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5437 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5438}
5439
5440TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5441 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5442}
5443
5444TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5445 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5446}
5447
[email protected]0877e3d2009-10-17 22:29:575448// Make sure we can handle an error when writing the request.
5449TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5450 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275451 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575452
5453 HttpRequestInfo request;
5454 request.method = "GET";
5455 request.url = GURL("http://www.foo.com/");
5456 request.load_flags = 0;
5457
5458 MockWrite write_failure[] = {
5459 MockWrite(true, ERR_CONNECTION_RESET),
5460 };
[email protected]31a2bfe2010-02-09 08:03:395461 StaticSocketDataProvider data(NULL, 0,
5462 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595463 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575464
5465 TestCompletionCallback callback;
5466
5467 scoped_ptr<HttpTransaction> trans(
5468 new HttpNetworkTransaction(CreateSession(&session_deps)));
5469
[email protected]5a1d7ca2010-04-28 20:12:275470 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575471 EXPECT_EQ(ERR_IO_PENDING, rv);
5472
5473 rv = callback.WaitForResult();
5474 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5475}
5476
5477// Check that a connection closed after the start of the headers finishes ok.
5478TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5479 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275480 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575481
5482 HttpRequestInfo request;
5483 request.method = "GET";
5484 request.url = GURL("http://www.foo.com/");
5485 request.load_flags = 0;
5486
5487 MockRead data_reads[] = {
5488 MockRead("HTTP/1."),
5489 MockRead(false, OK),
5490 };
5491
[email protected]31a2bfe2010-02-09 08:03:395492 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595493 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575494
5495 TestCompletionCallback callback;
5496
5497 scoped_ptr<HttpTransaction> trans(
5498 new HttpNetworkTransaction(CreateSession(&session_deps)));
5499
[email protected]5a1d7ca2010-04-28 20:12:275500 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575501 EXPECT_EQ(ERR_IO_PENDING, rv);
5502
5503 rv = callback.WaitForResult();
5504 EXPECT_EQ(OK, rv);
5505
5506 const HttpResponseInfo* response = trans->GetResponseInfo();
5507 EXPECT_TRUE(response != NULL);
5508
5509 EXPECT_TRUE(response->headers != NULL);
5510 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5511
5512 std::string response_data;
5513 rv = ReadTransaction(trans.get(), &response_data);
5514 EXPECT_EQ(OK, rv);
5515 EXPECT_EQ("", response_data);
5516}
5517
5518// Make sure that a dropped connection while draining the body for auth
5519// restart does the right thing.
5520TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5521 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275522 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575523
5524 HttpRequestInfo request;
5525 request.method = "GET";
5526 request.url = GURL("http://www.google.com/");
5527 request.load_flags = 0;
5528
5529 MockWrite data_writes1[] = {
5530 MockWrite("GET / HTTP/1.1\r\n"
5531 "Host: www.google.com\r\n"
5532 "Connection: keep-alive\r\n\r\n"),
5533 };
5534
5535 MockRead data_reads1[] = {
5536 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5537 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5538 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5539 MockRead("Content-Length: 14\r\n\r\n"),
5540 MockRead("Unauth"),
5541 MockRead(true, ERR_CONNECTION_RESET),
5542 };
5543
[email protected]31a2bfe2010-02-09 08:03:395544 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5545 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595546 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575547
5548 // After calling trans->RestartWithAuth(), this is the request we should
5549 // be issuing -- the final header line contains the credentials.
5550 MockWrite data_writes2[] = {
5551 MockWrite("GET / HTTP/1.1\r\n"
5552 "Host: www.google.com\r\n"
5553 "Connection: keep-alive\r\n"
5554 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5555 };
5556
5557 // Lastly, the server responds with the actual content.
5558 MockRead data_reads2[] = {
5559 MockRead("HTTP/1.1 200 OK\r\n"),
5560 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5561 MockRead("Content-Length: 100\r\n\r\n"),
5562 MockRead(false, OK),
5563 };
5564
[email protected]31a2bfe2010-02-09 08:03:395565 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5566 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595567 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575568
5569 TestCompletionCallback callback1;
5570
[email protected]0b0bf032010-09-21 18:08:505571 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5572
[email protected]5a1d7ca2010-04-28 20:12:275573 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575574 EXPECT_EQ(ERR_IO_PENDING, rv);
5575
5576 rv = callback1.WaitForResult();
5577 EXPECT_EQ(OK, rv);
5578
5579 const HttpResponseInfo* response = trans->GetResponseInfo();
5580 EXPECT_FALSE(response == NULL);
5581
5582 // The password prompt info should have been set in response->auth_challenge.
5583 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5584
5585 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5586 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5587 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5588
5589 TestCompletionCallback callback2;
5590
[email protected]13c8a092010-07-29 06:15:445591 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575592 EXPECT_EQ(ERR_IO_PENDING, rv);
5593
5594 rv = callback2.WaitForResult();
5595 EXPECT_EQ(OK, rv);
5596
5597 response = trans->GetResponseInfo();
5598 EXPECT_FALSE(response == NULL);
5599 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5600 EXPECT_EQ(100, response->headers->GetContentLength());
5601}
5602
5603// Test HTTPS connections going through a proxy that sends extra data.
5604TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005605 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575606
5607 HttpRequestInfo request;
5608 request.method = "GET";
5609 request.url = GURL("https://www.google.com/");
5610 request.load_flags = 0;
5611
5612 MockRead proxy_reads[] = {
5613 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5614 MockRead(false, OK)
5615 };
5616
[email protected]31a2bfe2010-02-09 08:03:395617 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595618 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575619
[email protected]5ecc992a42009-11-11 01:41:595620 session_deps.socket_factory.AddSocketDataProvider(&data);
5621 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575622
5623 TestCompletionCallback callback;
5624
5625 session_deps.socket_factory.ResetNextMockIndexes();
5626
5627 scoped_ptr<HttpTransaction> trans(
5628 new HttpNetworkTransaction(CreateSession(&session_deps)));
5629
[email protected]5a1d7ca2010-04-28 20:12:275630 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575631 EXPECT_EQ(ERR_IO_PENDING, rv);
5632
5633 rv = callback.WaitForResult();
5634 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5635}
5636
[email protected]e22e1362009-11-23 21:31:125637TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465638 SessionDependencies session_deps;
5639 scoped_ptr<HttpTransaction> trans(
5640 new HttpNetworkTransaction(CreateSession(&session_deps)));
5641
5642 HttpRequestInfo request;
5643 request.method = "GET";
5644 request.url = GURL("http://www.google.com/");
5645 request.load_flags = 0;
5646
[email protected]e22e1362009-11-23 21:31:125647 MockRead data_reads[] = {
5648 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5649 MockRead(false, OK),
5650 };
[email protected]9492e4a2010-02-24 00:58:465651
5652 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5653 session_deps.socket_factory.AddSocketDataProvider(&data);
5654
5655 TestCompletionCallback callback;
5656
[email protected]5a1d7ca2010-04-28 20:12:275657 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465658 EXPECT_EQ(ERR_IO_PENDING, rv);
5659
5660 EXPECT_EQ(OK, callback.WaitForResult());
5661
5662 const HttpResponseInfo* response = trans->GetResponseInfo();
5663 EXPECT_TRUE(response != NULL);
5664
5665 EXPECT_TRUE(response->headers != NULL);
5666 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5667
5668 std::string response_data;
5669 rv = ReadTransaction(trans.get(), &response_data);
5670 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125671}
5672
[email protected]95d88ffe2010-02-04 21:25:335673TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5674 SessionDependencies session_deps;
5675 scoped_ptr<HttpTransaction> trans(
5676 new HttpNetworkTransaction(CreateSession(&session_deps)));
5677
5678 HttpRequestInfo request;
5679 request.method = "POST";
5680 request.url = GURL("http://www.google.com/upload");
5681 request.upload_data = new UploadData;
5682 request.load_flags = 0;
5683
5684 FilePath temp_file_path;
5685 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5686 const uint64 kFakeSize = 100000; // file is actually blank
5687
5688 std::vector<UploadData::Element> elements;
5689 UploadData::Element element;
5690 element.SetToFilePath(temp_file_path);
5691 element.SetContentLength(kFakeSize);
5692 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535693 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335694 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5695
5696 MockRead data_reads[] = {
5697 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5698 MockRead("hello world"),
5699 MockRead(false, OK),
5700 };
[email protected]31a2bfe2010-02-09 08:03:395701 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335702 session_deps.socket_factory.AddSocketDataProvider(&data);
5703
5704 TestCompletionCallback callback;
5705
[email protected]5a1d7ca2010-04-28 20:12:275706 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335707 EXPECT_EQ(ERR_IO_PENDING, rv);
5708
5709 rv = callback.WaitForResult();
5710 EXPECT_EQ(OK, rv);
5711
5712 const HttpResponseInfo* response = trans->GetResponseInfo();
5713 EXPECT_TRUE(response != NULL);
5714
5715 EXPECT_TRUE(response->headers != NULL);
5716 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5717
5718 std::string response_data;
5719 rv = ReadTransaction(trans.get(), &response_data);
5720 EXPECT_EQ(OK, rv);
5721 EXPECT_EQ("hello world", response_data);
5722
5723 file_util::Delete(temp_file_path, false);
5724}
5725
[email protected]6624b4622010-03-29 19:58:365726TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5727 // If we try to upload an unreadable file, the network stack should report
5728 // the file size as zero and upload zero bytes for that file.
5729 SessionDependencies session_deps;
5730 scoped_ptr<HttpTransaction> trans(
5731 new HttpNetworkTransaction(CreateSession(&session_deps)));
5732
5733 FilePath temp_file;
5734 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5735 std::string temp_file_content("Unreadable file.");
5736 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5737 temp_file_content.length()));
5738 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5739
5740 HttpRequestInfo request;
5741 request.method = "POST";
5742 request.url = GURL("http://www.google.com/upload");
5743 request.upload_data = new UploadData;
5744 request.load_flags = 0;
5745
5746 std::vector<UploadData::Element> elements;
5747 UploadData::Element element;
5748 element.SetToFilePath(temp_file);
5749 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535750 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365751
5752 MockRead data_reads[] = {
5753 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5754 MockRead(false, OK),
5755 };
5756 MockWrite data_writes[] = {
5757 MockWrite("POST /upload HTTP/1.1\r\n"
5758 "Host: www.google.com\r\n"
5759 "Connection: keep-alive\r\n"
5760 "Content-Length: 0\r\n\r\n"),
5761 MockWrite(false, OK),
5762 };
5763 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5764 arraysize(data_writes));
5765 session_deps.socket_factory.AddSocketDataProvider(&data);
5766
5767 TestCompletionCallback callback;
5768
[email protected]5a1d7ca2010-04-28 20:12:275769 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365770 EXPECT_EQ(ERR_IO_PENDING, rv);
5771
5772 rv = callback.WaitForResult();
5773 EXPECT_EQ(OK, rv);
5774
5775 const HttpResponseInfo* response = trans->GetResponseInfo();
5776 EXPECT_TRUE(response != NULL);
5777 EXPECT_TRUE(response->headers != NULL);
5778 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5779
5780 file_util::Delete(temp_file, false);
5781}
5782
5783TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5784 SessionDependencies session_deps;
5785 scoped_ptr<HttpTransaction> trans(
5786 new HttpNetworkTransaction(CreateSession(&session_deps)));
5787
5788 FilePath temp_file;
5789 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5790 std::string temp_file_contents("Unreadable file.");
5791 std::string unreadable_contents(temp_file_contents.length(), '\0');
5792 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5793 temp_file_contents.length()));
5794
5795 HttpRequestInfo request;
5796 request.method = "POST";
5797 request.url = GURL("http://www.google.com/upload");
5798 request.upload_data = new UploadData;
5799 request.load_flags = 0;
5800
5801 std::vector<UploadData::Element> elements;
5802 UploadData::Element element;
5803 element.SetToFilePath(temp_file);
5804 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535805 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365806
5807 MockRead data_reads[] = {
5808 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5809 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5810 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5811
5812 MockRead("HTTP/1.1 200 OK\r\n"),
5813 MockRead("Content-Length: 0\r\n\r\n"),
5814 MockRead(false, OK),
5815 };
5816 MockWrite data_writes[] = {
5817 MockWrite("POST /upload HTTP/1.1\r\n"
5818 "Host: www.google.com\r\n"
5819 "Connection: keep-alive\r\n"
5820 "Content-Length: 16\r\n\r\n"),
5821 MockWrite(false, temp_file_contents.c_str()),
5822
5823 MockWrite("POST /upload HTTP/1.1\r\n"
5824 "Host: www.google.com\r\n"
5825 "Connection: keep-alive\r\n"
5826 "Content-Length: 16\r\n"
5827 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5828 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5829 MockWrite(false, OK),
5830 };
5831 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5832 arraysize(data_writes));
5833 session_deps.socket_factory.AddSocketDataProvider(&data);
5834
5835 TestCompletionCallback callback1;
5836
[email protected]5a1d7ca2010-04-28 20:12:275837 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365838 EXPECT_EQ(ERR_IO_PENDING, rv);
5839
5840 rv = callback1.WaitForResult();
5841 EXPECT_EQ(OK, rv);
5842
5843 const HttpResponseInfo* response = trans->GetResponseInfo();
5844 EXPECT_TRUE(response != NULL);
5845 EXPECT_TRUE(response->headers != NULL);
5846 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5847
5848 // The password prompt info should have been set in response->auth_challenge.
5849 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5850 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5851 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5852 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5853
5854 // Now make the file unreadable and try again.
5855 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5856
5857 TestCompletionCallback callback2;
5858
[email protected]13c8a092010-07-29 06:15:445859 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365860 EXPECT_EQ(ERR_IO_PENDING, rv);
5861
5862 rv = callback2.WaitForResult();
5863 EXPECT_EQ(OK, rv);
5864
5865 response = trans->GetResponseInfo();
5866 EXPECT_TRUE(response != NULL);
5867 EXPECT_TRUE(response->headers != NULL);
5868 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5869 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5870
5871 file_util::Delete(temp_file, false);
5872}
5873
[email protected]aeefc9e82010-02-19 16:18:275874// Tests that changes to Auth realms are treated like auth rejections.
5875TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5876 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275877
5878 HttpRequestInfo request;
5879 request.method = "GET";
5880 request.url = GURL("http://www.google.com/");
5881 request.load_flags = 0;
5882
5883 // First transaction will request a resource and receive a Basic challenge
5884 // with realm="first_realm".
5885 MockWrite data_writes1[] = {
5886 MockWrite("GET / HTTP/1.1\r\n"
5887 "Host: www.google.com\r\n"
5888 "Connection: keep-alive\r\n"
5889 "\r\n"),
5890 };
5891 MockRead data_reads1[] = {
5892 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5893 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5894 "\r\n"),
5895 };
5896
5897 // After calling trans->RestartWithAuth(), provide an Authentication header
5898 // for first_realm. The server will reject and provide a challenge with
5899 // second_realm.
5900 MockWrite data_writes2[] = {
5901 MockWrite("GET / HTTP/1.1\r\n"
5902 "Host: www.google.com\r\n"
5903 "Connection: keep-alive\r\n"
5904 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5905 "\r\n"),
5906 };
5907 MockRead data_reads2[] = {
5908 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5909 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5910 "\r\n"),
5911 };
5912
5913 // This again fails, and goes back to first_realm. Make sure that the
5914 // entry is removed from cache.
5915 MockWrite data_writes3[] = {
5916 MockWrite("GET / HTTP/1.1\r\n"
5917 "Host: www.google.com\r\n"
5918 "Connection: keep-alive\r\n"
5919 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5920 "\r\n"),
5921 };
5922 MockRead data_reads3[] = {
5923 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5924 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5925 "\r\n"),
5926 };
5927
5928 // Try one last time (with the correct password) and get the resource.
5929 MockWrite data_writes4[] = {
5930 MockWrite("GET / HTTP/1.1\r\n"
5931 "Host: www.google.com\r\n"
5932 "Connection: keep-alive\r\n"
5933 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5934 "\r\n"),
5935 };
5936 MockRead data_reads4[] = {
5937 MockRead("HTTP/1.1 200 OK\r\n"
5938 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:505939 "Content-Length: 5\r\n"
5940 "\r\n"
5941 "hello"),
[email protected]aeefc9e82010-02-19 16:18:275942 };
5943
5944 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5945 data_writes1, arraysize(data_writes1));
5946 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5947 data_writes2, arraysize(data_writes2));
5948 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5949 data_writes3, arraysize(data_writes3));
5950 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5951 data_writes4, arraysize(data_writes4));
5952 session_deps.socket_factory.AddSocketDataProvider(&data1);
5953 session_deps.socket_factory.AddSocketDataProvider(&data2);
5954 session_deps.socket_factory.AddSocketDataProvider(&data3);
5955 session_deps.socket_factory.AddSocketDataProvider(&data4);
5956
5957 TestCompletionCallback callback1;
5958
[email protected]0b0bf032010-09-21 18:08:505959 scoped_ptr<HttpTransaction> trans(
5960 new HttpNetworkTransaction(CreateSession(&session_deps)));
5961
[email protected]aeefc9e82010-02-19 16:18:275962 // Issue the first request with Authorize headers. There should be a
5963 // password prompt for first_realm waiting to be filled in after the
5964 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275965 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275966 EXPECT_EQ(ERR_IO_PENDING, rv);
5967 rv = callback1.WaitForResult();
5968 EXPECT_EQ(OK, rv);
5969 const HttpResponseInfo* response = trans->GetResponseInfo();
5970 ASSERT_FALSE(response == NULL);
5971 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5972 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5973 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5974 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5975
5976 // Issue the second request with an incorrect password. There should be a
5977 // password prompt for second_realm waiting to be filled in after the
5978 // transaction completes.
5979 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445980 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275981 EXPECT_EQ(ERR_IO_PENDING, rv);
5982 rv = callback2.WaitForResult();
5983 EXPECT_EQ(OK, rv);
5984 response = trans->GetResponseInfo();
5985 ASSERT_FALSE(response == NULL);
5986 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5987 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5988 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5989 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5990
5991 // Issue the third request with another incorrect password. There should be
5992 // a password prompt for first_realm waiting to be filled in. If the password
5993 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5994 // first_realm was not correctly removed.
5995 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445996 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275997 EXPECT_EQ(ERR_IO_PENDING, rv);
5998 rv = callback3.WaitForResult();
5999 EXPECT_EQ(OK, rv);
6000 response = trans->GetResponseInfo();
6001 ASSERT_FALSE(response == NULL);
6002 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6003 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6004 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6005 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6006
6007 // Issue the fourth request with the correct password and username.
6008 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446009 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276010 EXPECT_EQ(ERR_IO_PENDING, rv);
6011 rv = callback4.WaitForResult();
6012 EXPECT_EQ(OK, rv);
6013 response = trans->GetResponseInfo();
6014 ASSERT_FALSE(response == NULL);
6015 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6016}
6017
[email protected]564b4912010-03-09 16:30:426018TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386019 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6020 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426021
[email protected]564b4912010-03-09 16:30:426022 SessionDependencies session_deps;
6023
6024 MockRead data_reads[] = {
6025 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356026 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426027 MockRead("hello world"),
6028 MockRead(false, OK),
6029 };
6030
6031 HttpRequestInfo request;
6032 request.method = "GET";
6033 request.url = GURL("http://www.google.com/");
6034 request.load_flags = 0;
6035
6036 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6037
6038 session_deps.socket_factory.AddSocketDataProvider(&data);
6039
6040 TestCompletionCallback callback;
6041
6042 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6043 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6044
[email protected]5a1d7ca2010-04-28 20:12:276045 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426046 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536047
[email protected]2fbaecf22010-07-22 22:20:356048 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426049 const HttpAlternateProtocols& alternate_protocols =
6050 session->alternate_protocols();
6051 EXPECT_FALSE(
6052 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6053
6054 EXPECT_EQ(OK, callback.WaitForResult());
6055
6056 const HttpResponseInfo* response = trans->GetResponseInfo();
6057 ASSERT_TRUE(response != NULL);
6058 ASSERT_TRUE(response->headers != NULL);
6059 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536060 EXPECT_FALSE(response->was_fetched_via_spdy);
6061 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576062 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:426063
6064 std::string response_data;
6065 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6066 EXPECT_EQ("hello world", response_data);
6067
6068 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6069 const HttpAlternateProtocols::PortProtocolPair alternate =
6070 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6071 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6072 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356073 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426074 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426075
[email protected]8e6441ca2010-08-19 05:56:386076 HttpStreamFactory::set_use_alternate_protocols(false);
6077 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426078}
6079
6080TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386081 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426082 SessionDependencies session_deps;
6083
6084 HttpRequestInfo request;
6085 request.method = "GET";
6086 request.url = GURL("http://www.google.com/");
6087 request.load_flags = 0;
6088
6089 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6090 StaticSocketDataProvider first_data;
6091 first_data.set_connect_data(mock_connect);
6092 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6093
6094 MockRead data_reads[] = {
6095 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6096 MockRead("hello world"),
6097 MockRead(true, OK),
6098 };
6099 StaticSocketDataProvider second_data(
6100 data_reads, arraysize(data_reads), NULL, 0);
6101 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6102
6103 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6104 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6105 // http://crbug.com/37454.
6106 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6107
6108 TestCompletionCallback callback;
6109
6110 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6111
[email protected]2fbaecf22010-07-22 22:20:356112 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426113 HttpAlternateProtocols* alternate_protocols =
6114 session->mutable_alternate_protocols();
6115 alternate_protocols->SetAlternateProtocolFor(
6116 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356117 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426118
6119 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6120
[email protected]5a1d7ca2010-04-28 20:12:276121 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426122 EXPECT_EQ(ERR_IO_PENDING, rv);
6123 EXPECT_EQ(OK, callback.WaitForResult());
6124
6125 const HttpResponseInfo* response = trans->GetResponseInfo();
6126 ASSERT_TRUE(response != NULL);
6127 ASSERT_TRUE(response->headers != NULL);
6128 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6129
6130 std::string response_data;
6131 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6132 EXPECT_EQ("hello world", response_data);
6133
6134 ASSERT_TRUE(
6135 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6136 const HttpAlternateProtocols::PortProtocolPair alternate =
6137 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6138 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386139 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426140}
6141
6142// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6143// says that it does SPDY, but it just does the TLS handshake, but the NPN
6144// response does not indicate SPDY, so we just do standard HTTPS over the port.
6145// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6146// on the original port.
[email protected]a2cb8122010-03-10 17:22:426147// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6148// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536149//
[email protected]a2cb8122010-03-10 17:22:426150// HttpRequestInfo request;
6151// request.method = "GET";
6152// request.url = GURL("http://www.google.com/");
6153// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536154//
[email protected]a2cb8122010-03-10 17:22:426155// MockRead data_reads[] = {
6156// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6157// MockRead("hello world"),
6158// MockRead(true, OK),
6159// };
6160// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6161// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536162//
[email protected]a2cb8122010-03-10 17:22:426163// SSLSocketDataProvider ssl(true, OK);
6164// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536165//
[email protected]a2cb8122010-03-10 17:22:426166// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536167//
[email protected]a2cb8122010-03-10 17:22:426168// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536169//
[email protected]a2cb8122010-03-10 17:22:426170// HostPortPair http_host_port_pair;
6171// http_host_port_pair.host = "www.google.com";
6172// http_host_port_pair.port = 80;
6173// HttpAlternateProtocols* alternate_protocols =
6174// session->mutable_alternate_protocols();
6175// alternate_protocols->SetAlternateProtocolFor(
6176// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066177// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536178//
[email protected]a2cb8122010-03-10 17:22:426179// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536180//
[email protected]5a1d7ca2010-04-28 20:12:276181// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426182// EXPECT_EQ(ERR_IO_PENDING, rv);
6183// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536184//
[email protected]a2cb8122010-03-10 17:22:426185// const HttpResponseInfo* response = trans->GetResponseInfo();
6186// ASSERT_TRUE(response != NULL);
6187// ASSERT_TRUE(response->headers != NULL);
6188// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536189//
[email protected]a2cb8122010-03-10 17:22:426190// std::string response_data;
6191// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6192// EXPECT_EQ("hello world", response_data);
6193// }
6194
6195TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386196 HttpStreamFactory::set_use_alternate_protocols(true);
6197 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426198 SessionDependencies session_deps;
6199
6200 HttpRequestInfo request;
6201 request.method = "GET";
6202 request.url = GURL("http://www.google.com/");
6203 request.load_flags = 0;
6204
[email protected]a2cb8122010-03-10 17:22:426205 StaticSocketDataProvider first_tcp_connect;
6206 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6207
6208 SSLSocketDataProvider ssl(true, OK);
6209 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6210
[email protected]564b4912010-03-09 16:30:426211 MockRead data_reads[] = {
6212 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6213 MockRead("hello world"),
6214 MockRead(true, OK),
6215 };
[email protected]a2cb8122010-03-10 17:22:426216 StaticSocketDataProvider fallback_data(
6217 data_reads, arraysize(data_reads), NULL, 0);
6218 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426219
6220 TestCompletionCallback callback;
6221
6222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6223
[email protected]2fbaecf22010-07-22 22:20:356224 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426225 HttpAlternateProtocols* alternate_protocols =
6226 session->mutable_alternate_protocols();
6227 alternate_protocols->SetAlternateProtocolFor(
6228 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356229 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426230
6231 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6232
[email protected]5a1d7ca2010-04-28 20:12:276233 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426234 EXPECT_EQ(ERR_IO_PENDING, rv);
6235 EXPECT_EQ(OK, callback.WaitForResult());
6236
6237 const HttpResponseInfo* response = trans->GetResponseInfo();
6238 ASSERT_TRUE(response != NULL);
6239 ASSERT_TRUE(response->headers != NULL);
6240 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6241
6242 std::string response_data;
6243 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6244 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386245 HttpStreamFactory::set_next_protos("");
6246 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546247}
6248
6249TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386250 HttpStreamFactory::set_use_alternate_protocols(true);
6251 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546252 SessionDependencies session_deps;
6253
6254 HttpRequestInfo request;
6255 request.method = "GET";
6256 request.url = GURL("http://www.google.com/");
6257 request.load_flags = 0;
6258
6259 MockRead data_reads[] = {
6260 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356261 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546262 MockRead("hello world"),
6263 MockRead(true, OK),
6264 };
6265
6266 StaticSocketDataProvider first_transaction(
6267 data_reads, arraysize(data_reads), NULL, 0);
6268 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6269
6270 SSLSocketDataProvider ssl(true, OK);
6271 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356272 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536273 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546274 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6275
[email protected]2bd93022010-07-17 00:58:446276 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136277 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546278
[email protected]2bd93022010-07-17 00:58:446279 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6280 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546281 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136282 CreateMockRead(*resp),
6283 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546284 MockRead(true, 0, 0),
6285 };
6286
6287 scoped_refptr<DelayedSocketData> spdy_data(
6288 new DelayedSocketData(
6289 1, // wait for one write to finish before reading.
6290 spdy_reads, arraysize(spdy_reads),
6291 spdy_writes, arraysize(spdy_writes)));
6292 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6293
6294 TestCompletionCallback callback;
6295
6296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6297 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6298
[email protected]5a1d7ca2010-04-28 20:12:276299 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546300 EXPECT_EQ(ERR_IO_PENDING, rv);
6301 EXPECT_EQ(OK, callback.WaitForResult());
6302
6303 const HttpResponseInfo* response = trans->GetResponseInfo();
6304 ASSERT_TRUE(response != NULL);
6305 ASSERT_TRUE(response->headers != NULL);
6306 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6307
6308 std::string response_data;
6309 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6310 EXPECT_EQ("hello world", response_data);
6311
6312 trans.reset(new HttpNetworkTransaction(session));
6313
[email protected]5a1d7ca2010-04-28 20:12:276314 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546315 EXPECT_EQ(ERR_IO_PENDING, rv);
6316 EXPECT_EQ(OK, callback.WaitForResult());
6317
6318 response = trans->GetResponseInfo();
6319 ASSERT_TRUE(response != NULL);
6320 ASSERT_TRUE(response->headers != NULL);
6321 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536322 EXPECT_TRUE(response->was_fetched_via_spdy);
6323 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576324 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546325
6326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6327 EXPECT_EQ("hello!", response_data);
6328
[email protected]8e6441ca2010-08-19 05:56:386329 HttpStreamFactory::set_next_protos("");
6330 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546331}
6332
[email protected]631f1322010-04-30 17:59:116333class CapturingProxyResolver : public ProxyResolver {
6334 public:
6335 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6336 virtual ~CapturingProxyResolver() {}
6337
6338 virtual int GetProxyForURL(const GURL& url,
6339 ProxyInfo* results,
6340 CompletionCallback* callback,
6341 RequestHandle* request,
6342 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406343 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6344 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426345 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116346 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426347 return OK;
[email protected]631f1322010-04-30 17:59:116348 }
6349
6350 virtual void CancelRequest(RequestHandle request) {
6351 NOTREACHED();
6352 }
6353
[email protected]24476402010-07-20 20:55:176354 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116355 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426356 return OK;
[email protected]631f1322010-04-30 17:59:116357 }
6358
[email protected]24476402010-07-20 20:55:176359 const std::vector<GURL>& resolved() const { return resolved_; }
6360
6361 private:
[email protected]631f1322010-04-30 17:59:116362 std::vector<GURL> resolved_;
6363
6364 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6365};
6366
[email protected]631f1322010-04-30 17:59:116367TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386368 HttpStreamFactory::set_use_alternate_protocols(true);
6369 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116370
6371 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426372 proxy_config.set_auto_detect(true);
6373 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116374
[email protected]631f1322010-04-30 17:59:116375 CapturingProxyResolver* capturing_proxy_resolver =
6376 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386377 SessionDependencies session_deps(new ProxyService(
6378 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6379 NULL));
[email protected]631f1322010-04-30 17:59:116380
6381 HttpRequestInfo request;
6382 request.method = "GET";
6383 request.url = GURL("http://www.google.com/");
6384 request.load_flags = 0;
6385
6386 MockRead data_reads[] = {
6387 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356388 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116389 MockRead("hello world"),
6390 MockRead(true, OK),
6391 };
6392
6393 StaticSocketDataProvider first_transaction(
6394 data_reads, arraysize(data_reads), NULL, 0);
6395 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6396
6397 SSLSocketDataProvider ssl(true, OK);
6398 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356399 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536400 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116401 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6402
[email protected]2bd93022010-07-17 00:58:446403 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116404 MockWrite spdy_writes[] = {
6405 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6406 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426407 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136408 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116409 };
6410
[email protected]d911f1b2010-05-05 22:39:426411 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6412
[email protected]2bd93022010-07-17 00:58:446413 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6414 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116415 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426416 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136417 CreateMockRead(*resp.get(), 4), // 2, 4
6418 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426419 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116420 };
6421
[email protected]d911f1b2010-05-05 22:39:426422 scoped_refptr<OrderedSocketData> spdy_data(
6423 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116424 spdy_reads, arraysize(spdy_reads),
6425 spdy_writes, arraysize(spdy_writes)));
6426 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6427
6428 TestCompletionCallback callback;
6429
6430 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6431 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6432
6433 int rv = trans->Start(&request, &callback, BoundNetLog());
6434 EXPECT_EQ(ERR_IO_PENDING, rv);
6435 EXPECT_EQ(OK, callback.WaitForResult());
6436
6437 const HttpResponseInfo* response = trans->GetResponseInfo();
6438 ASSERT_TRUE(response != NULL);
6439 ASSERT_TRUE(response->headers != NULL);
6440 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536441 EXPECT_FALSE(response->was_fetched_via_spdy);
6442 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116443
6444 std::string response_data;
6445 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6446 EXPECT_EQ("hello world", response_data);
6447
6448 trans.reset(new HttpNetworkTransaction(session));
6449
6450 rv = trans->Start(&request, &callback, BoundNetLog());
6451 EXPECT_EQ(ERR_IO_PENDING, rv);
6452 EXPECT_EQ(OK, callback.WaitForResult());
6453
6454 response = trans->GetResponseInfo();
6455 ASSERT_TRUE(response != NULL);
6456 ASSERT_TRUE(response->headers != NULL);
6457 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536458 EXPECT_TRUE(response->was_fetched_via_spdy);
6459 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116460
6461 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6462 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426463 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6464 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116465 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426466 EXPECT_EQ("https://www.google.com/",
6467 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116468
[email protected]8e6441ca2010-08-19 05:56:386469 HttpStreamFactory::set_next_protos("");
6470 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116471}
[email protected]631f1322010-04-30 17:59:116472
[email protected]2ff8b312010-04-26 22:20:546473TEST_F(HttpNetworkTransactionTest,
6474 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386475 HttpStreamFactory::set_use_alternate_protocols(true);
6476 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546477 SessionDependencies session_deps;
6478
6479 HttpRequestInfo request;
6480 request.method = "GET";
6481 request.url = GURL("http://www.google.com/");
6482 request.load_flags = 0;
6483
6484 MockRead data_reads[] = {
6485 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356486 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546487 MockRead("hello world"),
6488 MockRead(true, OK),
6489 };
6490
6491 StaticSocketDataProvider first_transaction(
6492 data_reads, arraysize(data_reads), NULL, 0);
6493 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6494
6495 SSLSocketDataProvider ssl(true, OK);
6496 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356497 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536498 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546499 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536500 // Make sure we use ssl for spdy here.
6501 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546502
[email protected]2bd93022010-07-17 00:58:446503 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136504 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546505
[email protected]2bd93022010-07-17 00:58:446506 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6507 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546508 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136509 CreateMockRead(*resp),
6510 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546511 MockRead(true, 0, 0),
6512 };
6513
6514 scoped_refptr<DelayedSocketData> spdy_data(
6515 new DelayedSocketData(
6516 1, // wait for one write to finish before reading.
6517 spdy_reads, arraysize(spdy_reads),
6518 spdy_writes, arraysize(spdy_writes)));
6519 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6520
6521 TestCompletionCallback callback;
6522
6523 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6524
6525 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6526
[email protected]5a1d7ca2010-04-28 20:12:276527 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546528 EXPECT_EQ(ERR_IO_PENDING, rv);
6529 EXPECT_EQ(OK, callback.WaitForResult());
6530
6531 const HttpResponseInfo* response = trans->GetResponseInfo();
6532 ASSERT_TRUE(response != NULL);
6533 ASSERT_TRUE(response->headers != NULL);
6534 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6535
6536 std::string response_data;
6537 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6538 EXPECT_EQ("hello world", response_data);
6539
6540 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386541 HostPortPair host_port_pair("www.google.com", 443);
6542 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546543 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276544 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6545 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276546 scoped_refptr<TCPSocketParams> tcp_params(
6547 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386548
6549 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6550 EXPECT_EQ(ERR_IO_PENDING,
6551 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6552 &callback, session->tcp_socket_pool(),
6553 BoundNetLog()));
6554 EXPECT_EQ(OK, callback.WaitForResult());
6555
6556 SSLConfig ssl_config;
6557 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6558 ClientSocket* socket = connection->release_socket();
[email protected]7ab5bbd12010-10-19 13:33:216559 socket = session->socket_factory()->CreateSSLClientSocket(
6560 socket, "" , ssl_config, NULL /* ssl_host_info */);
[email protected]02b0c342010-09-25 21:09:386561 connection->set_socket(socket);
6562 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6563 EXPECT_EQ(OK, callback.WaitForResult());
6564
6565 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6566 true, OK));
6567
[email protected]2ff8b312010-04-26 22:20:546568 trans.reset(new HttpNetworkTransaction(session));
6569
[email protected]5a1d7ca2010-04-28 20:12:276570 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546571 EXPECT_EQ(ERR_IO_PENDING, rv);
6572 EXPECT_EQ(OK, callback.WaitForResult());
6573
6574 response = trans->GetResponseInfo();
6575 ASSERT_TRUE(response != NULL);
6576 ASSERT_TRUE(response->headers != NULL);
6577 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536578 EXPECT_TRUE(response->was_fetched_via_spdy);
6579 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576580 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546581
6582 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6583 EXPECT_EQ("hello!", response_data);
6584
[email protected]8e6441ca2010-08-19 05:56:386585 HttpStreamFactory::set_next_protos("");
6586 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426587}
6588
[email protected]044de0642010-06-17 10:42:156589// GenerateAuthToken is a mighty big test.
6590// It tests all permutation of GenerateAuthToken behavior:
6591// - Synchronous and Asynchronous completion.
6592// - OK or error on completion.
6593// - Direct connection, non-authenticating proxy, and authenticating proxy.
6594// - HTTP or HTTPS backend (to include proxy tunneling).
6595// - Non-authenticating and authenticating backend.
6596//
6597// In all, there are 44 reasonable permuations (for example, if there are
6598// problems generating an auth token for an authenticating proxy, we don't
6599// need to test all permutations of the backend server).
6600//
6601// The test proceeds by going over each of the configuration cases, and
6602// potentially running up to three rounds in each of the tests. The TestConfig
6603// specifies both the configuration for the test as well as the expectations
6604// for the results.
6605TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506606 static const char kServer[] = "http://www.example.com";
6607 static const char kSecureServer[] = "https://www.example.com";
6608 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156609 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6610
6611 enum AuthTiming {
6612 AUTH_NONE,
6613 AUTH_SYNC,
6614 AUTH_ASYNC,
6615 };
6616
6617 const MockWrite kGet(
6618 "GET / HTTP/1.1\r\n"
6619 "Host: www.example.com\r\n"
6620 "Connection: keep-alive\r\n\r\n");
6621 const MockWrite kGetProxy(
6622 "GET http://www.example.com/ HTTP/1.1\r\n"
6623 "Host: www.example.com\r\n"
6624 "Proxy-Connection: keep-alive\r\n\r\n");
6625 const MockWrite kGetAuth(
6626 "GET / HTTP/1.1\r\n"
6627 "Host: www.example.com\r\n"
6628 "Connection: keep-alive\r\n"
6629 "Authorization: auth_token\r\n\r\n");
6630 const MockWrite kGetProxyAuth(
6631 "GET http://www.example.com/ HTTP/1.1\r\n"
6632 "Host: www.example.com\r\n"
6633 "Proxy-Connection: keep-alive\r\n"
6634 "Proxy-Authorization: auth_token\r\n\r\n");
6635 const MockWrite kGetAuthThroughProxy(
6636 "GET http://www.example.com/ HTTP/1.1\r\n"
6637 "Host: www.example.com\r\n"
6638 "Proxy-Connection: keep-alive\r\n"
6639 "Authorization: auth_token\r\n\r\n");
6640 const MockWrite kGetAuthWithProxyAuth(
6641 "GET http://www.example.com/ HTTP/1.1\r\n"
6642 "Host: www.example.com\r\n"
6643 "Proxy-Connection: keep-alive\r\n"
6644 "Proxy-Authorization: auth_token\r\n"
6645 "Authorization: auth_token\r\n\r\n");
6646 const MockWrite kConnect(
6647 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6648 "Host: www.example.com\r\n"
6649 "Proxy-Connection: keep-alive\r\n\r\n");
6650 const MockWrite kConnectProxyAuth(
6651 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6652 "Host: www.example.com\r\n"
6653 "Proxy-Connection: keep-alive\r\n"
6654 "Proxy-Authorization: auth_token\r\n\r\n");
6655
6656 const MockRead kSuccess(
6657 "HTTP/1.1 200 OK\r\n"
6658 "Content-Type: text/html; charset=iso-8859-1\r\n"
6659 "Content-Length: 3\r\n\r\n"
6660 "Yes");
6661 const MockRead kFailure(
6662 "Should not be called.");
6663 const MockRead kServerChallenge(
6664 "HTTP/1.1 401 Unauthorized\r\n"
6665 "WWW-Authenticate: Mock realm=server\r\n"
6666 "Content-Type: text/html; charset=iso-8859-1\r\n"
6667 "Content-Length: 14\r\n\r\n"
6668 "Unauthorized\r\n");
6669 const MockRead kProxyChallenge(
6670 "HTTP/1.1 407 Unauthorized\r\n"
6671 "Proxy-Authenticate: Mock realm=proxy\r\n"
6672 "Proxy-Connection: close\r\n"
6673 "Content-Type: text/html; charset=iso-8859-1\r\n"
6674 "Content-Length: 14\r\n\r\n"
6675 "Unauthorized\r\n");
6676 const MockRead kProxyConnected(
6677 "HTTP/1.1 200 Connection Established\r\n\r\n");
6678
6679 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6680 // no constructors, but the C++ compiler on Windows warns about
6681 // unspecified data in compound literals. So, moved to using constructors,
6682 // and TestRound's created with the default constructor should not be used.
6683 struct TestRound {
6684 TestRound()
6685 : expected_rv(ERR_UNEXPECTED),
6686 extra_write(NULL),
6687 extra_read(NULL) {
6688 }
6689 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6690 int expected_rv_arg)
6691 : write(write_arg),
6692 read(read_arg),
6693 expected_rv(expected_rv_arg),
6694 extra_write(NULL),
6695 extra_read(NULL) {
6696 }
6697 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6698 int expected_rv_arg, const MockWrite* extra_write_arg,
6699 const MockWrite* extra_read_arg)
6700 : write(write_arg),
6701 read(read_arg),
6702 expected_rv(expected_rv_arg),
6703 extra_write(extra_write_arg),
6704 extra_read(extra_read_arg) {
6705 }
6706 MockWrite write;
6707 MockRead read;
6708 int expected_rv;
6709 const MockWrite* extra_write;
6710 const MockRead* extra_read;
6711 };
6712
6713 static const int kNoSSL = 500;
6714
6715 struct TestConfig {
6716 const char* proxy_url;
6717 AuthTiming proxy_auth_timing;
6718 int proxy_auth_rv;
6719 const char* server_url;
6720 AuthTiming server_auth_timing;
6721 int server_auth_rv;
6722 int num_auth_rounds;
6723 int first_ssl_round;
6724 TestRound rounds[3];
6725 } test_configs[] = {
6726 // Non-authenticating HTTP server with a direct connection.
6727 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6728 { TestRound(kGet, kSuccess, OK)}},
6729 // Authenticating HTTP server with a direct connection.
6730 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6731 { TestRound(kGet, kServerChallenge, OK),
6732 TestRound(kGetAuth, kSuccess, OK)}},
6733 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6734 { TestRound(kGet, kServerChallenge, OK),
6735 TestRound(kGetAuth, kFailure, kAuthErr)}},
6736 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6737 { TestRound(kGet, kServerChallenge, OK),
6738 TestRound(kGetAuth, kSuccess, OK)}},
6739 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6740 { TestRound(kGet, kServerChallenge, OK),
6741 TestRound(kGetAuth, kFailure, kAuthErr)}},
6742 // Non-authenticating HTTP server through a non-authenticating proxy.
6743 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6744 { TestRound(kGetProxy, kSuccess, OK)}},
6745 // Authenticating HTTP server through a non-authenticating proxy.
6746 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6747 { TestRound(kGetProxy, kServerChallenge, OK),
6748 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6749 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6750 { TestRound(kGetProxy, kServerChallenge, OK),
6751 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6752 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6753 { TestRound(kGetProxy, kServerChallenge, OK),
6754 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6755 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6756 { TestRound(kGetProxy, kServerChallenge, OK),
6757 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6758 // Non-authenticating HTTP server through an authenticating proxy.
6759 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6760 { TestRound(kGetProxy, kProxyChallenge, OK),
6761 TestRound(kGetProxyAuth, kSuccess, OK)}},
6762 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6763 { TestRound(kGetProxy, kProxyChallenge, OK),
6764 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6765 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6766 { TestRound(kGetProxy, kProxyChallenge, OK),
6767 TestRound(kGetProxyAuth, kSuccess, OK)}},
6768 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6769 { TestRound(kGetProxy, kProxyChallenge, OK),
6770 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6771 // Authenticating HTTP server through an authenticating proxy.
6772 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6773 { TestRound(kGetProxy, kProxyChallenge, OK),
6774 TestRound(kGetProxyAuth, kServerChallenge, OK),
6775 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6776 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6777 { TestRound(kGetProxy, kProxyChallenge, OK),
6778 TestRound(kGetProxyAuth, kServerChallenge, OK),
6779 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6780 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6781 { TestRound(kGetProxy, kProxyChallenge, OK),
6782 TestRound(kGetProxyAuth, kServerChallenge, OK),
6783 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6784 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6785 { TestRound(kGetProxy, kProxyChallenge, OK),
6786 TestRound(kGetProxyAuth, kServerChallenge, OK),
6787 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6788 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6789 { TestRound(kGetProxy, kProxyChallenge, OK),
6790 TestRound(kGetProxyAuth, kServerChallenge, OK),
6791 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6792 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6793 { TestRound(kGetProxy, kProxyChallenge, OK),
6794 TestRound(kGetProxyAuth, kServerChallenge, OK),
6795 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6796 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6797 { TestRound(kGetProxy, kProxyChallenge, OK),
6798 TestRound(kGetProxyAuth, kServerChallenge, OK),
6799 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6800 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6801 { TestRound(kGetProxy, kProxyChallenge, OK),
6802 TestRound(kGetProxyAuth, kServerChallenge, OK),
6803 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6804 // Non-authenticating HTTPS server with a direct connection.
6805 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6806 { TestRound(kGet, kSuccess, OK)}},
6807 // Authenticating HTTPS server with a direct connection.
6808 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6809 { TestRound(kGet, kServerChallenge, OK),
6810 TestRound(kGetAuth, kSuccess, OK)}},
6811 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6812 { TestRound(kGet, kServerChallenge, OK),
6813 TestRound(kGetAuth, kFailure, kAuthErr)}},
6814 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6815 { TestRound(kGet, kServerChallenge, OK),
6816 TestRound(kGetAuth, kSuccess, OK)}},
6817 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6818 { TestRound(kGet, kServerChallenge, OK),
6819 TestRound(kGetAuth, kFailure, kAuthErr)}},
6820 // Non-authenticating HTTPS server with a non-authenticating proxy.
6821 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6822 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6823 // Authenticating HTTPS server through a non-authenticating proxy.
6824 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6825 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6826 TestRound(kGetAuth, kSuccess, OK)}},
6827 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6828 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6829 TestRound(kGetAuth, kFailure, kAuthErr)}},
6830 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6831 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6832 TestRound(kGetAuth, kSuccess, OK)}},
6833 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6834 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6835 TestRound(kGetAuth, kFailure, kAuthErr)}},
6836 // Non-Authenticating HTTPS server through an authenticating proxy.
6837 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6838 { TestRound(kConnect, kProxyChallenge, OK),
6839 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6840 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6841 { TestRound(kConnect, kProxyChallenge, OK),
6842 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6843 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6844 { TestRound(kConnect, kProxyChallenge, OK),
6845 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6846 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6847 { TestRound(kConnect, kProxyChallenge, OK),
6848 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6849 // Authenticating HTTPS server through an authenticating proxy.
6850 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6851 { TestRound(kConnect, kProxyChallenge, OK),
6852 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6853 &kGet, &kServerChallenge),
6854 TestRound(kGetAuth, kSuccess, OK)}},
6855 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6856 { TestRound(kConnect, kProxyChallenge, OK),
6857 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6858 &kGet, &kServerChallenge),
6859 TestRound(kGetAuth, kFailure, kAuthErr)}},
6860 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6861 { TestRound(kConnect, kProxyChallenge, OK),
6862 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6863 &kGet, &kServerChallenge),
6864 TestRound(kGetAuth, kSuccess, OK)}},
6865 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6866 { TestRound(kConnect, kProxyChallenge, OK),
6867 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6868 &kGet, &kServerChallenge),
6869 TestRound(kGetAuth, kFailure, kAuthErr)}},
6870 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6871 { TestRound(kConnect, kProxyChallenge, OK),
6872 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6873 &kGet, &kServerChallenge),
6874 TestRound(kGetAuth, kSuccess, OK)}},
6875 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6876 { TestRound(kConnect, kProxyChallenge, OK),
6877 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6878 &kGet, &kServerChallenge),
6879 TestRound(kGetAuth, kFailure, kAuthErr)}},
6880 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6881 { TestRound(kConnect, kProxyChallenge, OK),
6882 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6883 &kGet, &kServerChallenge),
6884 TestRound(kGetAuth, kSuccess, OK)}},
6885 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6886 { TestRound(kConnect, kProxyChallenge, OK),
6887 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6888 &kGet, &kServerChallenge),
6889 TestRound(kGetAuth, kFailure, kAuthErr)}},
6890 };
6891
6892 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:006893 HttpAuthHandlerMock::Factory* auth_factory(
6894 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156895 session_deps.http_auth_handler_factory.reset(auth_factory);
6896
6897 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6898 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266899
6900 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156901 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006902 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156903 std::string auth_challenge = "Mock realm=proxy";
6904 GURL origin(test_config.proxy_url);
6905 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6906 auth_challenge.end());
6907 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6908 origin, BoundNetLog());
6909 auth_handler->SetGenerateExpectation(
6910 test_config.proxy_auth_timing == AUTH_ASYNC,
6911 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156912 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6913 }
6914 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006915 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156916 std::string auth_challenge = "Mock realm=server";
6917 GURL origin(test_config.server_url);
6918 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6919 auth_challenge.end());
6920 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6921 origin, BoundNetLog());
6922 auth_handler->SetGenerateExpectation(
6923 test_config.server_auth_timing == AUTH_ASYNC,
6924 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156925 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6926 }
6927 if (test_config.proxy_url) {
6928 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:006929 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:156930 } else {
[email protected]ebeefff32010-09-15 05:10:026931 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:156932 }
6933
6934 HttpRequestInfo request;
6935 request.method = "GET";
6936 request.url = GURL(test_config.server_url);
6937 request.load_flags = 0;
6938
[email protected]0b0bf032010-09-21 18:08:506939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6940 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:156941
6942 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6943 const TestRound& read_write_round = test_config.rounds[round];
6944
6945 // Set up expected reads and writes.
6946 MockRead reads[2];
6947 reads[0] = read_write_round.read;
6948 size_t length_reads = 1;
6949 if (read_write_round.extra_read) {
6950 reads[1] = *read_write_round.extra_read;
6951 length_reads = 2;
6952 }
6953
6954 MockWrite writes[2];
6955 writes[0] = read_write_round.write;
6956 size_t length_writes = 1;
6957 if (read_write_round.extra_write) {
6958 writes[1] = *read_write_round.extra_write;
6959 length_writes = 2;
6960 }
6961 StaticSocketDataProvider data_provider(
6962 reads, length_reads, writes, length_writes);
6963 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6964
6965 // Add an SSL sequence if necessary.
6966 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6967 if (round >= test_config.first_ssl_round)
6968 session_deps.socket_factory.AddSSLSocketDataProvider(
6969 &ssl_socket_data_provider);
6970
6971 // Start or restart the transaction.
6972 TestCompletionCallback callback;
6973 int rv;
6974 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:506975 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:156976 } else {
[email protected]0b0bf032010-09-21 18:08:506977 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156978 }
6979 if (rv == ERR_IO_PENDING)
6980 rv = callback.WaitForResult();
6981
6982 // Compare results with expected data.
6983 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:506984 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:156985 if (read_write_round.expected_rv == OK) {
6986 EXPECT_FALSE(response == NULL);
6987 } else {
6988 EXPECT_TRUE(response == NULL);
6989 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6990 continue;
6991 }
6992 if (round + 1 < test_config.num_auth_rounds) {
6993 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6994 } else {
6995 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6996 }
6997 }
[email protected]e5ae96a2010-04-14 20:12:456998 }
6999}
7000
[email protected]c871bce92010-07-15 21:51:147001TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7002 // Do multi-round authentication and make sure it works correctly.
7003 SessionDependencies session_deps;
7004 HttpAuthHandlerMock::Factory* auth_factory(
7005 new HttpAuthHandlerMock::Factory());
7006 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:027007 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:147008 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7009 session_deps.host_resolver->set_synchronous_mode(true);
7010
7011 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7012 auth_handler->set_connection_based(true);
7013 std::string auth_challenge = "Mock realm=server";
7014 GURL origin("http://www.example.com");
7015 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7016 auth_challenge.end());
7017 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7018 origin, BoundNetLog());
7019 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7020
[email protected]ad8e04a2010-11-01 04:16:277021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c871bce92010-07-15 21:51:147022 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7023
7024 int rv = OK;
7025 const HttpResponseInfo* response = NULL;
7026 HttpRequestInfo request;
7027 request.method = "GET";
7028 request.url = origin;
7029 request.load_flags = 0;
7030 TestCompletionCallback callback;
7031
7032 const MockWrite kGet(
7033 "GET / HTTP/1.1\r\n"
7034 "Host: www.example.com\r\n"
7035 "Connection: keep-alive\r\n\r\n");
7036 const MockWrite kGetAuth(
7037 "GET / HTTP/1.1\r\n"
7038 "Host: www.example.com\r\n"
7039 "Connection: keep-alive\r\n"
7040 "Authorization: auth_token\r\n\r\n");
7041
7042 const MockRead kServerChallenge(
7043 "HTTP/1.1 401 Unauthorized\r\n"
7044 "WWW-Authenticate: Mock realm=server\r\n"
7045 "Content-Type: text/html; charset=iso-8859-1\r\n"
7046 "Content-Length: 14\r\n\r\n"
7047 "Unauthorized\r\n");
7048 const MockRead kSuccess(
7049 "HTTP/1.1 200 OK\r\n"
7050 "Content-Type: text/html; charset=iso-8859-1\r\n"
7051 "Content-Length: 3\r\n\r\n"
7052 "Yes");
7053
7054 MockWrite writes[] = {
7055 // First round
7056 kGet,
7057 // Second round
7058 kGetAuth,
7059 // Third round
7060 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307061 // Fourth round
7062 kGetAuth
[email protected]c871bce92010-07-15 21:51:147063 };
7064 MockRead reads[] = {
7065 // First round
7066 kServerChallenge,
7067 // Second round
7068 kServerChallenge,
7069 // Third round
[email protected]eca50e122010-09-11 14:03:307070 kServerChallenge,
7071 // Fourth round
[email protected]c871bce92010-07-15 21:51:147072 kSuccess,
7073 };
7074 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7075 writes, arraysize(writes));
7076 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7077
7078 // First round
7079 auth_handler->SetGenerateExpectation(false, OK);
7080 rv = trans->Start(&request, &callback, BoundNetLog());
7081 if (rv == ERR_IO_PENDING)
7082 rv = callback.WaitForResult();
7083 EXPECT_EQ(OK, rv);
7084 response = trans->GetResponseInfo();
7085 ASSERT_FALSE(response == NULL);
7086 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7087
7088 // Second round
7089 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447090 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147091 if (rv == ERR_IO_PENDING)
7092 rv = callback.WaitForResult();
7093 EXPECT_EQ(OK, rv);
7094 response = trans->GetResponseInfo();
7095 ASSERT_FALSE(response == NULL);
7096 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7097
7098 // Third round
7099 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447100 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147101 if (rv == ERR_IO_PENDING)
7102 rv = callback.WaitForResult();
7103 EXPECT_EQ(OK, rv);
7104 response = trans->GetResponseInfo();
7105 ASSERT_FALSE(response == NULL);
7106 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:307107
7108 // Fourth round
7109 auth_handler->SetGenerateExpectation(false, OK);
7110 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7111 if (rv == ERR_IO_PENDING)
7112 rv = callback.WaitForResult();
7113 EXPECT_EQ(OK, rv);
7114 response = trans->GetResponseInfo();
7115 ASSERT_FALSE(response == NULL);
7116 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:147117}
7118
[email protected]aeaca1f2010-04-20 22:05:217119class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7120 public:
[email protected]06650c52010-06-03 00:49:177121 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217122 : fail_all_(fail_all) {
7123 }
7124
7125 virtual MockRead GetNextRead() {
7126 if (fail_all_)
7127 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7128
7129 return MockRead(false /* async */,
7130 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7131 }
7132
7133 virtual MockWriteResult OnWrite(const std::string& data) {
7134 return MockWriteResult(false /* async */, data.size());
7135 }
7136
7137 void Reset() {
7138 }
7139
7140 private:
7141 const bool fail_all_;
7142};
7143
7144// Test that we restart a connection when we see a decompression failure from
7145// the peer during the handshake. (In the real world we'll restart with SSLv3
7146// and we won't offer DEFLATE in that case.)
7147TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7148 HttpRequestInfo request;
7149 request.method = "GET";
7150 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7151 request.load_flags = 0;
7152
7153 SessionDependencies session_deps;
7154 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7155 false /* fail all reads */);
7156 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7157 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117158 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217159 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7160 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7161 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7162 session_deps.socket_factory.AddSSLSocketDataProvider(
7163 &ssl_socket_data_provider1);
7164 session_deps.socket_factory.AddSSLSocketDataProvider(
7165 &ssl_socket_data_provider2);
7166
[email protected]e60e47a2010-07-14 03:37:187167 // Work around http://crbug.com/37454
7168 StaticSocketDataProvider bug37454_connection;
7169 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7170 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7171
[email protected]aeaca1f2010-04-20 22:05:217172 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7173 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7174 TestCompletionCallback callback;
7175
[email protected]5a1d7ca2010-04-28 20:12:277176 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217177 EXPECT_EQ(ERR_IO_PENDING, rv);
7178 EXPECT_EQ(OK, callback.WaitForResult());
7179
7180 const HttpResponseInfo* response = trans->GetResponseInfo();
7181 ASSERT_TRUE(response != NULL);
7182 ASSERT_TRUE(response->headers != NULL);
7183 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7184
7185 std::string response_data;
7186 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7187 EXPECT_EQ("ok.", response_data);
7188}
7189
7190// Test that we restart a connection if we get a decompression failure from the
7191// peer while reading the first bytes from the connection. This occurs when the
7192// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7193// in the handshake.
7194TEST_F(HttpNetworkTransactionTest,
7195 RestartAfterTLSDecompressionFailureWithFalseStart) {
7196 HttpRequestInfo request;
7197 request.method = "GET";
7198 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7199 request.load_flags = 0;
7200
7201 SessionDependencies session_deps;
7202 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7203 true /* fail all reads */);
7204 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7205 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7206 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7207 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7208 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7209 session_deps.socket_factory.AddSSLSocketDataProvider(
7210 &ssl_socket_data_provider1);
7211 session_deps.socket_factory.AddSSLSocketDataProvider(
7212 &ssl_socket_data_provider2);
7213
7214 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7215 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7216 TestCompletionCallback callback;
7217
[email protected]5a1d7ca2010-04-28 20:12:277218 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217219 EXPECT_EQ(ERR_IO_PENDING, rv);
7220 EXPECT_EQ(OK, callback.WaitForResult());
7221
7222 const HttpResponseInfo* response = trans->GetResponseInfo();
7223 ASSERT_TRUE(response != NULL);
7224 ASSERT_TRUE(response->headers != NULL);
7225 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7226
7227 std::string response_data;
7228 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7229 EXPECT_EQ("ok.", response_data);
7230}
7231
[email protected]65041fa2010-05-21 06:56:537232// This tests the case that a request is issued via http instead of spdy after
7233// npn is negotiated.
7234TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387235 HttpStreamFactory::set_use_alternate_protocols(true);
7236 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537237 SessionDependencies session_deps;
7238 HttpRequestInfo request;
7239 request.method = "GET";
7240 request.url = GURL("https://www.google.com/");
7241 request.load_flags = 0;
7242
7243 MockWrite data_writes[] = {
7244 MockWrite("GET / HTTP/1.1\r\n"
7245 "Host: www.google.com\r\n"
7246 "Connection: keep-alive\r\n\r\n"),
7247 };
7248
7249 MockRead data_reads[] = {
7250 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357251 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537252 MockRead("hello world"),
7253 MockRead(false, OK),
7254 };
7255
7256 SSLSocketDataProvider ssl(true, OK);
7257 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7258 ssl.next_proto = "http/1.1";
7259
7260 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7261
7262 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7263 data_writes, arraysize(data_writes));
7264 session_deps.socket_factory.AddSocketDataProvider(&data);
7265
7266 TestCompletionCallback callback;
7267
7268 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7269 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7270
7271 int rv = trans->Start(&request, &callback, BoundNetLog());
7272
7273 EXPECT_EQ(ERR_IO_PENDING, rv);
7274 EXPECT_EQ(OK, callback.WaitForResult());
7275
7276 const HttpResponseInfo* response = trans->GetResponseInfo();
7277 ASSERT_TRUE(response != NULL);
7278 ASSERT_TRUE(response->headers != NULL);
7279 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7280
7281 std::string response_data;
7282 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7283 EXPECT_EQ("hello world", response_data);
7284
7285 EXPECT_FALSE(response->was_fetched_via_spdy);
7286 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577287 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537288
[email protected]8e6441ca2010-08-19 05:56:387289 HttpStreamFactory::set_next_protos("");
7290 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537291}
[email protected]26ef6582010-06-24 02:30:477292
7293TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7294 // Simulate the SSL handshake completing with an NPN negotiation
7295 // followed by an immediate server closing of the socket.
7296 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387297 HttpStreamFactory::set_use_alternate_protocols(true);
7298 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477299 SessionDependencies session_deps;
7300
7301 HttpRequestInfo request;
7302 request.method = "GET";
7303 request.url = GURL("https://www.google.com/");
7304 request.load_flags = 0;
7305
7306 SSLSocketDataProvider ssl(true, OK);
7307 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357308 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477309 ssl.was_npn_negotiated = true;
7310 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7311
[email protected]2bd93022010-07-17 00:58:447312 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137313 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477314
7315 MockRead spdy_reads[] = {
7316 MockRead(false, 0, 0) // Not async - return 0 immediately.
7317 };
7318
7319 scoped_refptr<DelayedSocketData> spdy_data(
7320 new DelayedSocketData(
7321 0, // don't wait in this case, immediate hangup.
7322 spdy_reads, arraysize(spdy_reads),
7323 spdy_writes, arraysize(spdy_writes)));
7324 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7325
7326 TestCompletionCallback callback;
7327
7328 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7329 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7330
7331 int rv = trans->Start(&request, &callback, BoundNetLog());
7332 EXPECT_EQ(ERR_IO_PENDING, rv);
7333 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7334
[email protected]8e6441ca2010-08-19 05:56:387335 HttpStreamFactory::set_next_protos("");
7336 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477337}
[email protected]65d34382010-07-01 18:12:267338
[email protected]f45c1ee2010-08-03 00:54:307339TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7340 // This test ensures that the URL passed into the proxy is upgraded
7341 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387342 HttpStreamFactory::set_use_alternate_protocols(true);
7343 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307344 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7345
[email protected]81cdfcd2010-10-16 00:49:007346 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307347 HttpAuthHandlerMock::Factory* auth_factory =
7348 new HttpAuthHandlerMock::Factory();
7349 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7350 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7351 auth_factory->set_do_init_from_challenge(true);
7352 session_deps.http_auth_handler_factory.reset(auth_factory);
7353
7354 HttpRequestInfo request;
7355 request.method = "GET";
7356 request.url = GURL("http://www.google.com");
7357 request.load_flags = 0;
7358
7359 // First round goes unauthenticated through the proxy.
7360 MockWrite data_writes_1[] = {
7361 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7362 "Host: www.google.com\r\n"
7363 "Proxy-Connection: keep-alive\r\n"
7364 "\r\n"),
7365 };
7366 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597367 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307368 MockRead("HTTP/1.1 200 OK\r\n"
7369 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7370 "Proxy-Connection: close\r\n"
7371 "\r\n"),
7372 };
7373 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7374 data_writes_1, arraysize(data_writes_1));
7375
7376 // Second round tries to tunnel to www.google.com due to the
7377 // Alternate-Protocol announcement in the first round. It fails due
7378 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597379 // After the failure, a tunnel is established to www.google.com using
7380 // Proxy-Authorization headers. There is then a SPDY request round.
7381 //
7382 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7383 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7384 // does a Disconnect and Connect on the same socket, rather than trying
7385 // to obtain a new one.
7386 //
7387 // NOTE: Originally, the proxy response to the second CONNECT request
7388 // simply returned another 407 so the unit test could skip the SSL connection
7389 // establishment and SPDY framing issues. Alas, the
7390 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307391 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597392
[email protected]f45c1ee2010-08-03 00:54:307393 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7394 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7395 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7396
[email protected]394816e92010-08-03 07:38:597397 MockWrite data_writes_2[] = {
7398 // First connection attempt without Proxy-Authorization.
7399 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7400 "Host: www.google.com\r\n"
7401 "Proxy-Connection: keep-alive\r\n"
7402 "\r\n"),
7403
7404 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307405 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7406 "Host: www.google.com\r\n"
7407 "Proxy-Connection: keep-alive\r\n"
7408 "Proxy-Authorization: auth_token\r\n"
7409 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307410
[email protected]394816e92010-08-03 07:38:597411 // SPDY request
7412 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307413 };
[email protected]394816e92010-08-03 07:38:597414 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7415 "Proxy-Authenticate: Mock\r\n"
7416 "Proxy-Connection: close\r\n"
7417 "\r\n");
7418 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7419 MockRead data_reads_2[] = {
7420 // First connection attempt fails
7421 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7422 MockRead(true, kRejectConnectResponse,
7423 arraysize(kRejectConnectResponse) - 1, 1),
7424
7425 // Second connection attempt passes
7426 MockRead(true, kAcceptConnectResponse,
7427 arraysize(kAcceptConnectResponse) -1, 4),
7428
7429 // SPDY response
7430 CreateMockRead(*resp.get(), 6),
7431 CreateMockRead(*data.get(), 6),
7432 MockRead(true, 0, 0, 6),
7433 };
7434 scoped_refptr<OrderedSocketData> data_2(
7435 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7436 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307437
7438 SSLSocketDataProvider ssl(true, OK);
7439 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7440 ssl.next_proto = "spdy/2";
7441 ssl.was_npn_negotiated = true;
7442
7443 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597444 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307445 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7446 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7447
7448 // First round should work and provide the Alternate-Protocol state.
7449 TestCompletionCallback callback_1;
7450 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7451 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7452 EXPECT_EQ(ERR_IO_PENDING, rv);
7453 EXPECT_EQ(OK, callback_1.WaitForResult());
7454
7455 // Second round should attempt a tunnel connect and get an auth challenge.
7456 TestCompletionCallback callback_2;
7457 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7458 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7459 EXPECT_EQ(ERR_IO_PENDING, rv);
7460 EXPECT_EQ(OK, callback_2.WaitForResult());
7461 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7462 ASSERT_FALSE(response == NULL);
7463 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7464
7465 // Restart with auth. Tunnel should work and response received.
7466 TestCompletionCallback callback_3;
7467 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7468 EXPECT_EQ(ERR_IO_PENDING, rv);
7469 EXPECT_EQ(OK, callback_3.WaitForResult());
7470
7471 // After all that work, these two lines (or actually, just the scheme) are
7472 // what this test is all about. Make sure it happens correctly.
7473 const GURL& request_url = auth_handler->request_url();
7474 EXPECT_EQ("https", request_url.scheme());
7475 EXPECT_EQ("www.google.com", request_url.host());
7476
[email protected]8e6441ca2010-08-19 05:56:387477 HttpStreamFactory::set_next_protos("");
7478 HttpStreamFactory::set_use_alternate_protocols(false);
7479}
7480
7481// Test that if we cancel the transaction as the connection is completing, that
7482// everything tears down correctly.
7483TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7484 // Setup everything about the connection to complete synchronously, so that
7485 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7486 // for is the callback from the HttpStreamRequest.
7487 // Then cancel the transaction.
7488 // Verify that we don't crash.
7489 MockConnect mock_connect(false, OK);
7490 MockRead data_reads[] = {
7491 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7492 MockRead(false, "hello world"),
7493 MockRead(false, OK),
7494 };
7495
7496 SessionDependencies session_deps;
7497 session_deps.host_resolver->set_synchronous_mode(true);
7498 scoped_ptr<HttpTransaction> trans(
7499 new HttpNetworkTransaction(CreateSession(&session_deps)));
7500
7501 HttpRequestInfo request;
7502 request.method = "GET";
7503 request.url = GURL("http://www.google.com/");
7504 request.load_flags = 0;
7505
7506 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7507 data.set_connect_data(mock_connect);
7508 session_deps.socket_factory.AddSocketDataProvider(&data);
7509
7510 TestCompletionCallback callback;
7511
7512 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7513 int rv = trans->Start(&request, &callback, log.bound());
7514 EXPECT_EQ(ERR_IO_PENDING, rv);
7515 trans.reset(); // Cancel the transaction here.
7516
7517 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307518}
7519
[email protected]76a505b2010-08-25 06:23:007520// Test a basic GET request through a proxy.
7521TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007522 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007523 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7524 session_deps.net_log = log.bound().net_log();
7525 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7526
[email protected]76a505b2010-08-25 06:23:007527 HttpRequestInfo request;
7528 request.method = "GET";
7529 request.url = GURL("http://www.google.com/");
7530
7531 MockWrite data_writes1[] = {
7532 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7533 "Host: www.google.com\r\n"
7534 "Proxy-Connection: keep-alive\r\n\r\n"),
7535 };
7536
7537 MockRead data_reads1[] = {
7538 MockRead("HTTP/1.1 200 OK\r\n"),
7539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7540 MockRead("Content-Length: 100\r\n\r\n"),
7541 MockRead(false, OK),
7542 };
7543
7544 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7545 data_writes1, arraysize(data_writes1));
7546 session_deps.socket_factory.AddSocketDataProvider(&data1);
7547
7548 TestCompletionCallback callback1;
7549
[email protected]0b0bf032010-09-21 18:08:507550 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7551
[email protected]76a505b2010-08-25 06:23:007552 int rv = trans->Start(&request, &callback1, log.bound());
7553 EXPECT_EQ(ERR_IO_PENDING, rv);
7554
7555 rv = callback1.WaitForResult();
7556 EXPECT_EQ(OK, rv);
7557
7558 const HttpResponseInfo* response = trans->GetResponseInfo();
7559 ASSERT_FALSE(response == NULL);
7560
7561 EXPECT_TRUE(response->headers->IsKeepAlive());
7562 EXPECT_EQ(200, response->headers->response_code());
7563 EXPECT_EQ(100, response->headers->GetContentLength());
7564 EXPECT_TRUE(response->was_fetched_via_proxy);
7565 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7566}
7567
7568// Test a basic HTTPS GET request through a proxy.
7569TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007570 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007571 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7572 session_deps.net_log = log.bound().net_log();
7573 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7574
[email protected]76a505b2010-08-25 06:23:007575 HttpRequestInfo request;
7576 request.method = "GET";
7577 request.url = GURL("https://www.google.com/");
7578
7579 // Since we have proxy, should try to establish tunnel.
7580 MockWrite data_writes1[] = {
7581 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7582 "Host: www.google.com\r\n"
7583 "Proxy-Connection: keep-alive\r\n\r\n"),
7584
7585 MockWrite("GET / HTTP/1.1\r\n"
7586 "Host: www.google.com\r\n"
7587 "Connection: keep-alive\r\n\r\n"),
7588 };
7589
7590 MockRead data_reads1[] = {
7591 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7592
7593 MockRead("HTTP/1.1 200 OK\r\n"),
7594 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7595 MockRead("Content-Length: 100\r\n\r\n"),
7596 MockRead(false, OK),
7597 };
7598
7599 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7600 data_writes1, arraysize(data_writes1));
7601 session_deps.socket_factory.AddSocketDataProvider(&data1);
7602 SSLSocketDataProvider ssl(true, OK);
7603 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7604
7605 TestCompletionCallback callback1;
7606
[email protected]0b0bf032010-09-21 18:08:507607 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7608
[email protected]76a505b2010-08-25 06:23:007609 int rv = trans->Start(&request, &callback1, log.bound());
7610 EXPECT_EQ(ERR_IO_PENDING, rv);
7611
7612 rv = callback1.WaitForResult();
7613 EXPECT_EQ(OK, rv);
7614 size_t pos = ExpectLogContainsSomewhere(
7615 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7616 NetLog::PHASE_NONE);
7617 ExpectLogContainsSomewhere(
7618 log.entries(), pos,
7619 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7620 NetLog::PHASE_NONE);
7621
7622 const HttpResponseInfo* response = trans->GetResponseInfo();
7623 ASSERT_FALSE(response == NULL);
7624
7625 EXPECT_TRUE(response->headers->IsKeepAlive());
7626 EXPECT_EQ(200, response->headers->response_code());
7627 EXPECT_EQ(100, response->headers->GetContentLength());
7628 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7629 EXPECT_TRUE(response->was_fetched_via_proxy);
7630}
7631
7632// Test a basic HTTPS GET request through a proxy, but the server hangs up
7633// while establishing the tunnel.
7634TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:007635 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007636 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7637 session_deps.net_log = log.bound().net_log();
7638 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7639
[email protected]76a505b2010-08-25 06:23:007640 HttpRequestInfo request;
7641 request.method = "GET";
7642 request.url = GURL("https://www.google.com/");
7643
7644 // Since we have proxy, should try to establish tunnel.
7645 MockWrite data_writes1[] = {
7646 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7647 "Host: www.google.com\r\n"
7648 "Proxy-Connection: keep-alive\r\n\r\n"),
7649
7650 MockWrite("GET / HTTP/1.1\r\n"
7651 "Host: www.google.com\r\n"
7652 "Connection: keep-alive\r\n\r\n"),
7653 };
7654
7655 MockRead data_reads1[] = {
7656 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7657 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7658 MockRead(true, 0, 0), // EOF
7659 };
7660
7661 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7662 data_writes1, arraysize(data_writes1));
7663 session_deps.socket_factory.AddSocketDataProvider(&data1);
7664 SSLSocketDataProvider ssl(true, OK);
7665 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7666
7667 TestCompletionCallback callback1;
7668
[email protected]0b0bf032010-09-21 18:08:507669 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7670
[email protected]76a505b2010-08-25 06:23:007671 int rv = trans->Start(&request, &callback1, log.bound());
7672 EXPECT_EQ(ERR_IO_PENDING, rv);
7673
7674 rv = callback1.WaitForResult();
7675 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7676 size_t pos = ExpectLogContainsSomewhere(
7677 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7678 NetLog::PHASE_NONE);
7679 ExpectLogContainsSomewhere(
7680 log.entries(), pos,
7681 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7682 NetLog::PHASE_NONE);
7683}
7684
[email protected]749eefa82010-09-13 22:14:037685// Test for crbug.com/55424.
7686TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7687 SessionDependencies session_deps;
7688
7689 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7690 "https://www.google.com", false, 1, LOWEST));
7691 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7692
7693 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7694 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7695 MockRead spdy_reads[] = {
7696 CreateMockRead(*resp),
7697 CreateMockRead(*data),
7698 MockRead(true, 0, 0),
7699 };
7700
7701 scoped_refptr<DelayedSocketData> spdy_data(
7702 new DelayedSocketData(
7703 1, // wait for one write to finish before reading.
7704 spdy_reads, arraysize(spdy_reads),
7705 spdy_writes, arraysize(spdy_writes)));
7706 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7707
7708 SSLSocketDataProvider ssl(true, OK);
7709 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7710 ssl.next_proto = "spdy/2";
7711 ssl.was_npn_negotiated = true;
7712 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7713
7714 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7715
7716 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387717 HostPortPair host_port_pair("www.google.com", 443);
7718 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037719 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277720 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7721 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:277722 scoped_refptr<TCPSocketParams> tcp_params(
7723 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:387724 TestCompletionCallback callback;
7725
7726 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7727 EXPECT_EQ(ERR_IO_PENDING,
7728 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7729 &callback, session->tcp_socket_pool(),
7730 BoundNetLog()));
7731 EXPECT_EQ(OK, callback.WaitForResult());
7732 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037733
7734 HttpRequestInfo request;
7735 request.method = "GET";
7736 request.url = GURL("https://www.google.com/");
7737 request.load_flags = 0;
7738
7739 // This is the important line that marks this as a preconnect.
7740 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7741
7742 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7743
[email protected]749eefa82010-09-13 22:14:037744 int rv = trans->Start(&request, &callback, BoundNetLog());
7745 EXPECT_EQ(ERR_IO_PENDING, rv);
7746 EXPECT_EQ(OK, callback.WaitForResult());
7747}
7748
[email protected]73b8dd222010-11-11 19:55:247749// Given a net error, cause that error to be returned from the first Write()
7750// call and verify that the HttpTransaction fails with that error.
7751static void CheckErrorIsPassedBack(int error, bool async) {
7752 SessionDependencies session_deps;
7753
7754 SSLSocketDataProvider ssl_data(async, OK);
7755 net::MockWrite data_writes[] = {
7756 net::MockWrite(async, error),
7757 };
7758 net::StaticSocketDataProvider data(NULL, 0,
7759 data_writes, arraysize(data_writes));
7760 session_deps.socket_factory.AddSocketDataProvider(&data);
7761 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
7762
7763 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7764 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7765
7766 net::HttpRequestInfo request_info;
7767 request_info.url = GURL("https://www.example.com/");
7768 request_info.method = "GET";
7769 request_info.load_flags = net::LOAD_NORMAL;
7770
7771 TestCompletionCallback callback;
7772 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
7773 if (rv == net::ERR_IO_PENDING)
7774 rv = callback.WaitForResult();
7775 ASSERT_EQ(error, rv);
7776}
7777
7778TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
7779 // Just check a grab bag of cert errors.
7780 static const int kErrors[] = {
7781 ERR_CERT_COMMON_NAME_INVALID,
7782 ERR_CERT_AUTHORITY_INVALID,
7783 ERR_CERT_DATE_INVALID,
7784 };
7785 for (size_t i = 0; i < arraysize(kErrors); i++) {
7786 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
7787 CheckErrorIsPassedBack(kErrors[i], true /* async */);
7788 }
7789}
7790
7791// Test that the transaction is restarted in the event of an NPN misprediction.
7792TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
7793 SessionDependencies session_deps;
7794
7795 SSLSocketDataProvider ssl_data1(true /* async */, OK);
7796 SSLSocketDataProvider ssl_data2(true /* async */, OK);
7797
7798 net::MockWrite data1_writes[] = {
7799 net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION),
7800 };
7801 net::MockRead data2_reads[] = {
7802 net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7803 net::MockRead("hello world"),
7804 net::MockRead(false, net::OK),
7805 };
7806 net::MockWrite data2_writes[] = {
7807 net::MockWrite("GET / HTTP/1.1\r\n"
7808 "Host: www.example.com\r\n"
7809 "Connection: keep-alive\r\n\r\n"),
7810 };
7811 net::StaticSocketDataProvider data1(
7812 NULL, 0, data1_writes, arraysize(data1_writes));
7813 net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads),
7814 data2_writes, arraysize(data2_writes));
7815
7816 session_deps.socket_factory.AddSocketDataProvider(&data1);
7817 session_deps.socket_factory.AddSocketDataProvider(&data2);
7818 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
7819 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
7820
7821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7822 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7823
7824 net::HttpRequestInfo request_info;
7825 request_info.url = GURL("https://www.example.com/");
7826 request_info.method = "GET";
7827 request_info.load_flags = net::LOAD_NORMAL;
7828
7829 TestCompletionCallback callback;
7830 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
7831 if (rv == net::ERR_IO_PENDING)
7832 rv = callback.WaitForResult();
7833 ASSERT_EQ(OK, rv);
7834
7835 std::string contents;
7836 rv = ReadTransaction(trans.get(), &contents);
7837 EXPECT_EQ(net::OK, rv);
7838 EXPECT_EQ("hello world", contents);
7839}
7840
[email protected]89ceba9a2009-03-21 03:46:067841} // namespace net