Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1053)

Side by Side Diff: net/http/http_network_transaction_unittest.cc

Issue 9582034: Fork SPDY/2 and SPDY/3 versions of our SPDY tests, in preparation for landing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix merge bug Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_network_transaction.h"
6
7 #include <math.h> // ceil
8 #include <stdarg.h>
9 #include <string>
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_path.h"
15 #include "base/file_util.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/metrics/histogram.h"
18 #include "base/test/test_file_util.h"
19 #include "base/utf_string_conversions.h"
20 #include "net/base/auth.h"
21 #include "net/base/capturing_net_log.h"
22 #include "net/base/completion_callback.h"
23 #include "net/base/host_cache.h"
24 #include "net/base/mock_host_resolver.h"
25 #include "net/base/net_log.h"
26 #include "net/base/net_log_unittest.h"
27 #include "net/base/request_priority.h"
28 #include "net/base/ssl_cert_request_info.h"
29 #include "net/base/ssl_config_service_defaults.h"
30 #include "net/base/ssl_info.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/upload_data.h"
33 #include "net/http/http_auth_handler_digest.h"
34 #include "net/http/http_auth_handler_mock.h"
35 #include "net/http/http_auth_handler_ntlm.h"
36 #include "net/http/http_basic_stream.h"
37 #include "net/http/http_net_log_params.h"
38 #include "net/http/http_network_session.h"
39 #include "net/http/http_network_session_peer.h"
40 #include "net/http/http_server_properties_impl.h"
41 #include "net/http/http_stream.h"
42 #include "net/http/http_stream_factory.h"
43 #include "net/http/http_transaction_unittest.h"
44 #include "net/proxy/proxy_config_service_fixed.h"
45 #include "net/proxy/proxy_resolver.h"
46 #include "net/proxy/proxy_service.h"
47 #include "net/socket/client_socket_factory.h"
48 #include "net/socket/mock_client_socket_pool_manager.h"
49 #include "net/socket/socket_test_util.h"
50 #include "net/socket/ssl_client_socket.h"
51 #include "net/spdy/spdy_framer.h"
52 #include "net/spdy/spdy_session.h"
53 #include "net/spdy/spdy_session_pool.h"
54 #include "net/spdy/spdy_test_util.h"
55 #include "testing/gtest/include/gtest/gtest.h"
56 #include "testing/platform_test.h"
57
58 //-----------------------------------------------------------------------------
59
60 namespace {
61
62 const string16 kBar(ASCIIToUTF16("bar"));
63 const string16 kBar2(ASCIIToUTF16("bar2"));
64 const string16 kBar3(ASCIIToUTF16("bar3"));
65 const string16 kBaz(ASCIIToUTF16("baz"));
66 const string16 kFirst(ASCIIToUTF16("first"));
67 const string16 kFoo(ASCIIToUTF16("foo"));
68 const string16 kFoo2(ASCIIToUTF16("foo2"));
69 const string16 kFoo3(ASCIIToUTF16("foo3"));
70 const string16 kFou(ASCIIToUTF16("fou"));
71 const string16 kSecond(ASCIIToUTF16("second"));
72 const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
73 const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
74
75 // MakeNextProtos is a utility function that returns a vector of std::strings
76 // from its arguments. Don't forget to terminate the argument list with a NULL.
77 std::vector<std::string> MakeNextProtos(const char* a, ...) {
78 std::vector<std::string> ret;
79 ret.push_back(a);
80
81 va_list args;
82 va_start(args, a);
83
84 for (;;) {
85 const char* value = va_arg(args, const char*);
86 if (value == NULL)
87 break;
88 ret.push_back(value);
89 }
90 va_end(args);
91
92 return ret;
93 }
94
95 // SpdyNextProtos returns a vector of NPN protocol strings for negotiating
96 // SPDY.
97 std::vector<std::string> SpdyNextProtos() {
98 return MakeNextProtos("http/1.1", "spdy/2", "spdy/2.1", NULL);
99 }
100
101 } // namespace
102
103 namespace net {
104
105 // Helper to manage the lifetimes of the dependencies for a
106 // HttpNetworkTransaction.
107 struct SessionDependencies {
108 // Default set of dependencies -- "null" proxy service.
109 SessionDependencies()
110 : host_resolver(new MockHostResolver),
111 cert_verifier(new CertVerifier),
112 proxy_service(ProxyService::CreateDirect()),
113 ssl_config_service(new SSLConfigServiceDefaults),
114 http_auth_handler_factory(
115 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
116 net_log(NULL) {}
117
118 // Custom proxy service dependency.
119 explicit SessionDependencies(ProxyService* proxy_service)
120 : host_resolver(new MockHostResolver),
121 cert_verifier(new CertVerifier),
122 proxy_service(proxy_service),
123 ssl_config_service(new SSLConfigServiceDefaults),
124 http_auth_handler_factory(
125 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
126 net_log(NULL) {}
127
128 scoped_ptr<MockHostResolverBase> host_resolver;
129 scoped_ptr<CertVerifier> cert_verifier;
130 scoped_ptr<ProxyService> proxy_service;
131 scoped_refptr<SSLConfigService> ssl_config_service;
132 MockClientSocketFactory socket_factory;
133 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
134 HttpServerPropertiesImpl http_server_properties;
135 NetLog* net_log;
136 };
137
138 HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
139 net::HttpNetworkSession::Params params;
140 params.client_socket_factory = &session_deps->socket_factory;
141 params.host_resolver = session_deps->host_resolver.get();
142 params.cert_verifier = session_deps->cert_verifier.get();
143 params.proxy_service = session_deps->proxy_service.get();
144 params.ssl_config_service = session_deps->ssl_config_service;
145 params.http_auth_handler_factory =
146 session_deps->http_auth_handler_factory.get();
147 params.http_server_properties = &session_deps->http_server_properties;
148 params.net_log = session_deps->net_log;
149 return new HttpNetworkSession(params);
150 }
151
152 class HttpNetworkTransactionTest : public PlatformTest {
153 protected:
154 struct SimpleGetHelperResult {
155 int rv;
156 std::string status_line;
157 std::string response_data;
158 };
159
160 virtual void SetUp() {
161 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
162 MessageLoop::current()->RunAllPending();
163 spdy::SpdyFramer::set_enable_compression_default(false);
164 }
165
166 virtual void TearDown() {
167 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
168 MessageLoop::current()->RunAllPending();
169 spdy::SpdyFramer::set_enable_compression_default(true);
170 // Empty the current queue.
171 MessageLoop::current()->RunAllPending();
172 PlatformTest::TearDown();
173 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
174 MessageLoop::current()->RunAllPending();
175 }
176
177 // Either |write_failure| specifies a write failure or |read_failure|
178 // specifies a read failure when using a reused socket. In either case, the
179 // failure should cause the network transaction to resend the request, and the
180 // other argument should be NULL.
181 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
182 const MockRead* read_failure);
183
184 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
185 size_t data_count) {
186 SimpleGetHelperResult out;
187
188 HttpRequestInfo request;
189 request.method = "GET";
190 request.url = GURL("http://www.google.com/");
191 request.load_flags = 0;
192
193 SessionDependencies session_deps;
194 scoped_ptr<HttpTransaction> trans(
195 new HttpNetworkTransaction(CreateSession(&session_deps)));
196
197 for (size_t i = 0; i < data_count; ++i) {
198 session_deps.socket_factory.AddSocketDataProvider(data[i]);
199 }
200
201 TestCompletionCallback callback;
202
203 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
204 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
205 int rv = trans->Start(&request, callback.callback(), log.bound());
206 EXPECT_EQ(ERR_IO_PENDING, rv);
207
208 out.rv = callback.WaitForResult();
209 if (out.rv != OK)
210 return out;
211
212 const HttpResponseInfo* response = trans->GetResponseInfo();
213 // Can't use ASSERT_* inside helper functions like this, so
214 // return an error.
215 if (response == NULL || response->headers == NULL) {
216 out.rv = ERR_UNEXPECTED;
217 return out;
218 }
219 out.status_line = response->headers->GetStatusLine();
220
221 EXPECT_EQ("192.0.2.33", response->socket_address.host());
222 EXPECT_EQ(0, response->socket_address.port());
223
224 rv = ReadTransaction(trans.get(), &out.response_data);
225 EXPECT_EQ(OK, rv);
226
227 net::CapturingNetLog::EntryList entries;
228 log.GetEntries(&entries);
229 size_t pos = ExpectLogContainsSomewhere(
230 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
231 NetLog::PHASE_NONE);
232 ExpectLogContainsSomewhere(
233 entries, pos,
234 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
235 NetLog::PHASE_NONE);
236
237 CapturingNetLog::Entry entry = entries[pos];
238 NetLogHttpRequestParameter* request_params =
239 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
240 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
241 EXPECT_EQ("Host: www.google.com\r\n"
242 "Connection: keep-alive\r\n\r\n",
243 request_params->GetHeaders().ToString());
244
245 return out;
246 }
247
248 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
249 size_t reads_count) {
250 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
251 StaticSocketDataProvider* data[] = { &reads };
252 return SimpleGetHelperForData(data, 1);
253 }
254
255 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
256 int expected_status);
257
258 void ConnectStatusHelper(const MockRead& status);
259 };
260
261 // Fill |str| with a long header list that consumes >= |size| bytes.
262 void FillLargeHeadersString(std::string* str, int size) {
263 const char* row =
264 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
265 const int sizeof_row = strlen(row);
266 const int num_rows = static_cast<int>(
267 ceil(static_cast<float>(size) / sizeof_row));
268 const int sizeof_data = num_rows * sizeof_row;
269 DCHECK(sizeof_data >= size);
270 str->reserve(sizeof_data);
271
272 for (int i = 0; i < num_rows; ++i)
273 str->append(row, sizeof_row);
274 }
275
276 // Alternative functions that eliminate randomness and dependency on the local
277 // host name so that the generated NTLM messages are reproducible.
278 void MockGenerateRandom1(uint8* output, size_t n) {
279 static const uint8 bytes[] = {
280 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
281 };
282 static size_t current_byte = 0;
283 for (size_t i = 0; i < n; ++i) {
284 output[i] = bytes[current_byte++];
285 current_byte %= arraysize(bytes);
286 }
287 }
288
289 void MockGenerateRandom2(uint8* output, size_t n) {
290 static const uint8 bytes[] = {
291 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
292 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
293 };
294 static size_t current_byte = 0;
295 for (size_t i = 0; i < n; ++i) {
296 output[i] = bytes[current_byte++];
297 current_byte %= arraysize(bytes);
298 }
299 }
300
301 std::string MockGetHostName() {
302 return "WTC-WIN7";
303 }
304
305 template<typename ParentPool>
306 class CaptureGroupNameSocketPool : public ParentPool {
307 public:
308 CaptureGroupNameSocketPool(HostResolver* host_resolver,
309 CertVerifier* cert_verifier);
310
311 const std::string last_group_name_received() const {
312 return last_group_name_;
313 }
314
315 virtual int RequestSocket(const std::string& group_name,
316 const void* socket_params,
317 RequestPriority priority,
318 ClientSocketHandle* handle,
319 const CompletionCallback& callback,
320 const BoundNetLog& net_log) {
321 last_group_name_ = group_name;
322 return ERR_IO_PENDING;
323 }
324 virtual void CancelRequest(const std::string& group_name,
325 ClientSocketHandle* handle) {}
326 virtual void ReleaseSocket(const std::string& group_name,
327 StreamSocket* socket,
328 int id) {}
329 virtual void CloseIdleSockets() {}
330 virtual int IdleSocketCount() const {
331 return 0;
332 }
333 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
334 return 0;
335 }
336 virtual LoadState GetLoadState(const std::string& group_name,
337 const ClientSocketHandle* handle) const {
338 return LOAD_STATE_IDLE;
339 }
340 virtual base::TimeDelta ConnectionTimeout() const {
341 return base::TimeDelta();
342 }
343
344 private:
345 std::string last_group_name_;
346 };
347
348 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
349 CaptureGroupNameTransportSocketPool;
350 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
351 CaptureGroupNameHttpProxySocketPool;
352 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
353 CaptureGroupNameSOCKSSocketPool;
354 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
355 CaptureGroupNameSSLSocketPool;
356
357 template<typename ParentPool>
358 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
359 HostResolver* host_resolver,
360 CertVerifier* /* cert_verifier */)
361 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
362
363 template<>
364 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
365 HostResolver* host_resolver,
366 CertVerifier* /* cert_verifier */)
367 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
368
369 template<>
370 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
371 HostResolver* host_resolver,
372 CertVerifier* cert_verifier)
373 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL,
374 NULL, NULL, "", NULL, NULL, NULL, NULL, NULL, NULL) {}
375
376 //-----------------------------------------------------------------------------
377
378 // This is the expected return from a current server advertising SPDY.
379 static const char kAlternateProtocolHttpHeader[] =
380 "Alternate-Protocol: 443:npn-spdy/2.1\r\n\r\n";
381
382 // Helper functions for validating that AuthChallengeInfo's are correctly
383 // configured for common cases.
384 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
385 if (!auth_challenge)
386 return false;
387 EXPECT_FALSE(auth_challenge->is_proxy);
388 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
389 EXPECT_EQ("MyRealm1", auth_challenge->realm);
390 EXPECT_EQ("basic", auth_challenge->scheme);
391 return true;
392 }
393
394 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
395 if (!auth_challenge)
396 return false;
397 EXPECT_TRUE(auth_challenge->is_proxy);
398 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
399 EXPECT_EQ("MyRealm1", auth_challenge->realm);
400 EXPECT_EQ("basic", auth_challenge->scheme);
401 return true;
402 }
403
404 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
405 if (!auth_challenge)
406 return false;
407 EXPECT_FALSE(auth_challenge->is_proxy);
408 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
409 EXPECT_EQ("digestive", auth_challenge->realm);
410 EXPECT_EQ("digest", auth_challenge->scheme);
411 return true;
412 }
413
414 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
415 if (!auth_challenge)
416 return false;
417 EXPECT_FALSE(auth_challenge->is_proxy);
418 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
419 EXPECT_EQ(std::string(), auth_challenge->realm);
420 EXPECT_EQ("ntlm", auth_challenge->scheme);
421 return true;
422 }
423
424 TEST_F(HttpNetworkTransactionTest, Basic) {
425 SessionDependencies session_deps;
426 scoped_ptr<HttpTransaction> trans(
427 new HttpNetworkTransaction(CreateSession(&session_deps)));
428 }
429
430 TEST_F(HttpNetworkTransactionTest, SimpleGET) {
431 MockRead data_reads[] = {
432 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
433 MockRead("hello world"),
434 MockRead(SYNCHRONOUS, OK),
435 };
436 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
437 arraysize(data_reads));
438 EXPECT_EQ(OK, out.rv);
439 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
440 EXPECT_EQ("hello world", out.response_data);
441 }
442
443 // Response with no status line.
444 TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
445 MockRead data_reads[] = {
446 MockRead("hello world"),
447 MockRead(SYNCHRONOUS, OK),
448 };
449 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
450 arraysize(data_reads));
451 EXPECT_EQ(OK, out.rv);
452 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
453 EXPECT_EQ("hello world", out.response_data);
454 }
455
456 // Allow up to 4 bytes of junk to precede status line.
457 TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
458 MockRead data_reads[] = {
459 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
460 MockRead(SYNCHRONOUS, OK),
461 };
462 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
463 arraysize(data_reads));
464 EXPECT_EQ(OK, out.rv);
465 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
466 EXPECT_EQ("DATA", out.response_data);
467 }
468
469 // Allow up to 4 bytes of junk to precede status line.
470 TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
471 MockRead data_reads[] = {
472 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
473 MockRead(SYNCHRONOUS, OK),
474 };
475 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
476 arraysize(data_reads));
477 EXPECT_EQ(OK, out.rv);
478 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
479 EXPECT_EQ("DATA", out.response_data);
480 }
481
482 // Beyond 4 bytes of slop and it should fail to find a status line.
483 TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
484 MockRead data_reads[] = {
485 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
486 MockRead(SYNCHRONOUS, OK),
487 };
488 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
489 arraysize(data_reads));
490 EXPECT_EQ(OK, out.rv);
491 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
492 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
493 }
494
495 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
496 TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
497 MockRead data_reads[] = {
498 MockRead("\n"),
499 MockRead("\n"),
500 MockRead("Q"),
501 MockRead("J"),
502 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
503 MockRead(SYNCHRONOUS, OK),
504 };
505 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
506 arraysize(data_reads));
507 EXPECT_EQ(OK, out.rv);
508 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
509 EXPECT_EQ("DATA", out.response_data);
510 }
511
512 // Close the connection before enough bytes to have a status line.
513 TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
514 MockRead data_reads[] = {
515 MockRead("HTT"),
516 MockRead(SYNCHRONOUS, OK),
517 };
518 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
519 arraysize(data_reads));
520 EXPECT_EQ(OK, out.rv);
521 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
522 EXPECT_EQ("HTT", out.response_data);
523 }
524
525 // Simulate a 204 response, lacking a Content-Length header, sent over a
526 // persistent connection. The response should still terminate since a 204
527 // cannot have a response body.
528 TEST_F(HttpNetworkTransactionTest, StopsReading204) {
529 MockRead data_reads[] = {
530 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
531 MockRead("junk"), // Should not be read!!
532 MockRead(SYNCHRONOUS, OK),
533 };
534 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
535 arraysize(data_reads));
536 EXPECT_EQ(OK, out.rv);
537 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
538 EXPECT_EQ("", out.response_data);
539 }
540
541 // A simple request using chunked encoding with some extra data after.
542 // (Like might be seen in a pipelined response.)
543 TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
544 MockRead data_reads[] = {
545 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
546 MockRead("5\r\nHello\r\n"),
547 MockRead("1\r\n"),
548 MockRead(" \r\n"),
549 MockRead("5\r\nworld\r\n"),
550 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
551 MockRead(SYNCHRONOUS, OK),
552 };
553 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
554 arraysize(data_reads));
555 EXPECT_EQ(OK, out.rv);
556 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
557 EXPECT_EQ("Hello world", out.response_data);
558 }
559
560 // Next tests deal with http://crbug.com/56344.
561
562 TEST_F(HttpNetworkTransactionTest,
563 MultipleContentLengthHeadersNoTransferEncoding) {
564 MockRead data_reads[] = {
565 MockRead("HTTP/1.1 200 OK\r\n"),
566 MockRead("Content-Length: 10\r\n"),
567 MockRead("Content-Length: 5\r\n\r\n"),
568 };
569 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
570 arraysize(data_reads));
571 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
572 }
573
574 TEST_F(HttpNetworkTransactionTest,
575 DuplicateContentLengthHeadersNoTransferEncoding) {
576 MockRead data_reads[] = {
577 MockRead("HTTP/1.1 200 OK\r\n"),
578 MockRead("Content-Length: 5\r\n"),
579 MockRead("Content-Length: 5\r\n\r\n"),
580 MockRead("Hello"),
581 };
582 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
583 arraysize(data_reads));
584 EXPECT_EQ(OK, out.rv);
585 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
586 EXPECT_EQ("Hello", out.response_data);
587 }
588
589 TEST_F(HttpNetworkTransactionTest,
590 ComplexContentLengthHeadersNoTransferEncoding) {
591 // More than 2 dupes.
592 {
593 MockRead data_reads[] = {
594 MockRead("HTTP/1.1 200 OK\r\n"),
595 MockRead("Content-Length: 5\r\n"),
596 MockRead("Content-Length: 5\r\n"),
597 MockRead("Content-Length: 5\r\n\r\n"),
598 MockRead("Hello"),
599 };
600 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
601 arraysize(data_reads));
602 EXPECT_EQ(OK, out.rv);
603 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
604 EXPECT_EQ("Hello", out.response_data);
605 }
606 // HTTP/1.0
607 {
608 MockRead data_reads[] = {
609 MockRead("HTTP/1.0 200 OK\r\n"),
610 MockRead("Content-Length: 5\r\n"),
611 MockRead("Content-Length: 5\r\n"),
612 MockRead("Content-Length: 5\r\n\r\n"),
613 MockRead("Hello"),
614 };
615 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
616 arraysize(data_reads));
617 EXPECT_EQ(OK, out.rv);
618 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
619 EXPECT_EQ("Hello", out.response_data);
620 }
621 // 2 dupes and one mismatched.
622 {
623 MockRead data_reads[] = {
624 MockRead("HTTP/1.1 200 OK\r\n"),
625 MockRead("Content-Length: 10\r\n"),
626 MockRead("Content-Length: 10\r\n"),
627 MockRead("Content-Length: 5\r\n\r\n"),
628 };
629 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
630 arraysize(data_reads));
631 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
632 }
633 }
634
635 TEST_F(HttpNetworkTransactionTest,
636 MultipleContentLengthHeadersTransferEncoding) {
637 MockRead data_reads[] = {
638 MockRead("HTTP/1.1 200 OK\r\n"),
639 MockRead("Content-Length: 666\r\n"),
640 MockRead("Content-Length: 1337\r\n"),
641 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
642 MockRead("5\r\nHello\r\n"),
643 MockRead("1\r\n"),
644 MockRead(" \r\n"),
645 MockRead("5\r\nworld\r\n"),
646 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
647 MockRead(SYNCHRONOUS, OK),
648 };
649 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
650 arraysize(data_reads));
651 EXPECT_EQ(OK, out.rv);
652 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
653 EXPECT_EQ("Hello world", out.response_data);
654 }
655
656 // Next tests deal with http://crbug.com/98895.
657
658 // Checks that a single Content-Disposition header results in no error.
659 TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
660 MockRead data_reads[] = {
661 MockRead("HTTP/1.1 200 OK\r\n"),
662 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
663 MockRead("Content-Length: 5\r\n\r\n"),
664 MockRead("Hello"),
665 };
666 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
667 arraysize(data_reads));
668 EXPECT_EQ(OK, out.rv);
669 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
670 EXPECT_EQ("Hello", out.response_data);
671 }
672
673 // Checks that two identical Content-Disposition headers result in an error.
674 TEST_F(HttpNetworkTransactionTest,
675 DuplicateIdenticalContentDispositionHeaders) {
676 MockRead data_reads[] = {
677 MockRead("HTTP/1.1 200 OK\r\n"),
678 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
679 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
680 MockRead("Content-Length: 5\r\n\r\n"),
681 MockRead("Hello"),
682 };
683 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
684 arraysize(data_reads));
685 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
686 }
687
688 // Checks that two distinct Content-Disposition headers result in an error.
689 TEST_F(HttpNetworkTransactionTest, DuplicateDistinctContentDispositionHeaders) {
690 MockRead data_reads[] = {
691 MockRead("HTTP/1.1 200 OK\r\n"),
692 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
693 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
694 MockRead("Content-Length: 5\r\n\r\n"),
695 MockRead("Hello"),
696 };
697 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
698 arraysize(data_reads));
699 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
700 }
701
702 // Checks the behavior of a single Location header.
703 TEST_F(HttpNetworkTransactionTest, SingleLocationHeader) {
704 MockRead data_reads[] = {
705 MockRead("HTTP/1.1 302 Redirect\r\n"),
706 MockRead("Location: http://good.com/\r\n"),
707 MockRead("Content-Length: 0\r\n\r\n"),
708 MockRead(SYNCHRONOUS, OK),
709 };
710
711 HttpRequestInfo request;
712 request.method = "GET";
713 request.url = GURL("http://redirect.com/");
714 request.load_flags = 0;
715
716 SessionDependencies session_deps;
717 scoped_ptr<HttpTransaction> trans(
718 new HttpNetworkTransaction(CreateSession(&session_deps)));
719
720 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
721 session_deps.socket_factory.AddSocketDataProvider(&data);
722
723 TestCompletionCallback callback;
724
725 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
726 EXPECT_EQ(ERR_IO_PENDING, rv);
727
728 EXPECT_EQ(OK, callback.WaitForResult());
729
730 const HttpResponseInfo* response = trans->GetResponseInfo();
731 ASSERT_TRUE(response != NULL && response->headers != NULL);
732 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
733 std::string url;
734 EXPECT_TRUE(response->headers->IsRedirect(&url));
735 EXPECT_EQ("http://good.com/", url);
736 }
737
738 // Checks that two identical Location headers result in an error.
739 TEST_F(HttpNetworkTransactionTest, DuplicateIdenticalLocationHeaders) {
740 MockRead data_reads[] = {
741 MockRead("HTTP/1.1 302 Redirect\r\n"),
742 MockRead("Location: http://good.com/\r\n"),
743 MockRead("Location: http://good.com/\r\n"),
744 MockRead("Content-Length: 0\r\n\r\n"),
745 MockRead(SYNCHRONOUS, OK),
746 };
747 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
748 arraysize(data_reads));
749 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
750 }
751
752 // Checks that two distinct Location headers result in an error.
753 TEST_F(HttpNetworkTransactionTest, DuplicateDistinctLocationHeaders) {
754 MockRead data_reads[] = {
755 MockRead("HTTP/1.1 302 Redirect\r\n"),
756 MockRead("Location: http://good.com/\r\n"),
757 MockRead("Location: http://evil.com/\r\n"),
758 MockRead("Content-Length: 0\r\n\r\n"),
759 MockRead(SYNCHRONOUS, OK),
760 };
761 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
762 arraysize(data_reads));
763 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
764 }
765
766 // Do a request using the HEAD method. Verify that we don't try to read the
767 // message body (since HEAD has none).
768 TEST_F(HttpNetworkTransactionTest, Head) {
769 HttpRequestInfo request;
770 request.method = "HEAD";
771 request.url = GURL("http://www.google.com/");
772 request.load_flags = 0;
773
774 SessionDependencies session_deps;
775 scoped_ptr<HttpTransaction> trans(
776 new HttpNetworkTransaction(CreateSession(&session_deps)));
777
778 MockWrite data_writes1[] = {
779 MockWrite("HEAD / HTTP/1.1\r\n"
780 "Host: www.google.com\r\n"
781 "Connection: keep-alive\r\n"
782 "Content-Length: 0\r\n\r\n"),
783 };
784 MockRead data_reads1[] = {
785 MockRead("HTTP/1.1 404 Not Found\r\n"),
786 MockRead("Server: Blah\r\n"),
787 MockRead("Content-Length: 1234\r\n\r\n"),
788
789 // No response body because the test stops reading here.
790 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
791 };
792
793 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
794 data_writes1, arraysize(data_writes1));
795 session_deps.socket_factory.AddSocketDataProvider(&data1);
796
797 TestCompletionCallback callback1;
798
799 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
800 EXPECT_EQ(ERR_IO_PENDING, rv);
801
802 rv = callback1.WaitForResult();
803 EXPECT_EQ(OK, rv);
804
805 const HttpResponseInfo* response = trans->GetResponseInfo();
806 ASSERT_TRUE(response != NULL);
807
808 // Check that the headers got parsed.
809 EXPECT_TRUE(response->headers != NULL);
810 EXPECT_EQ(1234, response->headers->GetContentLength());
811 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
812
813 std::string server_header;
814 void* iter = NULL;
815 bool has_server_header = response->headers->EnumerateHeader(
816 &iter, "Server", &server_header);
817 EXPECT_TRUE(has_server_header);
818 EXPECT_EQ("Blah", server_header);
819
820 // Reading should give EOF right away, since there is no message body
821 // (despite non-zero content-length).
822 std::string response_data;
823 rv = ReadTransaction(trans.get(), &response_data);
824 EXPECT_EQ(OK, rv);
825 EXPECT_EQ("", response_data);
826 }
827
828 TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
829 SessionDependencies session_deps;
830 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
831
832 MockRead data_reads[] = {
833 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
834 MockRead("hello"),
835 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
836 MockRead("world"),
837 MockRead(SYNCHRONOUS, OK),
838 };
839 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
840 session_deps.socket_factory.AddSocketDataProvider(&data);
841
842 const char* const kExpectedResponseData[] = {
843 "hello", "world"
844 };
845
846 for (int i = 0; i < 2; ++i) {
847 HttpRequestInfo request;
848 request.method = "GET";
849 request.url = GURL("http://www.google.com/");
850 request.load_flags = 0;
851
852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
853
854 TestCompletionCallback callback;
855
856 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
857 EXPECT_EQ(ERR_IO_PENDING, rv);
858
859 rv = callback.WaitForResult();
860 EXPECT_EQ(OK, rv);
861
862 const HttpResponseInfo* response = trans->GetResponseInfo();
863 ASSERT_TRUE(response != NULL);
864
865 EXPECT_TRUE(response->headers != NULL);
866 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
867
868 std::string response_data;
869 rv = ReadTransaction(trans.get(), &response_data);
870 EXPECT_EQ(OK, rv);
871 EXPECT_EQ(kExpectedResponseData[i], response_data);
872 }
873 }
874
875 TEST_F(HttpNetworkTransactionTest, Ignores100) {
876 HttpRequestInfo request;
877 request.method = "POST";
878 request.url = GURL("http://www.foo.com/");
879 request.upload_data = new UploadData;
880 request.upload_data->AppendBytes("foo", 3);
881 request.load_flags = 0;
882
883 SessionDependencies session_deps;
884 scoped_ptr<HttpTransaction> trans(
885 new HttpNetworkTransaction(CreateSession(&session_deps)));
886
887 MockRead data_reads[] = {
888 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
889 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
890 MockRead("hello world"),
891 MockRead(SYNCHRONOUS, OK),
892 };
893 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
894 session_deps.socket_factory.AddSocketDataProvider(&data);
895
896 TestCompletionCallback callback;
897
898 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
899 EXPECT_EQ(ERR_IO_PENDING, rv);
900
901 rv = callback.WaitForResult();
902 EXPECT_EQ(OK, rv);
903
904 const HttpResponseInfo* response = trans->GetResponseInfo();
905 ASSERT_TRUE(response != NULL);
906
907 EXPECT_TRUE(response->headers != NULL);
908 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
909
910 std::string response_data;
911 rv = ReadTransaction(trans.get(), &response_data);
912 EXPECT_EQ(OK, rv);
913 EXPECT_EQ("hello world", response_data);
914 }
915
916 // This test is almost the same as Ignores100 above, but the response contains
917 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
918 // HTTP/1.1 and the two status headers are read in one read.
919 TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
920 HttpRequestInfo request;
921 request.method = "GET";
922 request.url = GURL("http://www.foo.com/");
923 request.load_flags = 0;
924
925 SessionDependencies session_deps;
926 scoped_ptr<HttpTransaction> trans(
927 new HttpNetworkTransaction(CreateSession(&session_deps)));
928
929 MockRead data_reads[] = {
930 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
931 "HTTP/1.1 200 OK\r\n\r\n"),
932 MockRead("hello world"),
933 MockRead(SYNCHRONOUS, OK),
934 };
935 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
936 session_deps.socket_factory.AddSocketDataProvider(&data);
937
938 TestCompletionCallback callback;
939
940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
941 EXPECT_EQ(ERR_IO_PENDING, rv);
942
943 rv = callback.WaitForResult();
944 EXPECT_EQ(OK, rv);
945
946 const HttpResponseInfo* response = trans->GetResponseInfo();
947 ASSERT_TRUE(response != NULL);
948
949 EXPECT_TRUE(response->headers != NULL);
950 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
951
952 std::string response_data;
953 rv = ReadTransaction(trans.get(), &response_data);
954 EXPECT_EQ(OK, rv);
955 EXPECT_EQ("hello world", response_data);
956 }
957
958 TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
959 HttpRequestInfo request;
960 request.method = "POST";
961 request.url = GURL("http://www.foo.com/");
962 request.load_flags = 0;
963
964 SessionDependencies session_deps;
965 scoped_ptr<HttpTransaction> trans(
966 new HttpNetworkTransaction(CreateSession(&session_deps)));
967
968 MockRead data_reads[] = {
969 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
970 MockRead(ASYNC, 0),
971 };
972 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
973 session_deps.socket_factory.AddSocketDataProvider(&data);
974
975 TestCompletionCallback callback;
976
977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
978 EXPECT_EQ(ERR_IO_PENDING, rv);
979
980 rv = callback.WaitForResult();
981 EXPECT_EQ(OK, rv);
982
983 std::string response_data;
984 rv = ReadTransaction(trans.get(), &response_data);
985 EXPECT_EQ(OK, rv);
986 EXPECT_EQ("", response_data);
987 }
988
989 TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
990 HttpRequestInfo request;
991 request.method = "POST";
992 request.url = GURL("http://www.foo.com/");
993 request.load_flags = 0;
994
995 SessionDependencies session_deps;
996 scoped_ptr<HttpTransaction> trans(
997 new HttpNetworkTransaction(CreateSession(&session_deps)));
998
999 MockRead data_reads[] = {
1000 MockRead(ASYNC, 0),
1001 };
1002 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1003 session_deps.socket_factory.AddSocketDataProvider(&data);
1004
1005 TestCompletionCallback callback;
1006
1007 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1008 EXPECT_EQ(ERR_IO_PENDING, rv);
1009
1010 rv = callback.WaitForResult();
1011 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1012 }
1013
1014 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1015 const MockWrite* write_failure,
1016 const MockRead* read_failure) {
1017 HttpRequestInfo request;
1018 request.method = "GET";
1019 request.url = GURL("http://www.foo.com/");
1020 request.load_flags = 0;
1021
1022 SessionDependencies session_deps;
1023 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1024
1025 // Written data for successfully sending both requests.
1026 MockWrite data1_writes[] = {
1027 MockWrite("GET / HTTP/1.1\r\n"
1028 "Host: www.foo.com\r\n"
1029 "Connection: keep-alive\r\n\r\n"),
1030 MockWrite("GET / HTTP/1.1\r\n"
1031 "Host: www.foo.com\r\n"
1032 "Connection: keep-alive\r\n\r\n")
1033 };
1034
1035 // Read results for the first request.
1036 MockRead data1_reads[] = {
1037 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1038 MockRead("hello"),
1039 MockRead(ASYNC, OK),
1040 };
1041
1042 if (write_failure) {
1043 ASSERT_TRUE(!read_failure);
1044 data1_writes[1] = *write_failure;
1045 } else {
1046 ASSERT_TRUE(read_failure);
1047 data1_reads[2] = *read_failure;
1048 }
1049
1050 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1051 data1_writes, arraysize(data1_writes));
1052 session_deps.socket_factory.AddSocketDataProvider(&data1);
1053
1054 MockRead data2_reads[] = {
1055 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1056 MockRead("world"),
1057 MockRead(ASYNC, OK),
1058 };
1059 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1060 session_deps.socket_factory.AddSocketDataProvider(&data2);
1061
1062 const char* kExpectedResponseData[] = {
1063 "hello", "world"
1064 };
1065
1066 for (int i = 0; i < 2; ++i) {
1067 TestCompletionCallback callback;
1068
1069 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1070
1071 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1072 EXPECT_EQ(ERR_IO_PENDING, rv);
1073
1074 rv = callback.WaitForResult();
1075 EXPECT_EQ(OK, rv);
1076
1077 const HttpResponseInfo* response = trans->GetResponseInfo();
1078 ASSERT_TRUE(response != NULL);
1079
1080 EXPECT_TRUE(response->headers != NULL);
1081 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1082
1083 std::string response_data;
1084 rv = ReadTransaction(trans.get(), &response_data);
1085 EXPECT_EQ(OK, rv);
1086 EXPECT_EQ(kExpectedResponseData[i], response_data);
1087 }
1088 }
1089
1090 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
1091 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1092 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1093 }
1094
1095 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1096 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1097 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1098 }
1099
1100 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1101 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1102 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1103 }
1104
1105 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1106 HttpRequestInfo request;
1107 request.method = "GET";
1108 request.url = GURL("http://www.google.com/");
1109 request.load_flags = 0;
1110
1111 SessionDependencies session_deps;
1112 scoped_ptr<HttpTransaction> trans(
1113 new HttpNetworkTransaction(CreateSession(&session_deps)));
1114
1115 MockRead data_reads[] = {
1116 MockRead(ASYNC, ERR_CONNECTION_RESET),
1117 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1118 MockRead("hello world"),
1119 MockRead(SYNCHRONOUS, OK),
1120 };
1121 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1122 session_deps.socket_factory.AddSocketDataProvider(&data);
1123
1124 TestCompletionCallback callback;
1125
1126 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1127 EXPECT_EQ(ERR_IO_PENDING, rv);
1128
1129 rv = callback.WaitForResult();
1130 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1131
1132 const HttpResponseInfo* response = trans->GetResponseInfo();
1133 EXPECT_TRUE(response == NULL);
1134 }
1135
1136 // What do various browsers do when the server closes a non-keepalive
1137 // connection without sending any response header or body?
1138 //
1139 // IE7: error page
1140 // Safari 3.1.2 (Windows): error page
1141 // Firefox 3.0.1: blank page
1142 // Opera 9.52: after five attempts, blank page
1143 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1144 // Us: error page (EMPTY_RESPONSE)
1145 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1146 MockRead data_reads[] = {
1147 MockRead(SYNCHRONOUS, OK), // EOF
1148 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1149 MockRead("hello world"),
1150 MockRead(SYNCHRONOUS, OK),
1151 };
1152 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1153 arraysize(data_reads));
1154 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1155 }
1156
1157 // Test that we correctly reuse a keep-alive connection after not explicitly
1158 // reading the body.
1159 TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1160 HttpRequestInfo request;
1161 request.method = "GET";
1162 request.url = GURL("http://www.foo.com/");
1163 request.load_flags = 0;
1164
1165 SessionDependencies session_deps;
1166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1167
1168 // Note that because all these reads happen in the same
1169 // StaticSocketDataProvider, it shows that the same socket is being reused for
1170 // all transactions.
1171 MockRead data1_reads[] = {
1172 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1173 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1174 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1175 MockRead("HTTP/1.1 302 Found\r\n"
1176 "Content-Length: 0\r\n\r\n"),
1177 MockRead("HTTP/1.1 302 Found\r\n"
1178 "Content-Length: 5\r\n\r\n"
1179 "hello"),
1180 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1181 "Content-Length: 0\r\n\r\n"),
1182 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1183 "Content-Length: 5\r\n\r\n"
1184 "hello"),
1185 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1186 MockRead("hello"),
1187 };
1188 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1189 session_deps.socket_factory.AddSocketDataProvider(&data1);
1190
1191 MockRead data2_reads[] = {
1192 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1193 };
1194 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1195 session_deps.socket_factory.AddSocketDataProvider(&data2);
1196
1197 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1198 std::string response_lines[kNumUnreadBodies];
1199
1200 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1201 TestCompletionCallback callback;
1202
1203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1204
1205 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1206 EXPECT_EQ(ERR_IO_PENDING, rv);
1207
1208 rv = callback.WaitForResult();
1209 EXPECT_EQ(OK, rv);
1210
1211 const HttpResponseInfo* response = trans->GetResponseInfo();
1212 ASSERT_TRUE(response != NULL);
1213
1214 ASSERT_TRUE(response->headers != NULL);
1215 response_lines[i] = response->headers->GetStatusLine();
1216
1217 // We intentionally don't read the response bodies.
1218 }
1219
1220 const char* const kStatusLines[] = {
1221 "HTTP/1.1 204 No Content",
1222 "HTTP/1.1 205 Reset Content",
1223 "HTTP/1.1 304 Not Modified",
1224 "HTTP/1.1 302 Found",
1225 "HTTP/1.1 302 Found",
1226 "HTTP/1.1 301 Moved Permanently",
1227 "HTTP/1.1 301 Moved Permanently",
1228 };
1229
1230 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1231 forgot_to_update_kStatusLines);
1232
1233 for (int i = 0; i < kNumUnreadBodies; ++i)
1234 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1235
1236 TestCompletionCallback callback;
1237 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1238 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1239 EXPECT_EQ(ERR_IO_PENDING, rv);
1240 rv = callback.WaitForResult();
1241 EXPECT_EQ(OK, rv);
1242 const HttpResponseInfo* response = trans->GetResponseInfo();
1243 ASSERT_TRUE(response != NULL);
1244 ASSERT_TRUE(response->headers != NULL);
1245 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1246 std::string response_data;
1247 rv = ReadTransaction(trans.get(), &response_data);
1248 EXPECT_EQ(OK, rv);
1249 EXPECT_EQ("hello", response_data);
1250 }
1251
1252 // Test the request-challenge-retry sequence for basic auth.
1253 // (basic auth is the easiest to mock, because it has no randomness).
1254 TEST_F(HttpNetworkTransactionTest, BasicAuth) {
1255 HttpRequestInfo request;
1256 request.method = "GET";
1257 request.url = GURL("http://www.google.com/");
1258 request.load_flags = 0;
1259
1260 SessionDependencies session_deps;
1261 scoped_ptr<HttpTransaction> trans(
1262 new HttpNetworkTransaction(CreateSession(&session_deps)));
1263
1264 MockWrite data_writes1[] = {
1265 MockWrite("GET / HTTP/1.1\r\n"
1266 "Host: www.google.com\r\n"
1267 "Connection: keep-alive\r\n\r\n"),
1268 };
1269
1270 MockRead data_reads1[] = {
1271 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1272 // Give a couple authenticate options (only the middle one is actually
1273 // supported).
1274 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1275 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1276 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1278 // Large content-length -- won't matter, as connection will be reset.
1279 MockRead("Content-Length: 10000\r\n\r\n"),
1280 MockRead(SYNCHRONOUS, ERR_FAILED),
1281 };
1282
1283 // After calling trans->RestartWithAuth(), this is the request we should
1284 // be issuing -- the final header line contains the credentials.
1285 MockWrite data_writes2[] = {
1286 MockWrite("GET / HTTP/1.1\r\n"
1287 "Host: www.google.com\r\n"
1288 "Connection: keep-alive\r\n"
1289 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1290 };
1291
1292 // Lastly, the server responds with the actual content.
1293 MockRead data_reads2[] = {
1294 MockRead("HTTP/1.0 200 OK\r\n"),
1295 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1296 MockRead("Content-Length: 100\r\n\r\n"),
1297 MockRead(SYNCHRONOUS, OK),
1298 };
1299
1300 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1301 data_writes1, arraysize(data_writes1));
1302 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1303 data_writes2, arraysize(data_writes2));
1304 session_deps.socket_factory.AddSocketDataProvider(&data1);
1305 session_deps.socket_factory.AddSocketDataProvider(&data2);
1306
1307 TestCompletionCallback callback1;
1308
1309 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1310 EXPECT_EQ(ERR_IO_PENDING, rv);
1311
1312 rv = callback1.WaitForResult();
1313 EXPECT_EQ(OK, rv);
1314
1315 const HttpResponseInfo* response = trans->GetResponseInfo();
1316 ASSERT_TRUE(response != NULL);
1317 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1318
1319 TestCompletionCallback callback2;
1320
1321 rv = trans->RestartWithAuth(
1322 AuthCredentials(kFoo, kBar), callback2.callback());
1323 EXPECT_EQ(ERR_IO_PENDING, rv);
1324
1325 rv = callback2.WaitForResult();
1326 EXPECT_EQ(OK, rv);
1327
1328 response = trans->GetResponseInfo();
1329 ASSERT_TRUE(response != NULL);
1330 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1331 EXPECT_EQ(100, response->headers->GetContentLength());
1332 }
1333
1334 TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1335 HttpRequestInfo request;
1336 request.method = "GET";
1337 request.url = GURL("http://www.google.com/");
1338 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1339
1340 SessionDependencies session_deps;
1341 scoped_ptr<HttpTransaction> trans(
1342 new HttpNetworkTransaction(CreateSession(&session_deps)));
1343
1344 MockWrite data_writes[] = {
1345 MockWrite("GET / HTTP/1.1\r\n"
1346 "Host: www.google.com\r\n"
1347 "Connection: keep-alive\r\n\r\n"),
1348 };
1349
1350 MockRead data_reads[] = {
1351 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1352 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1354 // Large content-length -- won't matter, as connection will be reset.
1355 MockRead("Content-Length: 10000\r\n\r\n"),
1356 MockRead(SYNCHRONOUS, ERR_FAILED),
1357 };
1358
1359 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1360 data_writes, arraysize(data_writes));
1361 session_deps.socket_factory.AddSocketDataProvider(&data);
1362 TestCompletionCallback callback;
1363
1364 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1365 EXPECT_EQ(ERR_IO_PENDING, rv);
1366
1367 rv = callback.WaitForResult();
1368 EXPECT_EQ(0, rv);
1369
1370 const HttpResponseInfo* response = trans->GetResponseInfo();
1371 ASSERT_TRUE(response != NULL);
1372 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1373 }
1374
1375 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1376 // connection.
1377 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1378 HttpRequestInfo request;
1379 request.method = "GET";
1380 request.url = GURL("http://www.google.com/");
1381 request.load_flags = 0;
1382
1383 SessionDependencies session_deps;
1384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1385
1386 MockWrite data_writes1[] = {
1387 MockWrite("GET / HTTP/1.1\r\n"
1388 "Host: www.google.com\r\n"
1389 "Connection: keep-alive\r\n\r\n"),
1390
1391 // After calling trans->RestartWithAuth(), this is the request we should
1392 // be issuing -- the final header line contains the credentials.
1393 MockWrite("GET / HTTP/1.1\r\n"
1394 "Host: www.google.com\r\n"
1395 "Connection: keep-alive\r\n"
1396 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1397 };
1398
1399 MockRead data_reads1[] = {
1400 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1401 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1403 MockRead("Content-Length: 14\r\n\r\n"),
1404 MockRead("Unauthorized\r\n"),
1405
1406 // Lastly, the server responds with the actual content.
1407 MockRead("HTTP/1.1 200 OK\r\n"),
1408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1409 MockRead("Content-Length: 5\r\n\r\n"),
1410 MockRead("Hello"),
1411 };
1412
1413 // If there is a regression where we disconnect a Keep-Alive
1414 // connection during an auth roundtrip, we'll end up reading this.
1415 MockRead data_reads2[] = {
1416 MockRead(SYNCHRONOUS, ERR_FAILED),
1417 };
1418
1419 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1420 data_writes1, arraysize(data_writes1));
1421 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1422 NULL, 0);
1423 session_deps.socket_factory.AddSocketDataProvider(&data1);
1424 session_deps.socket_factory.AddSocketDataProvider(&data2);
1425
1426 TestCompletionCallback callback1;
1427
1428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1429 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1430 EXPECT_EQ(ERR_IO_PENDING, rv);
1431
1432 rv = callback1.WaitForResult();
1433 EXPECT_EQ(OK, rv);
1434
1435 const HttpResponseInfo* response = trans->GetResponseInfo();
1436 ASSERT_TRUE(response != NULL);
1437 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1438
1439 TestCompletionCallback callback2;
1440
1441 rv = trans->RestartWithAuth(
1442 AuthCredentials(kFoo, kBar), callback2.callback());
1443 EXPECT_EQ(ERR_IO_PENDING, rv);
1444
1445 rv = callback2.WaitForResult();
1446 EXPECT_EQ(OK, rv);
1447
1448 response = trans->GetResponseInfo();
1449 ASSERT_TRUE(response != NULL);
1450 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1451 EXPECT_EQ(5, response->headers->GetContentLength());
1452 }
1453
1454 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1455 // connection and with no response body to drain.
1456 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
1457 HttpRequestInfo request;
1458 request.method = "GET";
1459 request.url = GURL("http://www.google.com/");
1460 request.load_flags = 0;
1461
1462 SessionDependencies session_deps;
1463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1464
1465 MockWrite data_writes1[] = {
1466 MockWrite("GET / HTTP/1.1\r\n"
1467 "Host: www.google.com\r\n"
1468 "Connection: keep-alive\r\n\r\n"),
1469
1470 // After calling trans->RestartWithAuth(), this is the request we should
1471 // be issuing -- the final header line contains the credentials.
1472 MockWrite("GET / HTTP/1.1\r\n"
1473 "Host: www.google.com\r\n"
1474 "Connection: keep-alive\r\n"
1475 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1476 };
1477
1478 MockRead data_reads1[] = {
1479 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1480 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1481 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
1482
1483 // Lastly, the server responds with the actual content.
1484 MockRead("HTTP/1.1 200 OK\r\n"),
1485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1486 MockRead("Content-Length: 5\r\n\r\n"),
1487 MockRead("hello"),
1488 };
1489
1490 // An incorrect reconnect would cause this to be read.
1491 MockRead data_reads2[] = {
1492 MockRead(SYNCHRONOUS, ERR_FAILED),
1493 };
1494
1495 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1496 data_writes1, arraysize(data_writes1));
1497 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1498 NULL, 0);
1499 session_deps.socket_factory.AddSocketDataProvider(&data1);
1500 session_deps.socket_factory.AddSocketDataProvider(&data2);
1501
1502 TestCompletionCallback callback1;
1503
1504 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1505 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1506 EXPECT_EQ(ERR_IO_PENDING, rv);
1507
1508 rv = callback1.WaitForResult();
1509 EXPECT_EQ(OK, rv);
1510
1511 const HttpResponseInfo* response = trans->GetResponseInfo();
1512 ASSERT_TRUE(response != NULL);
1513 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1514
1515 TestCompletionCallback callback2;
1516
1517 rv = trans->RestartWithAuth(
1518 AuthCredentials(kFoo, kBar), callback2.callback());
1519 EXPECT_EQ(ERR_IO_PENDING, rv);
1520
1521 rv = callback2.WaitForResult();
1522 EXPECT_EQ(OK, rv);
1523
1524 response = trans->GetResponseInfo();
1525 ASSERT_TRUE(response != NULL);
1526 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1527 EXPECT_EQ(5, response->headers->GetContentLength());
1528 }
1529
1530 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1531 // connection and with a large response body to drain.
1532 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
1533 HttpRequestInfo request;
1534 request.method = "GET";
1535 request.url = GURL("http://www.google.com/");
1536 request.load_flags = 0;
1537
1538 SessionDependencies session_deps;
1539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1540
1541 MockWrite data_writes1[] = {
1542 MockWrite("GET / HTTP/1.1\r\n"
1543 "Host: www.google.com\r\n"
1544 "Connection: keep-alive\r\n\r\n"),
1545
1546 // After calling trans->RestartWithAuth(), this is the request we should
1547 // be issuing -- the final header line contains the credentials.
1548 MockWrite("GET / HTTP/1.1\r\n"
1549 "Host: www.google.com\r\n"
1550 "Connection: keep-alive\r\n"
1551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1552 };
1553
1554 // Respond with 5 kb of response body.
1555 std::string large_body_string("Unauthorized");
1556 large_body_string.append(5 * 1024, ' ');
1557 large_body_string.append("\r\n");
1558
1559 MockRead data_reads1[] = {
1560 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1563 // 5134 = 12 + 5 * 1024 + 2
1564 MockRead("Content-Length: 5134\r\n\r\n"),
1565 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
1566
1567 // Lastly, the server responds with the actual content.
1568 MockRead("HTTP/1.1 200 OK\r\n"),
1569 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1570 MockRead("Content-Length: 5\r\n\r\n"),
1571 MockRead("hello"),
1572 };
1573
1574 // An incorrect reconnect would cause this to be read.
1575 MockRead data_reads2[] = {
1576 MockRead(SYNCHRONOUS, ERR_FAILED),
1577 };
1578
1579 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1580 data_writes1, arraysize(data_writes1));
1581 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1582 NULL, 0);
1583 session_deps.socket_factory.AddSocketDataProvider(&data1);
1584 session_deps.socket_factory.AddSocketDataProvider(&data2);
1585
1586 TestCompletionCallback callback1;
1587
1588 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1589 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1590 EXPECT_EQ(ERR_IO_PENDING, rv);
1591
1592 rv = callback1.WaitForResult();
1593 EXPECT_EQ(OK, rv);
1594
1595 const HttpResponseInfo* response = trans->GetResponseInfo();
1596 ASSERT_TRUE(response != NULL);
1597 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1598
1599 TestCompletionCallback callback2;
1600
1601 rv = trans->RestartWithAuth(
1602 AuthCredentials(kFoo, kBar), callback2.callback());
1603 EXPECT_EQ(ERR_IO_PENDING, rv);
1604
1605 rv = callback2.WaitForResult();
1606 EXPECT_EQ(OK, rv);
1607
1608 response = trans->GetResponseInfo();
1609 ASSERT_TRUE(response != NULL);
1610 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1611 EXPECT_EQ(5, response->headers->GetContentLength());
1612 }
1613
1614 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1615 // connection, but the server gets impatient and closes the connection.
1616 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1617 HttpRequestInfo request;
1618 request.method = "GET";
1619 request.url = GURL("http://www.google.com/");
1620 request.load_flags = 0;
1621
1622 SessionDependencies session_deps;
1623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1624
1625 MockWrite data_writes1[] = {
1626 MockWrite("GET / HTTP/1.1\r\n"
1627 "Host: www.google.com\r\n"
1628 "Connection: keep-alive\r\n\r\n"),
1629 // This simulates the seemingly successful write to a closed connection
1630 // if the bug is not fixed.
1631 MockWrite("GET / HTTP/1.1\r\n"
1632 "Host: www.google.com\r\n"
1633 "Connection: keep-alive\r\n"
1634 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1635 };
1636
1637 MockRead data_reads1[] = {
1638 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1639 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1640 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1641 MockRead("Content-Length: 14\r\n\r\n"),
1642 // Tell MockTCPClientSocket to simulate the server closing the connection.
1643 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1644 MockRead("Unauthorized\r\n"),
1645 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
1646 };
1647
1648 // After calling trans->RestartWithAuth(), this is the request we should
1649 // be issuing -- the final header line contains the credentials.
1650 MockWrite data_writes2[] = {
1651 MockWrite("GET / HTTP/1.1\r\n"
1652 "Host: www.google.com\r\n"
1653 "Connection: keep-alive\r\n"
1654 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1655 };
1656
1657 // Lastly, the server responds with the actual content.
1658 MockRead data_reads2[] = {
1659 MockRead("HTTP/1.1 200 OK\r\n"),
1660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1661 MockRead("Content-Length: 5\r\n\r\n"),
1662 MockRead("hello"),
1663 };
1664
1665 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1666 data_writes1, arraysize(data_writes1));
1667 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1668 data_writes2, arraysize(data_writes2));
1669 session_deps.socket_factory.AddSocketDataProvider(&data1);
1670 session_deps.socket_factory.AddSocketDataProvider(&data2);
1671
1672 TestCompletionCallback callback1;
1673
1674 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1675 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1676 EXPECT_EQ(ERR_IO_PENDING, rv);
1677
1678 rv = callback1.WaitForResult();
1679 EXPECT_EQ(OK, rv);
1680
1681 const HttpResponseInfo* response = trans->GetResponseInfo();
1682 ASSERT_TRUE(response != NULL);
1683 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1684
1685 TestCompletionCallback callback2;
1686
1687 rv = trans->RestartWithAuth(
1688 AuthCredentials(kFoo, kBar), callback2.callback());
1689 EXPECT_EQ(ERR_IO_PENDING, rv);
1690
1691 rv = callback2.WaitForResult();
1692 EXPECT_EQ(OK, rv);
1693
1694 response = trans->GetResponseInfo();
1695 ASSERT_TRUE(response != NULL);
1696 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1697 EXPECT_EQ(5, response->headers->GetContentLength());
1698 }
1699
1700 // Test the request-challenge-retry sequence for basic auth, over a connection
1701 // that requires a restart when setting up an SSL tunnel.
1702 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1703 HttpRequestInfo request;
1704 request.method = "GET";
1705 request.url = GURL("https://www.google.com/");
1706 // when the no authentication data flag is set.
1707 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1708
1709 // Configure against proxy server "myproxy:70".
1710 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1711 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1712 session_deps.net_log = log.bound().net_log();
1713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1714
1715 // Since we have proxy, should try to establish tunnel.
1716 MockWrite data_writes1[] = {
1717 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1718 "Host: www.google.com\r\n"
1719 "Proxy-Connection: keep-alive\r\n\r\n"),
1720
1721 // After calling trans->RestartWithAuth(), this is the request we should
1722 // be issuing -- the final header line contains the credentials.
1723 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1724 "Host: www.google.com\r\n"
1725 "Proxy-Connection: keep-alive\r\n"
1726 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1727
1728 MockWrite("GET / HTTP/1.1\r\n"
1729 "Host: www.google.com\r\n"
1730 "Connection: keep-alive\r\n\r\n"),
1731 };
1732
1733 // The proxy responds to the connect with a 407, using a persistent
1734 // connection.
1735 MockRead data_reads1[] = {
1736 // No credentials.
1737 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1738 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1739 MockRead("Proxy-Connection: close\r\n\r\n"),
1740
1741 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1742
1743 MockRead("HTTP/1.1 200 OK\r\n"),
1744 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1745 MockRead("Content-Length: 5\r\n\r\n"),
1746 MockRead(SYNCHRONOUS, "hello"),
1747 };
1748
1749 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1750 data_writes1, arraysize(data_writes1));
1751 session_deps.socket_factory.AddSocketDataProvider(&data1);
1752 SSLSocketDataProvider ssl(ASYNC, OK);
1753 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1754
1755 TestCompletionCallback callback1;
1756
1757 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1758
1759 int rv = trans->Start(&request, callback1.callback(), log.bound());
1760 EXPECT_EQ(ERR_IO_PENDING, rv);
1761
1762 rv = callback1.WaitForResult();
1763 EXPECT_EQ(OK, rv);
1764 net::CapturingNetLog::EntryList entries;
1765 log.GetEntries(&entries);
1766 size_t pos = ExpectLogContainsSomewhere(
1767 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1768 NetLog::PHASE_NONE);
1769 ExpectLogContainsSomewhere(
1770 entries, pos,
1771 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1772 NetLog::PHASE_NONE);
1773
1774 const HttpResponseInfo* response = trans->GetResponseInfo();
1775 ASSERT_TRUE(response != NULL);
1776 ASSERT_FALSE(response->headers == NULL);
1777 EXPECT_EQ(407, response->headers->response_code());
1778 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1779 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
1780
1781 TestCompletionCallback callback2;
1782
1783 rv = trans->RestartWithAuth(
1784 AuthCredentials(kFoo, kBar), callback2.callback());
1785 EXPECT_EQ(ERR_IO_PENDING, rv);
1786
1787 rv = callback2.WaitForResult();
1788 EXPECT_EQ(OK, rv);
1789
1790 response = trans->GetResponseInfo();
1791 ASSERT_TRUE(response != NULL);
1792
1793 EXPECT_TRUE(response->headers->IsKeepAlive());
1794 EXPECT_EQ(200, response->headers->response_code());
1795 EXPECT_EQ(5, response->headers->GetContentLength());
1796 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1797
1798 // The password prompt info should not be set.
1799 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1800
1801 trans.reset();
1802 session->CloseAllConnections();
1803 }
1804
1805 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1806 // proxy connection, when setting up an SSL tunnel.
1807 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1808 HttpRequestInfo request;
1809 request.method = "GET";
1810 request.url = GURL("https://www.google.com/");
1811 // Ensure that proxy authentication is attempted even
1812 // when the no authentication data flag is set.
1813 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1814
1815 // Configure against proxy server "myproxy:70".
1816 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1817 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1818 session_deps.net_log = log.bound().net_log();
1819 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1820
1821 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1822
1823 // Since we have proxy, should try to establish tunnel.
1824 MockWrite data_writes1[] = {
1825 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1826 "Host: www.google.com\r\n"
1827 "Proxy-Connection: keep-alive\r\n\r\n"),
1828
1829 // After calling trans->RestartWithAuth(), this is the request we should
1830 // be issuing -- the final header line contains the credentials.
1831 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1832 "Host: www.google.com\r\n"
1833 "Proxy-Connection: keep-alive\r\n"
1834 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1835 };
1836
1837 // The proxy responds to the connect with a 407, using a persistent
1838 // connection.
1839 MockRead data_reads1[] = {
1840 // No credentials.
1841 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1842 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1843 MockRead("Content-Length: 10\r\n\r\n"),
1844 MockRead("0123456789"),
1845
1846 // Wrong credentials (wrong password).
1847 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1848 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1849 MockRead("Content-Length: 10\r\n\r\n"),
1850 // No response body because the test stops reading here.
1851 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1852 };
1853
1854 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1855 data_writes1, arraysize(data_writes1));
1856 session_deps.socket_factory.AddSocketDataProvider(&data1);
1857
1858 TestCompletionCallback callback1;
1859
1860 int rv = trans->Start(&request, callback1.callback(), log.bound());
1861 EXPECT_EQ(ERR_IO_PENDING, rv);
1862
1863 rv = callback1.WaitForResult();
1864 EXPECT_EQ(OK, rv);
1865 net::CapturingNetLog::EntryList entries;
1866 log.GetEntries(&entries);
1867 size_t pos = ExpectLogContainsSomewhere(
1868 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1869 NetLog::PHASE_NONE);
1870 ExpectLogContainsSomewhere(
1871 entries, pos,
1872 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1873 NetLog::PHASE_NONE);
1874
1875 const HttpResponseInfo* response = trans->GetResponseInfo();
1876 ASSERT_TRUE(response != NULL);
1877 ASSERT_FALSE(response->headers == NULL);
1878 EXPECT_TRUE(response->headers->IsKeepAlive());
1879 EXPECT_EQ(407, response->headers->response_code());
1880 EXPECT_EQ(10, response->headers->GetContentLength());
1881 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1882 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
1883
1884 TestCompletionCallback callback2;
1885
1886 // Wrong password (should be "bar").
1887 rv = trans->RestartWithAuth(
1888 AuthCredentials(kFoo, kBaz), callback2.callback());
1889 EXPECT_EQ(ERR_IO_PENDING, rv);
1890
1891 rv = callback2.WaitForResult();
1892 EXPECT_EQ(OK, rv);
1893
1894 response = trans->GetResponseInfo();
1895 ASSERT_TRUE(response != NULL);
1896 ASSERT_FALSE(response->headers == NULL);
1897 EXPECT_TRUE(response->headers->IsKeepAlive());
1898 EXPECT_EQ(407, response->headers->response_code());
1899 EXPECT_EQ(10, response->headers->GetContentLength());
1900 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1901 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
1902
1903 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1904 // out of scope.
1905 session->CloseAllConnections();
1906 }
1907
1908 // Test that we don't read the response body when we fail to establish a tunnel,
1909 // even if the user cancels the proxy's auth attempt.
1910 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1911 HttpRequestInfo request;
1912 request.method = "GET";
1913 request.url = GURL("https://www.google.com/");
1914 request.load_flags = 0;
1915
1916 // Configure against proxy server "myproxy:70".
1917 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1918
1919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1920
1921 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1922
1923 // Since we have proxy, should try to establish tunnel.
1924 MockWrite data_writes[] = {
1925 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1926 "Host: www.google.com\r\n"
1927 "Proxy-Connection: keep-alive\r\n\r\n"),
1928 };
1929
1930 // The proxy responds to the connect with a 407.
1931 MockRead data_reads[] = {
1932 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1933 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1934 MockRead("Content-Length: 10\r\n\r\n"),
1935 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1936 };
1937
1938 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1939 data_writes, arraysize(data_writes));
1940 session_deps.socket_factory.AddSocketDataProvider(&data);
1941
1942 TestCompletionCallback callback;
1943
1944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1945 EXPECT_EQ(ERR_IO_PENDING, rv);
1946
1947 rv = callback.WaitForResult();
1948 EXPECT_EQ(OK, rv);
1949
1950 const HttpResponseInfo* response = trans->GetResponseInfo();
1951 ASSERT_TRUE(response != NULL);
1952
1953 EXPECT_TRUE(response->headers->IsKeepAlive());
1954 EXPECT_EQ(407, response->headers->response_code());
1955 EXPECT_EQ(10, response->headers->GetContentLength());
1956 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1957
1958 std::string response_data;
1959 rv = ReadTransaction(trans.get(), &response_data);
1960 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
1961
1962 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1963 session->CloseAllConnections();
1964 }
1965
1966 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1967 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1968 TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1969 HttpRequestInfo request;
1970 request.method = "GET";
1971 request.url = GURL("http://www.google.com/");
1972 request.load_flags = 0;
1973
1974 // We are using a DIRECT connection (i.e. no proxy) for this session.
1975 SessionDependencies session_deps;
1976 scoped_ptr<HttpTransaction> trans(
1977 new HttpNetworkTransaction(CreateSession(&session_deps)));
1978
1979 MockWrite data_writes1[] = {
1980 MockWrite("GET / HTTP/1.1\r\n"
1981 "Host: www.google.com\r\n"
1982 "Connection: keep-alive\r\n\r\n"),
1983 };
1984
1985 MockRead data_reads1[] = {
1986 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1987 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1988 // Large content-length -- won't matter, as connection will be reset.
1989 MockRead("Content-Length: 10000\r\n\r\n"),
1990 MockRead(SYNCHRONOUS, ERR_FAILED),
1991 };
1992
1993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1994 data_writes1, arraysize(data_writes1));
1995 session_deps.socket_factory.AddSocketDataProvider(&data1);
1996
1997 TestCompletionCallback callback;
1998
1999 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2000 EXPECT_EQ(ERR_IO_PENDING, rv);
2001
2002 rv = callback.WaitForResult();
2003 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2004 }
2005
2006 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2007 // through a non-authenticating proxy. The request should fail with
2008 // ERR_UNEXPECTED_PROXY_AUTH.
2009 // Note that it is impossible to detect if an HTTP server returns a 407 through
2010 // a non-authenticating proxy - there is nothing to indicate whether the
2011 // response came from the proxy or the server, so it is treated as if the proxy
2012 // issued the challenge.
2013 TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
2014 HttpRequestInfo request;
2015 request.method = "GET";
2016 request.url = GURL("https://www.google.com/");
2017
2018 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2019 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2020 session_deps.net_log = log.bound().net_log();
2021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2022
2023 // Since we have proxy, should try to establish tunnel.
2024 MockWrite data_writes1[] = {
2025 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2026 "Host: www.google.com\r\n"
2027 "Proxy-Connection: keep-alive\r\n\r\n"),
2028
2029 MockWrite("GET / HTTP/1.1\r\n"
2030 "Host: www.google.com\r\n"
2031 "Connection: keep-alive\r\n\r\n"),
2032 };
2033
2034 MockRead data_reads1[] = {
2035 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2036
2037 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2038 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2039 MockRead("\r\n"),
2040 MockRead(SYNCHRONOUS, OK),
2041 };
2042
2043 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2044 data_writes1, arraysize(data_writes1));
2045 session_deps.socket_factory.AddSocketDataProvider(&data1);
2046 SSLSocketDataProvider ssl(ASYNC, OK);
2047 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2048
2049 TestCompletionCallback callback1;
2050
2051 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2052
2053 int rv = trans->Start(&request, callback1.callback(), log.bound());
2054 EXPECT_EQ(ERR_IO_PENDING, rv);
2055
2056 rv = callback1.WaitForResult();
2057 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2058 net::CapturingNetLog::EntryList entries;
2059 log.GetEntries(&entries);
2060 size_t pos = ExpectLogContainsSomewhere(
2061 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2062 NetLog::PHASE_NONE);
2063 ExpectLogContainsSomewhere(
2064 entries, pos,
2065 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2066 NetLog::PHASE_NONE);
2067 }
2068
2069 // Test a simple get through an HTTPS Proxy.
2070 TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
2071 HttpRequestInfo request;
2072 request.method = "GET";
2073 request.url = GURL("http://www.google.com/");
2074
2075 // Configure against https proxy server "proxy:70".
2076 SessionDependencies session_deps(ProxyService::CreateFixed(
2077 "https://proxy:70"));
2078 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2079 session_deps.net_log = log.bound().net_log();
2080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2081
2082 // Since we have proxy, should use full url
2083 MockWrite data_writes1[] = {
2084 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2085 "Host: www.google.com\r\n"
2086 "Proxy-Connection: keep-alive\r\n\r\n"),
2087 };
2088
2089 MockRead data_reads1[] = {
2090 MockRead("HTTP/1.1 200 OK\r\n"),
2091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2092 MockRead("Content-Length: 100\r\n\r\n"),
2093 MockRead(SYNCHRONOUS, OK),
2094 };
2095
2096 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2097 data_writes1, arraysize(data_writes1));
2098 session_deps.socket_factory.AddSocketDataProvider(&data1);
2099 SSLSocketDataProvider ssl(ASYNC, OK);
2100 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2101
2102 TestCompletionCallback callback1;
2103
2104 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2105
2106 int rv = trans->Start(&request, callback1.callback(), log.bound());
2107 EXPECT_EQ(ERR_IO_PENDING, rv);
2108
2109 rv = callback1.WaitForResult();
2110 EXPECT_EQ(OK, rv);
2111
2112 const HttpResponseInfo* response = trans->GetResponseInfo();
2113 ASSERT_TRUE(response != NULL);
2114
2115 EXPECT_TRUE(response->headers->IsKeepAlive());
2116 EXPECT_EQ(200, response->headers->response_code());
2117 EXPECT_EQ(100, response->headers->GetContentLength());
2118 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2119
2120 // The password prompt info should not be set.
2121 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2122 }
2123
2124 // Test a SPDY get through an HTTPS Proxy.
2125 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2126 HttpRequestInfo request;
2127 request.method = "GET";
2128 request.url = GURL("http://www.google.com/");
2129 request.load_flags = 0;
2130
2131 // Configure against https proxy server "proxy:70".
2132 SessionDependencies session_deps(ProxyService::CreateFixed(
2133 "https://proxy:70"));
2134 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2135 session_deps.net_log = log.bound().net_log();
2136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2137
2138 // fetch http://www.google.com/ via SPDY
2139 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
2140 false));
2141 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2142
2143 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2144 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2145 MockRead spdy_reads[] = {
2146 CreateMockRead(*resp),
2147 CreateMockRead(*data),
2148 MockRead(ASYNC, 0, 0),
2149 };
2150
2151 scoped_ptr<DelayedSocketData> spdy_data(
2152 new DelayedSocketData(
2153 1, // wait for one write to finish before reading.
2154 spdy_reads, arraysize(spdy_reads),
2155 spdy_writes, arraysize(spdy_writes)));
2156 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
2157
2158 SSLSocketDataProvider ssl(ASYNC, OK);
2159 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
2160 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2161
2162 TestCompletionCallback callback1;
2163
2164 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2165
2166 int rv = trans->Start(&request, callback1.callback(), log.bound());
2167 EXPECT_EQ(ERR_IO_PENDING, rv);
2168
2169 rv = callback1.WaitForResult();
2170 EXPECT_EQ(OK, rv);
2171
2172 const HttpResponseInfo* response = trans->GetResponseInfo();
2173 ASSERT_TRUE(response != NULL);
2174 ASSERT_TRUE(response->headers != NULL);
2175 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2176
2177 std::string response_data;
2178 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2179 EXPECT_EQ(net::kUploadData, response_data);
2180 }
2181
2182 // Test a SPDY get through an HTTPS Proxy.
2183 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
2184 HttpRequestInfo request;
2185 request.method = "GET";
2186 request.url = GURL("http://www.google.com/");
2187 request.load_flags = 0;
2188
2189 // Configure against https proxy server "myproxy:70".
2190 SessionDependencies session_deps(
2191 ProxyService::CreateFixed("https://myproxy:70"));
2192 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2193 session_deps.net_log = log.bound().net_log();
2194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2195
2196 // The first request will be a bare GET, the second request will be a
2197 // GET with a Proxy-Authorization header.
2198 scoped_ptr<spdy::SpdyFrame> req_get(
2199 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2200 const char* const kExtraAuthorizationHeaders[] = {
2201 "proxy-authorization",
2202 "Basic Zm9vOmJhcg==",
2203 };
2204 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2205 ConstructSpdyGet(
2206 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2207 false, 3, LOWEST, false));
2208 MockWrite spdy_writes[] = {
2209 CreateMockWrite(*req_get, 1),
2210 CreateMockWrite(*req_get_authorization, 4),
2211 };
2212
2213 // The first response is a 407 proxy authentication challenge, and the second
2214 // response will be a 200 response since the second request includes a valid
2215 // Authorization header.
2216 const char* const kExtraAuthenticationHeaders[] = {
2217 "proxy-authenticate",
2218 "Basic realm=\"MyRealm1\""
2219 };
2220 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2221 ConstructSpdySynReplyError(
2222 "407 Proxy Authentication Required",
2223 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2224 1));
2225 scoped_ptr<spdy::SpdyFrame> body_authentication(
2226 ConstructSpdyBodyFrame(1, true));
2227 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2228 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2229 MockRead spdy_reads[] = {
2230 CreateMockRead(*resp_authentication, 2),
2231 CreateMockRead(*body_authentication, 3),
2232 CreateMockRead(*resp_data, 5),
2233 CreateMockRead(*body_data, 6),
2234 MockRead(ASYNC, 0, 7),
2235 };
2236
2237 scoped_ptr<OrderedSocketData> data(
2238 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2239 spdy_writes, arraysize(spdy_writes)));
2240 session_deps.socket_factory.AddSocketDataProvider(data.get());
2241
2242 SSLSocketDataProvider ssl(ASYNC, OK);
2243 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
2244 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2245
2246 TestCompletionCallback callback1;
2247
2248 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2249
2250 int rv = trans->Start(&request, callback1.callback(), log.bound());
2251 EXPECT_EQ(ERR_IO_PENDING, rv);
2252
2253 rv = callback1.WaitForResult();
2254 EXPECT_EQ(OK, rv);
2255
2256 const HttpResponseInfo* const response = trans->GetResponseInfo();
2257
2258 ASSERT_TRUE(response != NULL);
2259 ASSERT_TRUE(response->headers != NULL);
2260 EXPECT_EQ(407, response->headers->response_code());
2261 EXPECT_TRUE(response->was_fetched_via_spdy);
2262 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2263
2264 TestCompletionCallback callback2;
2265
2266 rv = trans->RestartWithAuth(
2267 AuthCredentials(kFoo, kBar), callback2.callback());
2268 EXPECT_EQ(ERR_IO_PENDING, rv);
2269
2270 rv = callback2.WaitForResult();
2271 EXPECT_EQ(OK, rv);
2272
2273 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2274
2275 ASSERT_TRUE(response_restart != NULL);
2276 ASSERT_TRUE(response_restart->headers != NULL);
2277 EXPECT_EQ(200, response_restart->headers->response_code());
2278 // The password prompt info should not be set.
2279 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2280 }
2281
2282 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2283 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2284 HttpRequestInfo request;
2285 request.method = "GET";
2286 request.url = GURL("https://www.google.com/");
2287 request.load_flags = 0;
2288
2289 // Configure against https proxy server "proxy:70".
2290 SessionDependencies session_deps(ProxyService::CreateFixed(
2291 "https://proxy:70"));
2292 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2293 session_deps.net_log = log.bound().net_log();
2294 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2295
2296 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2297
2298 // CONNECT to www.google.com:443 via SPDY
2299 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2300 // fetch https://www.google.com/ via HTTP
2301
2302 const char get[] = "GET / HTTP/1.1\r\n"
2303 "Host: www.google.com\r\n"
2304 "Connection: keep-alive\r\n\r\n";
2305 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2306 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2307 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2308 const char resp[] = "HTTP/1.1 200 OK\r\n"
2309 "Content-Length: 10\r\n\r\n";
2310 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2311 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2312 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2313 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2314 scoped_ptr<spdy::SpdyFrame> window_update(
2315 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2316
2317 MockWrite spdy_writes[] = {
2318 CreateMockWrite(*connect, 1),
2319 CreateMockWrite(*wrapped_get, 3),
2320 CreateMockWrite(*window_update, 5)
2321 };
2322
2323 MockRead spdy_reads[] = {
2324 CreateMockRead(*conn_resp, 2, ASYNC),
2325 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2326 CreateMockRead(*wrapped_body, 6, ASYNC),
2327 CreateMockRead(*wrapped_body, 7, ASYNC),
2328 MockRead(ASYNC, 0, 8),
2329 };
2330
2331 scoped_ptr<OrderedSocketData> spdy_data(
2332 new OrderedSocketData(
2333 spdy_reads, arraysize(spdy_reads),
2334 spdy_writes, arraysize(spdy_writes)));
2335 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
2336
2337 SSLSocketDataProvider ssl(ASYNC, OK);
2338 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
2339 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2340 SSLSocketDataProvider ssl2(ASYNC, OK);
2341 ssl2.was_npn_negotiated = false;
2342 ssl2.protocol_negotiated = SSLClientSocket::kProtoUnknown;
2343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2344
2345 TestCompletionCallback callback1;
2346
2347 int rv = trans->Start(&request, callback1.callback(), log.bound());
2348 EXPECT_EQ(ERR_IO_PENDING, rv);
2349
2350 rv = callback1.WaitForResult();
2351 EXPECT_EQ(OK, rv);
2352
2353 const HttpResponseInfo* response = trans->GetResponseInfo();
2354 ASSERT_TRUE(response != NULL);
2355 ASSERT_TRUE(response->headers != NULL);
2356 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2357
2358 std::string response_data;
2359 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2360 EXPECT_EQ("1234567890", response_data);
2361 }
2362
2363 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2364 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2365 HttpRequestInfo request;
2366 request.method = "GET";
2367 request.url = GURL("https://www.google.com/");
2368 request.load_flags = 0;
2369
2370 // Configure against https proxy server "proxy:70".
2371 SessionDependencies session_deps(ProxyService::CreateFixed(
2372 "https://proxy:70"));
2373 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2374 session_deps.net_log = log.bound().net_log();
2375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2376
2377 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2378
2379 // CONNECT to www.google.com:443 via SPDY
2380 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2381 // fetch https://www.google.com/ via SPDY
2382 const char* const kMyUrl = "https://www.google.com/";
2383 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2384 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2385 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2386 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2387 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2388 ConstructWrappedSpdyFrame(get_resp, 1));
2389 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2390 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2391 scoped_ptr<spdy::SpdyFrame> window_update_get_resp(
2392 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2393 scoped_ptr<spdy::SpdyFrame> window_update_body(
2394 ConstructSpdyWindowUpdate(1, wrapped_body->length()));
2395
2396 MockWrite spdy_writes[] = {
2397 CreateMockWrite(*connect, 1),
2398 CreateMockWrite(*wrapped_get, 3),
2399 CreateMockWrite(*window_update_get_resp, 5),
2400 CreateMockWrite(*window_update_body, 7),
2401 };
2402
2403 MockRead spdy_reads[] = {
2404 CreateMockRead(*conn_resp, 2, ASYNC),
2405 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2406 CreateMockRead(*wrapped_body, 6, ASYNC),
2407 MockRead(ASYNC, 0, 8),
2408 };
2409
2410 scoped_ptr<OrderedSocketData> spdy_data(
2411 new OrderedSocketData(
2412 spdy_reads, arraysize(spdy_reads),
2413 spdy_writes, arraysize(spdy_writes)));
2414 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
2415
2416 SSLSocketDataProvider ssl(ASYNC, OK);
2417 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
2418 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2419 SSLSocketDataProvider ssl2(ASYNC, OK);
2420 ssl2.SetNextProto(SSLClientSocket::kProtoSPDY21);
2421 ssl2.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
2422 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2423
2424 TestCompletionCallback callback1;
2425
2426 int rv = trans->Start(&request, callback1.callback(), log.bound());
2427 EXPECT_EQ(ERR_IO_PENDING, rv);
2428
2429 rv = callback1.WaitForResult();
2430 EXPECT_EQ(OK, rv);
2431
2432 const HttpResponseInfo* response = trans->GetResponseInfo();
2433 ASSERT_TRUE(response != NULL);
2434 ASSERT_TRUE(response->headers != NULL);
2435 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2436
2437 std::string response_data;
2438 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2439 EXPECT_EQ(net::kUploadData, response_data);
2440 }
2441
2442 // Test a SPDY CONNECT failure through an HTTPS Proxy.
2443 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2444 HttpRequestInfo request;
2445 request.method = "GET";
2446 request.url = GURL("https://www.google.com/");
2447 request.load_flags = 0;
2448
2449 // Configure against https proxy server "proxy:70".
2450 SessionDependencies session_deps(ProxyService::CreateFixed(
2451 "https://proxy:70"));
2452 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2453 session_deps.net_log = log.bound().net_log();
2454 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2455
2456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2457
2458 // CONNECT to www.google.com:443 via SPDY
2459 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2460 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2461
2462 MockWrite spdy_writes[] = {
2463 CreateMockWrite(*connect, 1),
2464 CreateMockWrite(*get, 3),
2465 };
2466
2467 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2468 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2469 MockRead spdy_reads[] = {
2470 CreateMockRead(*resp, 2, ASYNC),
2471 MockRead(ASYNC, 0, 4),
2472 };
2473
2474 scoped_ptr<OrderedSocketData> spdy_data(
2475 new OrderedSocketData(
2476 spdy_reads, arraysize(spdy_reads),
2477 spdy_writes, arraysize(spdy_writes)));
2478 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
2479
2480 SSLSocketDataProvider ssl(ASYNC, OK);
2481 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
2482 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2483 SSLSocketDataProvider ssl2(ASYNC, OK);
2484 ssl2.SetNextProto(SSLClientSocket::kProtoSPDY21);
2485 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2486
2487 TestCompletionCallback callback1;
2488
2489 int rv = trans->Start(&request, callback1.callback(), log.bound());
2490 EXPECT_EQ(ERR_IO_PENDING, rv);
2491
2492 rv = callback1.WaitForResult();
2493 EXPECT_EQ(OK, rv);
2494
2495 const HttpResponseInfo* response = trans->GetResponseInfo();
2496 ASSERT_TRUE(response != NULL);
2497 EXPECT_EQ(500, response->headers->response_code());
2498 }
2499
2500 // Test the challenge-response-retry sequence through an HTTPS Proxy
2501 TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
2502 HttpRequestInfo request;
2503 request.method = "GET";
2504 request.url = GURL("http://www.google.com/");
2505 // when the no authentication data flag is set.
2506 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2507
2508 // Configure against https proxy server "myproxy:70".
2509 SessionDependencies session_deps(
2510 ProxyService::CreateFixed("https://myproxy:70"));
2511 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2512 session_deps.net_log = log.bound().net_log();
2513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2514
2515 // Since we have proxy, should use full url
2516 MockWrite data_writes1[] = {
2517 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2518 "Host: www.google.com\r\n"
2519 "Proxy-Connection: keep-alive\r\n\r\n"),
2520
2521 // After calling trans->RestartWithAuth(), this is the request we should
2522 // be issuing -- the final header line contains the credentials.
2523 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2524 "Host: www.google.com\r\n"
2525 "Proxy-Connection: keep-alive\r\n"
2526 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2527 };
2528
2529 // The proxy responds to the GET with a 407, using a persistent
2530 // connection.
2531 MockRead data_reads1[] = {
2532 // No credentials.
2533 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2534 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2535 MockRead("Proxy-Connection: keep-alive\r\n"),
2536 MockRead("Content-Length: 0\r\n\r\n"),
2537
2538 MockRead("HTTP/1.1 200 OK\r\n"),
2539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2540 MockRead("Content-Length: 100\r\n\r\n"),
2541 MockRead(SYNCHRONOUS, OK),
2542 };
2543
2544 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2545 data_writes1, arraysize(data_writes1));
2546 session_deps.socket_factory.AddSocketDataProvider(&data1);
2547 SSLSocketDataProvider ssl(ASYNC, OK);
2548 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2549
2550 TestCompletionCallback callback1;
2551
2552 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2553
2554 int rv = trans->Start(&request, callback1.callback(), log.bound());
2555 EXPECT_EQ(ERR_IO_PENDING, rv);
2556
2557 rv = callback1.WaitForResult();
2558 EXPECT_EQ(OK, rv);
2559
2560 const HttpResponseInfo* response = trans->GetResponseInfo();
2561 ASSERT_TRUE(response != NULL);
2562 ASSERT_FALSE(response->headers == NULL);
2563 EXPECT_EQ(407, response->headers->response_code());
2564 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2565 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2566
2567 TestCompletionCallback callback2;
2568
2569 rv = trans->RestartWithAuth(
2570 AuthCredentials(kFoo, kBar), callback2.callback());
2571 EXPECT_EQ(ERR_IO_PENDING, rv);
2572
2573 rv = callback2.WaitForResult();
2574 EXPECT_EQ(OK, rv);
2575
2576 response = trans->GetResponseInfo();
2577 ASSERT_TRUE(response != NULL);
2578
2579 EXPECT_TRUE(response->headers->IsKeepAlive());
2580 EXPECT_EQ(200, response->headers->response_code());
2581 EXPECT_EQ(100, response->headers->GetContentLength());
2582 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2583
2584 // The password prompt info should not be set.
2585 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2586 }
2587
2588 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
2589 const MockRead& status, int expected_status) {
2590 HttpRequestInfo request;
2591 request.method = "GET";
2592 request.url = GURL("https://www.google.com/");
2593 request.load_flags = 0;
2594
2595 // Configure against proxy server "myproxy:70".
2596 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2597
2598 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2599
2600 // Since we have proxy, should try to establish tunnel.
2601 MockWrite data_writes[] = {
2602 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2603 "Host: www.google.com\r\n"
2604 "Proxy-Connection: keep-alive\r\n\r\n"),
2605 };
2606
2607 MockRead data_reads[] = {
2608 status,
2609 MockRead("Content-Length: 10\r\n\r\n"),
2610 // No response body because the test stops reading here.
2611 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2612 };
2613
2614 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2615 data_writes, arraysize(data_writes));
2616 session_deps.socket_factory.AddSocketDataProvider(&data);
2617
2618 TestCompletionCallback callback;
2619
2620 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2621
2622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2623 EXPECT_EQ(ERR_IO_PENDING, rv);
2624
2625 rv = callback.WaitForResult();
2626 EXPECT_EQ(expected_status, rv);
2627 }
2628
2629 void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
2630 ConnectStatusHelperWithExpectedStatus(
2631 status, ERR_TUNNEL_CONNECTION_FAILED);
2632 }
2633
2634 TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2635 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2636 }
2637
2638 TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2639 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2640 }
2641
2642 TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2643 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2644 }
2645
2646 TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2647 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2648 }
2649
2650 TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2651 ConnectStatusHelper(
2652 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2653 }
2654
2655 TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2656 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2657 }
2658
2659 TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2660 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2661 }
2662
2663 TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2664 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2665 }
2666
2667 TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2668 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2669 }
2670
2671 TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2672 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2673 }
2674
2675 TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2676 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2677 }
2678
2679 TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2680 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2681 }
2682
2683 TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2684 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2685 }
2686
2687 TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2688 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2689 }
2690
2691 TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2692 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2693 }
2694
2695 TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2696 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2697 }
2698
2699 TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2700 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2701 }
2702
2703 TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2704 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2705 }
2706
2707 TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2708 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2709 }
2710
2711 TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2712 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2713 }
2714
2715 TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2716 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2717 }
2718
2719 TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2720 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2721 }
2722
2723 TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2724 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2725 }
2726
2727 TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2728 ConnectStatusHelperWithExpectedStatus(
2729 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2730 ERR_PROXY_AUTH_UNSUPPORTED);
2731 }
2732
2733 TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2734 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2735 }
2736
2737 TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2738 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2739 }
2740
2741 TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2742 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2743 }
2744
2745 TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2746 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2747 }
2748
2749 TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2750 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2751 }
2752
2753 TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2754 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2755 }
2756
2757 TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2758 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2759 }
2760
2761 TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2762 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2763 }
2764
2765 TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2766 ConnectStatusHelper(
2767 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2768 }
2769
2770 TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2771 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2772 }
2773
2774 TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2775 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2776 }
2777
2778 TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2779 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2780 }
2781
2782 TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2783 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2784 }
2785
2786 TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2787 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2788 }
2789
2790 TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2791 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2792 }
2793
2794 TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2795 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2796 }
2797
2798 // Test the flow when both the proxy server AND origin server require
2799 // authentication. Again, this uses basic auth for both since that is
2800 // the simplest to mock.
2801 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
2802 HttpRequestInfo request;
2803 request.method = "GET";
2804 request.url = GURL("http://www.google.com/");
2805 request.load_flags = 0;
2806
2807 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2808
2809 // Configure against proxy server "myproxy:70".
2810 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
2811 CreateSession(&session_deps)));
2812
2813 MockWrite data_writes1[] = {
2814 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2815 "Host: www.google.com\r\n"
2816 "Proxy-Connection: keep-alive\r\n\r\n"),
2817 };
2818
2819 MockRead data_reads1[] = {
2820 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2821 // Give a couple authenticate options (only the middle one is actually
2822 // supported).
2823 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
2824 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2825 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2826 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2827 // Large content-length -- won't matter, as connection will be reset.
2828 MockRead("Content-Length: 10000\r\n\r\n"),
2829 MockRead(SYNCHRONOUS, ERR_FAILED),
2830 };
2831
2832 // After calling trans->RestartWithAuth() the first time, this is the
2833 // request we should be issuing -- the final header line contains the
2834 // proxy's credentials.
2835 MockWrite data_writes2[] = {
2836 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2837 "Host: www.google.com\r\n"
2838 "Proxy-Connection: keep-alive\r\n"
2839 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2840 };
2841
2842 // Now the proxy server lets the request pass through to origin server.
2843 // The origin server responds with a 401.
2844 MockRead data_reads2[] = {
2845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2846 // Note: We are using the same realm-name as the proxy server. This is
2847 // completely valid, as realms are unique across hosts.
2848 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2849 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2850 MockRead("Content-Length: 2000\r\n\r\n"),
2851 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
2852 };
2853
2854 // After calling trans->RestartWithAuth() the second time, we should send
2855 // the credentials for both the proxy and origin server.
2856 MockWrite data_writes3[] = {
2857 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2858 "Host: www.google.com\r\n"
2859 "Proxy-Connection: keep-alive\r\n"
2860 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2861 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2862 };
2863
2864 // Lastly we get the desired content.
2865 MockRead data_reads3[] = {
2866 MockRead("HTTP/1.0 200 OK\r\n"),
2867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2868 MockRead("Content-Length: 100\r\n\r\n"),
2869 MockRead(SYNCHRONOUS, OK),
2870 };
2871
2872 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2873 data_writes1, arraysize(data_writes1));
2874 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2875 data_writes2, arraysize(data_writes2));
2876 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2877 data_writes3, arraysize(data_writes3));
2878 session_deps.socket_factory.AddSocketDataProvider(&data1);
2879 session_deps.socket_factory.AddSocketDataProvider(&data2);
2880 session_deps.socket_factory.AddSocketDataProvider(&data3);
2881
2882 TestCompletionCallback callback1;
2883
2884 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2885 EXPECT_EQ(ERR_IO_PENDING, rv);
2886
2887 rv = callback1.WaitForResult();
2888 EXPECT_EQ(OK, rv);
2889
2890 const HttpResponseInfo* response = trans->GetResponseInfo();
2891 ASSERT_TRUE(response != NULL);
2892 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2893
2894 TestCompletionCallback callback2;
2895
2896 rv = trans->RestartWithAuth(
2897 AuthCredentials(kFoo, kBar), callback2.callback());
2898 EXPECT_EQ(ERR_IO_PENDING, rv);
2899
2900 rv = callback2.WaitForResult();
2901 EXPECT_EQ(OK, rv);
2902
2903 response = trans->GetResponseInfo();
2904 ASSERT_TRUE(response != NULL);
2905 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2906
2907 TestCompletionCallback callback3;
2908
2909 rv = trans->RestartWithAuth(
2910 AuthCredentials(kFoo2, kBar2), callback3.callback());
2911 EXPECT_EQ(ERR_IO_PENDING, rv);
2912
2913 rv = callback3.WaitForResult();
2914 EXPECT_EQ(OK, rv);
2915
2916 response = trans->GetResponseInfo();
2917 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2918 EXPECT_EQ(100, response->headers->GetContentLength());
2919 }
2920
2921 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
2922 // can't hook into its internals to cause it to generate predictable NTLM
2923 // authorization headers.
2924 #if defined(NTLM_PORTABLE)
2925 // The NTLM authentication unit tests were generated by capturing the HTTP
2926 // requests and responses using Fiddler 2 and inspecting the generated random
2927 // bytes in the debugger.
2928
2929 // Enter the correct password and authenticate successfully.
2930 TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
2931 HttpRequestInfo request;
2932 request.method = "GET";
2933 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2934 request.load_flags = 0;
2935
2936 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2937 MockGetHostName);
2938 SessionDependencies session_deps;
2939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2940
2941 MockWrite data_writes1[] = {
2942 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2943 "Host: 172.22.68.17\r\n"
2944 "Connection: keep-alive\r\n\r\n"),
2945 };
2946
2947 MockRead data_reads1[] = {
2948 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2949 // Negotiate and NTLM are often requested together. However, we only want
2950 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2951 // the header that requests Negotiate for this test.
2952 MockRead("WWW-Authenticate: NTLM\r\n"),
2953 MockRead("Connection: close\r\n"),
2954 MockRead("Content-Length: 42\r\n"),
2955 MockRead("Content-Type: text/html\r\n\r\n"),
2956 // Missing content -- won't matter, as connection will be reset.
2957 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2958 };
2959
2960 MockWrite data_writes2[] = {
2961 // After restarting with a null identity, this is the
2962 // request we should be issuing -- the final header line contains a Type
2963 // 1 message.
2964 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2965 "Host: 172.22.68.17\r\n"
2966 "Connection: keep-alive\r\n"
2967 "Authorization: NTLM "
2968 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2969
2970 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2971 // (the credentials for the origin server). The second request continues
2972 // on the same connection.
2973 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2974 "Host: 172.22.68.17\r\n"
2975 "Connection: keep-alive\r\n"
2976 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2977 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2978 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2979 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2980 "ahlhx5I=\r\n\r\n"),
2981 };
2982
2983 MockRead data_reads2[] = {
2984 // The origin server responds with a Type 2 message.
2985 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2986 MockRead("WWW-Authenticate: NTLM "
2987 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
2988 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2989 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2990 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2991 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2992 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2993 "BtAAAAAAA=\r\n"),
2994 MockRead("Content-Length: 42\r\n"),
2995 MockRead("Content-Type: text/html\r\n\r\n"),
2996 MockRead("You are not authorized to view this page\r\n"),
2997
2998 // Lastly we get the desired content.
2999 MockRead("HTTP/1.1 200 OK\r\n"),
3000 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3001 MockRead("Content-Length: 13\r\n\r\n"),
3002 MockRead("Please Login\r\n"),
3003 MockRead(SYNCHRONOUS, OK),
3004 };
3005
3006 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3007 data_writes1, arraysize(data_writes1));
3008 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3009 data_writes2, arraysize(data_writes2));
3010 session_deps.socket_factory.AddSocketDataProvider(&data1);
3011 session_deps.socket_factory.AddSocketDataProvider(&data2);
3012
3013 TestCompletionCallback callback1;
3014
3015 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3016
3017 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3018 EXPECT_EQ(ERR_IO_PENDING, rv);
3019
3020 rv = callback1.WaitForResult();
3021 EXPECT_EQ(OK, rv);
3022
3023 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3024
3025 const HttpResponseInfo* response = trans->GetResponseInfo();
3026 ASSERT_FALSE(response == NULL);
3027 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
3028
3029 TestCompletionCallback callback2;
3030
3031 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
3032 callback2.callback());
3033 EXPECT_EQ(ERR_IO_PENDING, rv);
3034
3035 rv = callback2.WaitForResult();
3036 EXPECT_EQ(OK, rv);
3037
3038 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3039
3040 response = trans->GetResponseInfo();
3041 ASSERT_TRUE(response != NULL);
3042 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3043
3044 TestCompletionCallback callback3;
3045
3046 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
3047 EXPECT_EQ(ERR_IO_PENDING, rv);
3048
3049 rv = callback3.WaitForResult();
3050 EXPECT_EQ(OK, rv);
3051
3052 response = trans->GetResponseInfo();
3053 ASSERT_TRUE(response != NULL);
3054 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3055 EXPECT_EQ(13, response->headers->GetContentLength());
3056 }
3057
3058 // Enter a wrong password, and then the correct one.
3059 TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
3060 HttpRequestInfo request;
3061 request.method = "GET";
3062 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3063 request.load_flags = 0;
3064
3065 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3066 MockGetHostName);
3067 SessionDependencies session_deps;
3068 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3069
3070 MockWrite data_writes1[] = {
3071 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3072 "Host: 172.22.68.17\r\n"
3073 "Connection: keep-alive\r\n\r\n"),
3074 };
3075
3076 MockRead data_reads1[] = {
3077 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3078 // Negotiate and NTLM are often requested together. However, we only want
3079 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3080 // the header that requests Negotiate for this test.
3081 MockRead("WWW-Authenticate: NTLM\r\n"),
3082 MockRead("Connection: close\r\n"),
3083 MockRead("Content-Length: 42\r\n"),
3084 MockRead("Content-Type: text/html\r\n\r\n"),
3085 // Missing content -- won't matter, as connection will be reset.
3086 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
3087 };
3088
3089 MockWrite data_writes2[] = {
3090 // After restarting with a null identity, this is the
3091 // request we should be issuing -- the final header line contains a Type
3092 // 1 message.
3093 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3094 "Host: 172.22.68.17\r\n"
3095 "Connection: keep-alive\r\n"
3096 "Authorization: NTLM "
3097 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3098
3099 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3100 // (the credentials for the origin server). The second request continues
3101 // on the same connection.
3102 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3103 "Host: 172.22.68.17\r\n"
3104 "Connection: keep-alive\r\n"
3105 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3106 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3107 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3108 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3109 "4Ww7b7E=\r\n\r\n"),
3110 };
3111
3112 MockRead data_reads2[] = {
3113 // The origin server responds with a Type 2 message.
3114 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3115 MockRead("WWW-Authenticate: NTLM "
3116 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3117 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3118 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3119 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3120 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3121 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3122 "BtAAAAAAA=\r\n"),
3123 MockRead("Content-Length: 42\r\n"),
3124 MockRead("Content-Type: text/html\r\n\r\n"),
3125 MockRead("You are not authorized to view this page\r\n"),
3126
3127 // Wrong password.
3128 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3129 MockRead("WWW-Authenticate: NTLM\r\n"),
3130 MockRead("Connection: close\r\n"),
3131 MockRead("Content-Length: 42\r\n"),
3132 MockRead("Content-Type: text/html\r\n\r\n"),
3133 // Missing content -- won't matter, as connection will be reset.
3134 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
3135 };
3136
3137 MockWrite data_writes3[] = {
3138 // After restarting with a null identity, this is the
3139 // request we should be issuing -- the final header line contains a Type
3140 // 1 message.
3141 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3142 "Host: 172.22.68.17\r\n"
3143 "Connection: keep-alive\r\n"
3144 "Authorization: NTLM "
3145 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3146
3147 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3148 // (the credentials for the origin server). The second request continues
3149 // on the same connection.
3150 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3151 "Host: 172.22.68.17\r\n"
3152 "Connection: keep-alive\r\n"
3153 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3154 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3155 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3156 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3157 "+4MUm7c=\r\n\r\n"),
3158 };
3159
3160 MockRead data_reads3[] = {
3161 // The origin server responds with a Type 2 message.
3162 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3163 MockRead("WWW-Authenticate: NTLM "
3164 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3165 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3166 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3167 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3168 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3169 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3170 "BtAAAAAAA=\r\n"),
3171 MockRead("Content-Length: 42\r\n"),
3172 MockRead("Content-Type: text/html\r\n\r\n"),
3173 MockRead("You are not authorized to view this page\r\n"),
3174
3175 // Lastly we get the desired content.
3176 MockRead("HTTP/1.1 200 OK\r\n"),
3177 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3178 MockRead("Content-Length: 13\r\n\r\n"),
3179 MockRead("Please Login\r\n"),
3180 MockRead(SYNCHRONOUS, OK),
3181 };
3182
3183 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3184 data_writes1, arraysize(data_writes1));
3185 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3186 data_writes2, arraysize(data_writes2));
3187 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3188 data_writes3, arraysize(data_writes3));
3189 session_deps.socket_factory.AddSocketDataProvider(&data1);
3190 session_deps.socket_factory.AddSocketDataProvider(&data2);
3191 session_deps.socket_factory.AddSocketDataProvider(&data3);
3192
3193 TestCompletionCallback callback1;
3194
3195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3196
3197 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3198 EXPECT_EQ(ERR_IO_PENDING, rv);
3199
3200 rv = callback1.WaitForResult();
3201 EXPECT_EQ(OK, rv);
3202
3203 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3204
3205 const HttpResponseInfo* response = trans->GetResponseInfo();
3206 ASSERT_TRUE(response != NULL);
3207 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
3208
3209 TestCompletionCallback callback2;
3210
3211 // Enter the wrong password.
3212 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
3213 callback2.callback());
3214 EXPECT_EQ(ERR_IO_PENDING, rv);
3215
3216 rv = callback2.WaitForResult();
3217 EXPECT_EQ(OK, rv);
3218
3219 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3220 TestCompletionCallback callback3;
3221 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
3222 EXPECT_EQ(ERR_IO_PENDING, rv);
3223 rv = callback3.WaitForResult();
3224 EXPECT_EQ(OK, rv);
3225 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3226
3227 response = trans->GetResponseInfo();
3228 ASSERT_FALSE(response == NULL);
3229 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
3230
3231 TestCompletionCallback callback4;
3232
3233 // Now enter the right password.
3234 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
3235 callback4.callback());
3236 EXPECT_EQ(ERR_IO_PENDING, rv);
3237
3238 rv = callback4.WaitForResult();
3239 EXPECT_EQ(OK, rv);
3240
3241 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3242
3243 TestCompletionCallback callback5;
3244
3245 // One more roundtrip
3246 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
3247 EXPECT_EQ(ERR_IO_PENDING, rv);
3248
3249 rv = callback5.WaitForResult();
3250 EXPECT_EQ(OK, rv);
3251
3252 response = trans->GetResponseInfo();
3253 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3254 EXPECT_EQ(13, response->headers->GetContentLength());
3255 }
3256 #endif // NTLM_PORTABLE
3257
3258 // Test reading a server response which has only headers, and no body.
3259 // After some maximum number of bytes is consumed, the transaction should
3260 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3261 TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
3262 HttpRequestInfo request;
3263 request.method = "GET";
3264 request.url = GURL("http://www.google.com/");
3265 request.load_flags = 0;
3266
3267 SessionDependencies session_deps;
3268 scoped_ptr<HttpTransaction> trans(
3269 new HttpNetworkTransaction(CreateSession(&session_deps)));
3270
3271 // Respond with 300 kb of headers (we should fail after 256 kb).
3272 std::string large_headers_string;
3273 FillLargeHeadersString(&large_headers_string, 300 * 1024);
3274
3275 MockRead data_reads[] = {
3276 MockRead("HTTP/1.0 200 OK\r\n"),
3277 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
3278 MockRead("\r\nBODY"),
3279 MockRead(SYNCHRONOUS, OK),
3280 };
3281 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
3282 session_deps.socket_factory.AddSocketDataProvider(&data);
3283
3284 TestCompletionCallback callback;
3285
3286 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3287 EXPECT_EQ(ERR_IO_PENDING, rv);
3288
3289 rv = callback.WaitForResult();
3290 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
3291
3292 const HttpResponseInfo* response = trans->GetResponseInfo();
3293 EXPECT_TRUE(response == NULL);
3294 }
3295
3296 // Make sure that we don't try to reuse a TCPClientSocket when failing to
3297 // establish tunnel.
3298 // http://code.google.com/p/chromium/issues/detail?id=3772
3299 TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
3300 HttpRequestInfo request;
3301 request.method = "GET";
3302 request.url = GURL("https://www.google.com/");
3303 request.load_flags = 0;
3304
3305 // Configure against proxy server "myproxy:70".
3306 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
3307
3308 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3309
3310 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3311
3312 // Since we have proxy, should try to establish tunnel.
3313 MockWrite data_writes1[] = {
3314 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3315 "Host: www.google.com\r\n"
3316 "Proxy-Connection: keep-alive\r\n\r\n"),
3317 };
3318
3319 // The proxy responds to the connect with a 404, using a persistent
3320 // connection. Usually a proxy would return 501 (not implemented),
3321 // or 200 (tunnel established).
3322 MockRead data_reads1[] = {
3323 MockRead("HTTP/1.1 404 Not Found\r\n"),
3324 MockRead("Content-Length: 10\r\n\r\n"),
3325 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3326 };
3327
3328 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3329 data_writes1, arraysize(data_writes1));
3330 session_deps.socket_factory.AddSocketDataProvider(&data1);
3331
3332 TestCompletionCallback callback1;
3333
3334 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3335 EXPECT_EQ(ERR_IO_PENDING, rv);
3336
3337 rv = callback1.WaitForResult();
3338 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3339
3340 const HttpResponseInfo* response = trans->GetResponseInfo();
3341 EXPECT_TRUE(response == NULL);
3342
3343 // Empty the current queue. This is necessary because idle sockets are
3344 // added to the connection pool asynchronously with a PostTask.
3345 MessageLoop::current()->RunAllPending();
3346
3347 // We now check to make sure the TCPClientSocket was not added back to
3348 // the pool.
3349 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3350 trans.reset();
3351 MessageLoop::current()->RunAllPending();
3352 // Make sure that the socket didn't get recycled after calling the destructor.
3353 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3354 }
3355
3356 // Make sure that we recycle a socket after reading all of the response body.
3357 TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
3358 HttpRequestInfo request;
3359 request.method = "GET";
3360 request.url = GURL("http://www.google.com/");
3361 request.load_flags = 0;
3362
3363 SessionDependencies session_deps;
3364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3365
3366 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3367
3368 MockRead data_reads[] = {
3369 // A part of the response body is received with the response headers.
3370 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3371 // The rest of the response body is received in two parts.
3372 MockRead("lo"),
3373 MockRead(" world"),
3374 MockRead("junk"), // Should not be read!!
3375 MockRead(SYNCHRONOUS, OK),
3376 };
3377
3378 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
3379 session_deps.socket_factory.AddSocketDataProvider(&data);
3380
3381 TestCompletionCallback callback;
3382
3383 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3384 EXPECT_EQ(ERR_IO_PENDING, rv);
3385
3386 rv = callback.WaitForResult();
3387 EXPECT_EQ(OK, rv);
3388
3389 const HttpResponseInfo* response = trans->GetResponseInfo();
3390 ASSERT_TRUE(response != NULL);
3391
3392 EXPECT_TRUE(response->headers != NULL);
3393 std::string status_line = response->headers->GetStatusLine();
3394 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3395
3396 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3397
3398 std::string response_data;
3399 rv = ReadTransaction(trans.get(), &response_data);
3400 EXPECT_EQ(OK, rv);
3401 EXPECT_EQ("hello world", response_data);
3402
3403 // Empty the current queue. This is necessary because idle sockets are
3404 // added to the connection pool asynchronously with a PostTask.
3405 MessageLoop::current()->RunAllPending();
3406
3407 // We now check to make sure the socket was added back to the pool.
3408 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
3409 }
3410
3411 // Make sure that we recycle a SSL socket after reading all of the response
3412 // body.
3413 TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3414 SessionDependencies session_deps;
3415 HttpRequestInfo request;
3416 request.method = "GET";
3417 request.url = GURL("https://www.google.com/");
3418 request.load_flags = 0;
3419
3420 MockWrite data_writes[] = {
3421 MockWrite("GET / HTTP/1.1\r\n"
3422 "Host: www.google.com\r\n"
3423 "Connection: keep-alive\r\n\r\n"),
3424 };
3425
3426 MockRead data_reads[] = {
3427 MockRead("HTTP/1.1 200 OK\r\n"),
3428 MockRead("Content-Length: 11\r\n\r\n"),
3429 MockRead("hello world"),
3430 MockRead(SYNCHRONOUS, OK),
3431 };
3432
3433 SSLSocketDataProvider ssl(ASYNC, OK);
3434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3435
3436 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3437 data_writes, arraysize(data_writes));
3438 session_deps.socket_factory.AddSocketDataProvider(&data);
3439
3440 TestCompletionCallback callback;
3441
3442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3443 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3444
3445 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3446
3447 EXPECT_EQ(ERR_IO_PENDING, rv);
3448 EXPECT_EQ(OK, callback.WaitForResult());
3449
3450 const HttpResponseInfo* response = trans->GetResponseInfo();
3451 ASSERT_TRUE(response != NULL);
3452 ASSERT_TRUE(response->headers != NULL);
3453 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3454
3455 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3456
3457 std::string response_data;
3458 rv = ReadTransaction(trans.get(), &response_data);
3459 EXPECT_EQ(OK, rv);
3460 EXPECT_EQ("hello world", response_data);
3461
3462 // Empty the current queue. This is necessary because idle sockets are
3463 // added to the connection pool asynchronously with a PostTask.
3464 MessageLoop::current()->RunAllPending();
3465
3466 // We now check to make sure the socket was added back to the pool.
3467 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
3468 }
3469
3470 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3471 // from the pool and make sure that we recover okay.
3472 TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3473 SessionDependencies session_deps;
3474 HttpRequestInfo request;
3475 request.method = "GET";
3476 request.url = GURL("https://www.google.com/");
3477 request.load_flags = 0;
3478
3479 MockWrite data_writes[] = {
3480 MockWrite("GET / HTTP/1.1\r\n"
3481 "Host: www.google.com\r\n"
3482 "Connection: keep-alive\r\n\r\n"),
3483 MockWrite("GET / HTTP/1.1\r\n"
3484 "Host: www.google.com\r\n"
3485 "Connection: keep-alive\r\n\r\n"),
3486 };
3487
3488 MockRead data_reads[] = {
3489 MockRead("HTTP/1.1 200 OK\r\n"),
3490 MockRead("Content-Length: 11\r\n\r\n"),
3491 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3492 MockRead("hello world"),
3493 MockRead(ASYNC, 0, 0) // EOF
3494 };
3495
3496 SSLSocketDataProvider ssl(ASYNC, OK);
3497 SSLSocketDataProvider ssl2(ASYNC, OK);
3498 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3499 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3500
3501 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3502 data_writes, arraysize(data_writes));
3503 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3504 data_writes, arraysize(data_writes));
3505 session_deps.socket_factory.AddSocketDataProvider(&data);
3506 session_deps.socket_factory.AddSocketDataProvider(&data2);
3507
3508 TestCompletionCallback callback;
3509
3510 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3511 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3512
3513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3514
3515 EXPECT_EQ(ERR_IO_PENDING, rv);
3516 EXPECT_EQ(OK, callback.WaitForResult());
3517
3518 const HttpResponseInfo* response = trans->GetResponseInfo();
3519 ASSERT_TRUE(response != NULL);
3520 ASSERT_TRUE(response->headers != NULL);
3521 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3522
3523 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3524
3525 std::string response_data;
3526 rv = ReadTransaction(trans.get(), &response_data);
3527 EXPECT_EQ(OK, rv);
3528 EXPECT_EQ("hello world", response_data);
3529
3530 // Empty the current queue. This is necessary because idle sockets are
3531 // added to the connection pool asynchronously with a PostTask.
3532 MessageLoop::current()->RunAllPending();
3533
3534 // We now check to make sure the socket was added back to the pool.
3535 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
3536
3537 // Now start the second transaction, which should reuse the previous socket.
3538
3539 trans.reset(new HttpNetworkTransaction(session));
3540
3541 rv = trans->Start(&request, callback.callback(), BoundNetLog());
3542
3543 EXPECT_EQ(ERR_IO_PENDING, rv);
3544 EXPECT_EQ(OK, callback.WaitForResult());
3545
3546 response = trans->GetResponseInfo();
3547 ASSERT_TRUE(response != NULL);
3548 ASSERT_TRUE(response->headers != NULL);
3549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3550
3551 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3552
3553 rv = ReadTransaction(trans.get(), &response_data);
3554 EXPECT_EQ(OK, rv);
3555 EXPECT_EQ("hello world", response_data);
3556
3557 // Empty the current queue. This is necessary because idle sockets are
3558 // added to the connection pool asynchronously with a PostTask.
3559 MessageLoop::current()->RunAllPending();
3560
3561 // We now check to make sure the socket was added back to the pool.
3562 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
3563 }
3564
3565 // Make sure that we recycle a socket after a zero-length response.
3566 // http://crbug.com/9880
3567 TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
3568 HttpRequestInfo request;
3569 request.method = "GET";
3570 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3571 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3572 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3573 "rt=prt.2642,ol.2649,xjs.2951");
3574 request.load_flags = 0;
3575
3576 SessionDependencies session_deps;
3577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3578
3579 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3580
3581 MockRead data_reads[] = {
3582 MockRead("HTTP/1.1 204 No Content\r\n"
3583 "Content-Length: 0\r\n"
3584 "Content-Type: text/html\r\n\r\n"),
3585 MockRead("junk"), // Should not be read!!
3586 MockRead(SYNCHRONOUS, OK),
3587 };
3588
3589 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
3590 session_deps.socket_factory.AddSocketDataProvider(&data);
3591
3592 TestCompletionCallback callback;
3593
3594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3595 EXPECT_EQ(ERR_IO_PENDING, rv);
3596
3597 rv = callback.WaitForResult();
3598 EXPECT_EQ(OK, rv);
3599
3600 const HttpResponseInfo* response = trans->GetResponseInfo();
3601 ASSERT_TRUE(response != NULL);
3602
3603 EXPECT_TRUE(response->headers != NULL);
3604 std::string status_line = response->headers->GetStatusLine();
3605 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3606
3607 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
3608
3609 std::string response_data;
3610 rv = ReadTransaction(trans.get(), &response_data);
3611 EXPECT_EQ(OK, rv);
3612 EXPECT_EQ("", response_data);
3613
3614 // Empty the current queue. This is necessary because idle sockets are
3615 // added to the connection pool asynchronously with a PostTask.
3616 MessageLoop::current()->RunAllPending();
3617
3618 // We now check to make sure the socket was added back to the pool.
3619 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
3620 }
3621
3622 TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
3623 HttpRequestInfo request[2];
3624 // Transaction 1: a GET request that succeeds. The socket is recycled
3625 // after use.
3626 request[0].method = "GET";
3627 request[0].url = GURL("http://www.google.com/");
3628 request[0].load_flags = 0;
3629 // Transaction 2: a POST request. Reuses the socket kept alive from
3630 // transaction 1. The first attempts fails when writing the POST data.
3631 // This causes the transaction to retry with a new socket. The second
3632 // attempt succeeds.
3633 request[1].method = "POST";
3634 request[1].url = GURL("http://www.google.com/login.cgi");
3635 request[1].upload_data = new UploadData;
3636 request[1].upload_data->AppendBytes("foo", 3);
3637 request[1].load_flags = 0;
3638
3639 SessionDependencies session_deps;
3640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3641
3642 // The first socket is used for transaction 1 and the first attempt of
3643 // transaction 2.
3644
3645 // The response of transaction 1.
3646 MockRead data_reads1[] = {
3647 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3648 MockRead("hello world"),
3649 MockRead(SYNCHRONOUS, OK),
3650 };
3651 // The mock write results of transaction 1 and the first attempt of
3652 // transaction 2.
3653 MockWrite data_writes1[] = {
3654 MockWrite(SYNCHRONOUS, 64), // GET
3655 MockWrite(SYNCHRONOUS, 93), // POST
3656 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
3657 };
3658 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3659 data_writes1, arraysize(data_writes1));
3660
3661 // The second socket is used for the second attempt of transaction 2.
3662
3663 // The response of transaction 2.
3664 MockRead data_reads2[] = {
3665 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3666 MockRead("welcome"),
3667 MockRead(SYNCHRONOUS, OK),
3668 };
3669 // The mock write results of the second attempt of transaction 2.
3670 MockWrite data_writes2[] = {
3671 MockWrite(SYNCHRONOUS, 93), // POST
3672 MockWrite(SYNCHRONOUS, 3), // POST data
3673 };
3674 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3675 data_writes2, arraysize(data_writes2));
3676
3677 session_deps.socket_factory.AddSocketDataProvider(&data1);
3678 session_deps.socket_factory.AddSocketDataProvider(&data2);
3679
3680 const char* kExpectedResponseData[] = {
3681 "hello world", "welcome"
3682 };
3683
3684 for (int i = 0; i < 2; ++i) {
3685 scoped_ptr<HttpTransaction> trans(
3686 new HttpNetworkTransaction(session));
3687
3688 TestCompletionCallback callback;
3689
3690 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
3691 EXPECT_EQ(ERR_IO_PENDING, rv);
3692
3693 rv = callback.WaitForResult();
3694 EXPECT_EQ(OK, rv);
3695
3696 const HttpResponseInfo* response = trans->GetResponseInfo();
3697 ASSERT_TRUE(response != NULL);
3698
3699 EXPECT_TRUE(response->headers != NULL);
3700 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3701
3702 std::string response_data;
3703 rv = ReadTransaction(trans.get(), &response_data);
3704 EXPECT_EQ(OK, rv);
3705 EXPECT_EQ(kExpectedResponseData[i], response_data);
3706 }
3707 }
3708
3709 // Test the request-challenge-retry sequence for basic auth when there is
3710 // an identity in the URL. The request should be sent as normal, but when
3711 // it fails the identity from the URL is no longer used.
3712 TEST_F(HttpNetworkTransactionTest, IgnoreAuthIdentityInURL) {
3713 HttpRequestInfo request;
3714 request.method = "GET";
3715 request.url = GURL("http://foo:b@r@www.google.com/");
3716 request.load_flags = LOAD_NORMAL;
3717
3718 SessionDependencies session_deps;
3719 scoped_ptr<HttpTransaction> trans(
3720 new HttpNetworkTransaction(CreateSession(&session_deps)));
3721
3722 // The password contains an escaped character -- for this test to pass it
3723 // will need to be unescaped by HttpNetworkTransaction.
3724 EXPECT_EQ("b%40r", request.url.password());
3725
3726 MockWrite data_writes1[] = {
3727 MockWrite("GET / HTTP/1.1\r\n"
3728 "Host: www.google.com\r\n"
3729 "Connection: keep-alive\r\n\r\n"),
3730 };
3731
3732 MockRead data_reads1[] = {
3733 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3734 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3735 MockRead("Content-Length: 10\r\n\r\n"),
3736 MockRead(SYNCHRONOUS, ERR_FAILED),
3737 };
3738
3739 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3740 data_writes1, arraysize(data_writes1));
3741 session_deps.socket_factory.AddSocketDataProvider(&data1);
3742
3743 TestCompletionCallback callback1;
3744 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3745 EXPECT_EQ(ERR_IO_PENDING, rv);
3746 rv = callback1.WaitForResult();
3747 EXPECT_EQ(OK, rv);
3748 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3749
3750 // Empty the current queue.
3751 MessageLoop::current()->RunAllPending();
3752 }
3753
3754 // Test that previously tried username/passwords for a realm get re-used.
3755 TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
3756 SessionDependencies session_deps;
3757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3758
3759 // Transaction 1: authenticate (foo, bar) on MyRealm1
3760 {
3761 HttpRequestInfo request;
3762 request.method = "GET";
3763 request.url = GURL("http://www.google.com/x/y/z");
3764 request.load_flags = 0;
3765
3766 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3767
3768 MockWrite data_writes1[] = {
3769 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3770 "Host: www.google.com\r\n"
3771 "Connection: keep-alive\r\n\r\n"),
3772 };
3773
3774 MockRead data_reads1[] = {
3775 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3776 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3777 MockRead("Content-Length: 10000\r\n\r\n"),
3778 MockRead(SYNCHRONOUS, ERR_FAILED),
3779 };
3780
3781 // Resend with authorization (username=foo, password=bar)
3782 MockWrite data_writes2[] = {
3783 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3787 };
3788
3789 // Sever accepts the authorization.
3790 MockRead data_reads2[] = {
3791 MockRead("HTTP/1.0 200 OK\r\n"),
3792 MockRead("Content-Length: 100\r\n\r\n"),
3793 MockRead(SYNCHRONOUS, OK),
3794 };
3795
3796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3797 data_writes1, arraysize(data_writes1));
3798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3799 data_writes2, arraysize(data_writes2));
3800 session_deps.socket_factory.AddSocketDataProvider(&data1);
3801 session_deps.socket_factory.AddSocketDataProvider(&data2);
3802
3803 TestCompletionCallback callback1;
3804
3805 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3806 EXPECT_EQ(ERR_IO_PENDING, rv);
3807
3808 rv = callback1.WaitForResult();
3809 EXPECT_EQ(OK, rv);
3810
3811 const HttpResponseInfo* response = trans->GetResponseInfo();
3812 ASSERT_TRUE(response != NULL);
3813 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
3814
3815 TestCompletionCallback callback2;
3816
3817 rv = trans->RestartWithAuth(
3818 AuthCredentials(kFoo, kBar), callback2.callback());
3819 EXPECT_EQ(ERR_IO_PENDING, rv);
3820
3821 rv = callback2.WaitForResult();
3822 EXPECT_EQ(OK, rv);
3823
3824 response = trans->GetResponseInfo();
3825 ASSERT_TRUE(response != NULL);
3826 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3827 EXPECT_EQ(100, response->headers->GetContentLength());
3828 }
3829
3830 // ------------------------------------------------------------------------
3831
3832 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3833 {
3834 HttpRequestInfo request;
3835 request.method = "GET";
3836 // Note that Transaction 1 was at /x/y/z, so this is in the same
3837 // protection space as MyRealm1.
3838 request.url = GURL("http://www.google.com/x/y/a/b");
3839 request.load_flags = 0;
3840
3841 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3842
3843 MockWrite data_writes1[] = {
3844 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3845 "Host: www.google.com\r\n"
3846 "Connection: keep-alive\r\n"
3847 // Send preemptive authorization for MyRealm1
3848 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3849 };
3850
3851 // The server didn't like the preemptive authorization, and
3852 // challenges us for a different realm (MyRealm2).
3853 MockRead data_reads1[] = {
3854 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3855 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3856 MockRead("Content-Length: 10000\r\n\r\n"),
3857 MockRead(SYNCHRONOUS, ERR_FAILED),
3858 };
3859
3860 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3861 MockWrite data_writes2[] = {
3862 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3863 "Host: www.google.com\r\n"
3864 "Connection: keep-alive\r\n"
3865 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3866 };
3867
3868 // Sever accepts the authorization.
3869 MockRead data_reads2[] = {
3870 MockRead("HTTP/1.0 200 OK\r\n"),
3871 MockRead("Content-Length: 100\r\n\r\n"),
3872 MockRead(SYNCHRONOUS, OK),
3873 };
3874
3875 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3876 data_writes1, arraysize(data_writes1));
3877 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3878 data_writes2, arraysize(data_writes2));
3879 session_deps.socket_factory.AddSocketDataProvider(&data1);
3880 session_deps.socket_factory.AddSocketDataProvider(&data2);
3881
3882 TestCompletionCallback callback1;
3883
3884 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3885 EXPECT_EQ(ERR_IO_PENDING, rv);
3886
3887 rv = callback1.WaitForResult();
3888 EXPECT_EQ(OK, rv);
3889
3890 const HttpResponseInfo* response = trans->GetResponseInfo();
3891 ASSERT_TRUE(response != NULL);
3892 ASSERT_TRUE(response->auth_challenge.get());
3893 EXPECT_FALSE(response->auth_challenge->is_proxy);
3894 EXPECT_EQ("www.google.com:80",
3895 response->auth_challenge->challenger.ToString());
3896 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
3897 EXPECT_EQ("basic", response->auth_challenge->scheme);
3898
3899 TestCompletionCallback callback2;
3900
3901 rv = trans->RestartWithAuth(
3902 AuthCredentials(kFoo2, kBar2), callback2.callback());
3903 EXPECT_EQ(ERR_IO_PENDING, rv);
3904
3905 rv = callback2.WaitForResult();
3906 EXPECT_EQ(OK, rv);
3907
3908 response = trans->GetResponseInfo();
3909 ASSERT_TRUE(response != NULL);
3910 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3911 EXPECT_EQ(100, response->headers->GetContentLength());
3912 }
3913
3914 // ------------------------------------------------------------------------
3915
3916 // Transaction 3: Resend a request in MyRealm's protection space --
3917 // succeed with preemptive authorization.
3918 {
3919 HttpRequestInfo request;
3920 request.method = "GET";
3921 request.url = GURL("http://www.google.com/x/y/z2");
3922 request.load_flags = 0;
3923
3924 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3925
3926 MockWrite data_writes1[] = {
3927 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3928 "Host: www.google.com\r\n"
3929 "Connection: keep-alive\r\n"
3930 // The authorization for MyRealm1 gets sent preemptively
3931 // (since the url is in the same protection space)
3932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3933 };
3934
3935 // Sever accepts the preemptive authorization
3936 MockRead data_reads1[] = {
3937 MockRead("HTTP/1.0 200 OK\r\n"),
3938 MockRead("Content-Length: 100\r\n\r\n"),
3939 MockRead(SYNCHRONOUS, OK),
3940 };
3941
3942 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3943 data_writes1, arraysize(data_writes1));
3944 session_deps.socket_factory.AddSocketDataProvider(&data1);
3945
3946 TestCompletionCallback callback1;
3947
3948 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3949 EXPECT_EQ(ERR_IO_PENDING, rv);
3950
3951 rv = callback1.WaitForResult();
3952 EXPECT_EQ(OK, rv);
3953
3954 const HttpResponseInfo* response = trans->GetResponseInfo();
3955 ASSERT_TRUE(response != NULL);
3956
3957 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3958 EXPECT_EQ(100, response->headers->GetContentLength());
3959 }
3960
3961 // ------------------------------------------------------------------------
3962
3963 // Transaction 4: request another URL in MyRealm (however the
3964 // url is not known to belong to the protection space, so no pre-auth).
3965 {
3966 HttpRequestInfo request;
3967 request.method = "GET";
3968 request.url = GURL("http://www.google.com/x/1");
3969 request.load_flags = 0;
3970
3971 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3972
3973 MockWrite data_writes1[] = {
3974 MockWrite("GET /x/1 HTTP/1.1\r\n"
3975 "Host: www.google.com\r\n"
3976 "Connection: keep-alive\r\n\r\n"),
3977 };
3978
3979 MockRead data_reads1[] = {
3980 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3981 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3982 MockRead("Content-Length: 10000\r\n\r\n"),
3983 MockRead(SYNCHRONOUS, ERR_FAILED),
3984 };
3985
3986 // Resend with authorization from MyRealm's cache.
3987 MockWrite data_writes2[] = {
3988 MockWrite("GET /x/1 HTTP/1.1\r\n"
3989 "Host: www.google.com\r\n"
3990 "Connection: keep-alive\r\n"
3991 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3992 };
3993
3994 // Sever accepts the authorization.
3995 MockRead data_reads2[] = {
3996 MockRead("HTTP/1.0 200 OK\r\n"),
3997 MockRead("Content-Length: 100\r\n\r\n"),
3998 MockRead(SYNCHRONOUS, OK),
3999 };
4000
4001 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4002 data_writes1, arraysize(data_writes1));
4003 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4004 data_writes2, arraysize(data_writes2));
4005 session_deps.socket_factory.AddSocketDataProvider(&data1);
4006 session_deps.socket_factory.AddSocketDataProvider(&data2);
4007
4008 TestCompletionCallback callback1;
4009
4010 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4011 EXPECT_EQ(ERR_IO_PENDING, rv);
4012
4013 rv = callback1.WaitForResult();
4014 EXPECT_EQ(OK, rv);
4015
4016 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4017 TestCompletionCallback callback2;
4018 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4019 EXPECT_EQ(ERR_IO_PENDING, rv);
4020 rv = callback2.WaitForResult();
4021 EXPECT_EQ(OK, rv);
4022 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4023
4024 const HttpResponseInfo* response = trans->GetResponseInfo();
4025 ASSERT_TRUE(response != NULL);
4026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4027 EXPECT_EQ(100, response->headers->GetContentLength());
4028 }
4029
4030 // ------------------------------------------------------------------------
4031
4032 // Transaction 5: request a URL in MyRealm, but the server rejects the
4033 // cached identity. Should invalidate and re-prompt.
4034 {
4035 HttpRequestInfo request;
4036 request.method = "GET";
4037 request.url = GURL("http://www.google.com/p/q/t");
4038 request.load_flags = 0;
4039
4040 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4041
4042 MockWrite data_writes1[] = {
4043 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4044 "Host: www.google.com\r\n"
4045 "Connection: keep-alive\r\n\r\n"),
4046 };
4047
4048 MockRead data_reads1[] = {
4049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4050 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4051 MockRead("Content-Length: 10000\r\n\r\n"),
4052 MockRead(SYNCHRONOUS, ERR_FAILED),
4053 };
4054
4055 // Resend with authorization from cache for MyRealm.
4056 MockWrite data_writes2[] = {
4057 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4058 "Host: www.google.com\r\n"
4059 "Connection: keep-alive\r\n"
4060 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4061 };
4062
4063 // Sever rejects the authorization.
4064 MockRead data_reads2[] = {
4065 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4066 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4067 MockRead("Content-Length: 10000\r\n\r\n"),
4068 MockRead(SYNCHRONOUS, ERR_FAILED),
4069 };
4070
4071 // At this point we should prompt for new credentials for MyRealm.
4072 // Restart with username=foo3, password=foo4.
4073 MockWrite data_writes3[] = {
4074 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4075 "Host: www.google.com\r\n"
4076 "Connection: keep-alive\r\n"
4077 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4078 };
4079
4080 // Sever accepts the authorization.
4081 MockRead data_reads3[] = {
4082 MockRead("HTTP/1.0 200 OK\r\n"),
4083 MockRead("Content-Length: 100\r\n\r\n"),
4084 MockRead(SYNCHRONOUS, OK),
4085 };
4086
4087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4088 data_writes1, arraysize(data_writes1));
4089 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4090 data_writes2, arraysize(data_writes2));
4091 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4092 data_writes3, arraysize(data_writes3));
4093 session_deps.socket_factory.AddSocketDataProvider(&data1);
4094 session_deps.socket_factory.AddSocketDataProvider(&data2);
4095 session_deps.socket_factory.AddSocketDataProvider(&data3);
4096
4097 TestCompletionCallback callback1;
4098
4099 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4100 EXPECT_EQ(ERR_IO_PENDING, rv);
4101
4102 rv = callback1.WaitForResult();
4103 EXPECT_EQ(OK, rv);
4104
4105 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4106 TestCompletionCallback callback2;
4107 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4108 EXPECT_EQ(ERR_IO_PENDING, rv);
4109 rv = callback2.WaitForResult();
4110 EXPECT_EQ(OK, rv);
4111 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4112
4113 const HttpResponseInfo* response = trans->GetResponseInfo();
4114 ASSERT_TRUE(response != NULL);
4115 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4116
4117 TestCompletionCallback callback3;
4118
4119 rv = trans->RestartWithAuth(
4120 AuthCredentials(kFoo3, kBar3), callback3.callback());
4121 EXPECT_EQ(ERR_IO_PENDING, rv);
4122
4123 rv = callback3.WaitForResult();
4124 EXPECT_EQ(OK, rv);
4125
4126 response = trans->GetResponseInfo();
4127 ASSERT_TRUE(response != NULL);
4128 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4129 EXPECT_EQ(100, response->headers->GetContentLength());
4130 }
4131 }
4132
4133 // Tests that nonce count increments when multiple auth attempts
4134 // are started with the same nonce.
4135 TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4136 SessionDependencies session_deps;
4137 HttpAuthHandlerDigest::Factory* digest_factory =
4138 new HttpAuthHandlerDigest::Factory();
4139 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4140 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4141 digest_factory->set_nonce_generator(nonce_generator);
4142 session_deps.http_auth_handler_factory.reset(digest_factory);
4143 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4144
4145 // Transaction 1: authenticate (foo, bar) on MyRealm1
4146 {
4147 HttpRequestInfo request;
4148 request.method = "GET";
4149 request.url = GURL("http://www.google.com/x/y/z");
4150 request.load_flags = 0;
4151
4152 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4153
4154 MockWrite data_writes1[] = {
4155 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4156 "Host: www.google.com\r\n"
4157 "Connection: keep-alive\r\n\r\n"),
4158 };
4159
4160 MockRead data_reads1[] = {
4161 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4162 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4163 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4164 MockRead(SYNCHRONOUS, OK),
4165 };
4166
4167 // Resend with authorization (username=foo, password=bar)
4168 MockWrite data_writes2[] = {
4169 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4170 "Host: www.google.com\r\n"
4171 "Connection: keep-alive\r\n"
4172 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4173 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4174 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4175 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4176 };
4177
4178 // Sever accepts the authorization.
4179 MockRead data_reads2[] = {
4180 MockRead("HTTP/1.0 200 OK\r\n"),
4181 MockRead(SYNCHRONOUS, OK),
4182 };
4183
4184 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4185 data_writes1, arraysize(data_writes1));
4186 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4187 data_writes2, arraysize(data_writes2));
4188 session_deps.socket_factory.AddSocketDataProvider(&data1);
4189 session_deps.socket_factory.AddSocketDataProvider(&data2);
4190
4191 TestCompletionCallback callback1;
4192
4193 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4194 EXPECT_EQ(ERR_IO_PENDING, rv);
4195
4196 rv = callback1.WaitForResult();
4197 EXPECT_EQ(OK, rv);
4198
4199 const HttpResponseInfo* response = trans->GetResponseInfo();
4200 ASSERT_TRUE(response != NULL);
4201 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
4202
4203 TestCompletionCallback callback2;
4204
4205 rv = trans->RestartWithAuth(
4206 AuthCredentials(kFoo, kBar), callback2.callback());
4207 EXPECT_EQ(ERR_IO_PENDING, rv);
4208
4209 rv = callback2.WaitForResult();
4210 EXPECT_EQ(OK, rv);
4211
4212 response = trans->GetResponseInfo();
4213 ASSERT_TRUE(response != NULL);
4214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4215 }
4216
4217 // ------------------------------------------------------------------------
4218
4219 // Transaction 2: Request another resource in digestive's protection space.
4220 // This will preemptively add an Authorization header which should have an
4221 // "nc" value of 2 (as compared to 1 in the first use.
4222 {
4223 HttpRequestInfo request;
4224 request.method = "GET";
4225 // Note that Transaction 1 was at /x/y/z, so this is in the same
4226 // protection space as digest.
4227 request.url = GURL("http://www.google.com/x/y/a/b");
4228 request.load_flags = 0;
4229
4230 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4231
4232 MockWrite data_writes1[] = {
4233 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4234 "Host: www.google.com\r\n"
4235 "Connection: keep-alive\r\n"
4236 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4237 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4238 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4239 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4240 };
4241
4242 // Sever accepts the authorization.
4243 MockRead data_reads1[] = {
4244 MockRead("HTTP/1.0 200 OK\r\n"),
4245 MockRead("Content-Length: 100\r\n\r\n"),
4246 MockRead(SYNCHRONOUS, OK),
4247 };
4248
4249 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4250 data_writes1, arraysize(data_writes1));
4251 session_deps.socket_factory.AddSocketDataProvider(&data1);
4252
4253 TestCompletionCallback callback1;
4254
4255 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4256 EXPECT_EQ(ERR_IO_PENDING, rv);
4257
4258 rv = callback1.WaitForResult();
4259 EXPECT_EQ(OK, rv);
4260
4261 const HttpResponseInfo* response = trans->GetResponseInfo();
4262 ASSERT_TRUE(response != NULL);
4263 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4264 }
4265 }
4266
4267 // Test the ResetStateForRestart() private method.
4268 TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4269 // Create a transaction (the dependencies aren't important).
4270 SessionDependencies session_deps;
4271 scoped_ptr<HttpNetworkTransaction> trans(
4272 new HttpNetworkTransaction(CreateSession(&session_deps)));
4273
4274 // Setup some state (which we expect ResetStateForRestart() will clear).
4275 trans->read_buf_ = new IOBuffer(15);
4276 trans->read_buf_len_ = 15;
4277 trans->request_headers_.SetHeader("Authorization", "NTLM");
4278
4279 // Setup state in response_
4280 HttpResponseInfo* response = &trans->response_;
4281 response->auth_challenge = new AuthChallengeInfo();
4282 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
4283 response->response_time = base::Time::Now();
4284 response->was_cached = true; // (Wouldn't ever actually be true...)
4285
4286 { // Setup state for response_.vary_data
4287 HttpRequestInfo request;
4288 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4289 std::replace(temp.begin(), temp.end(), '\n', '\0');
4290 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
4291 request.extra_headers.SetHeader("Foo", "1");
4292 request.extra_headers.SetHeader("bar", "23");
4293 EXPECT_TRUE(response->vary_data.Init(request, *headers));
4294 }
4295
4296 // Cause the above state to be reset.
4297 trans->ResetStateForRestart();
4298
4299 // Verify that the state that needed to be reset, has been reset.
4300 EXPECT_TRUE(trans->read_buf_.get() == NULL);
4301 EXPECT_EQ(0, trans->read_buf_len_);
4302 EXPECT_TRUE(trans->request_headers_.IsEmpty());
4303 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4304 EXPECT_TRUE(response->headers.get() == NULL);
4305 EXPECT_FALSE(response->was_cached);
4306 EXPECT_EQ(0U, response->ssl_info.cert_status);
4307 EXPECT_FALSE(response->vary_data.is_valid());
4308 }
4309
4310 // Test HTTPS connections to a site with a bad certificate
4311 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
4312 HttpRequestInfo request;
4313 request.method = "GET";
4314 request.url = GURL("https://www.google.com/");
4315 request.load_flags = 0;
4316
4317 SessionDependencies session_deps;
4318 scoped_ptr<HttpTransaction> trans(
4319 new HttpNetworkTransaction(CreateSession(&session_deps)));
4320
4321 MockWrite data_writes[] = {
4322 MockWrite("GET / HTTP/1.1\r\n"
4323 "Host: www.google.com\r\n"
4324 "Connection: keep-alive\r\n\r\n"),
4325 };
4326
4327 MockRead data_reads[] = {
4328 MockRead("HTTP/1.0 200 OK\r\n"),
4329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4330 MockRead("Content-Length: 100\r\n\r\n"),
4331 MockRead(SYNCHRONOUS, OK),
4332 };
4333
4334 StaticSocketDataProvider ssl_bad_certificate;
4335 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4336 data_writes, arraysize(data_writes));
4337 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
4338 SSLSocketDataProvider ssl(ASYNC, OK);
4339
4340 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4341 session_deps.socket_factory.AddSocketDataProvider(&data);
4342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4344
4345 TestCompletionCallback callback;
4346
4347 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4348 EXPECT_EQ(ERR_IO_PENDING, rv);
4349
4350 rv = callback.WaitForResult();
4351 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4352
4353 rv = trans->RestartIgnoringLastError(callback.callback());
4354 EXPECT_EQ(ERR_IO_PENDING, rv);
4355
4356 rv = callback.WaitForResult();
4357 EXPECT_EQ(OK, rv);
4358
4359 const HttpResponseInfo* response = trans->GetResponseInfo();
4360
4361 ASSERT_TRUE(response != NULL);
4362 EXPECT_EQ(100, response->headers->GetContentLength());
4363 }
4364
4365 // Test HTTPS connections to a site with a bad certificate, going through a
4366 // proxy
4367 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
4368 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4369
4370 HttpRequestInfo request;
4371 request.method = "GET";
4372 request.url = GURL("https://www.google.com/");
4373 request.load_flags = 0;
4374
4375 MockWrite proxy_writes[] = {
4376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4377 "Host: www.google.com\r\n"
4378 "Proxy-Connection: keep-alive\r\n\r\n"),
4379 };
4380
4381 MockRead proxy_reads[] = {
4382 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4383 MockRead(SYNCHRONOUS, OK)
4384 };
4385
4386 MockWrite data_writes[] = {
4387 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4388 "Host: www.google.com\r\n"
4389 "Proxy-Connection: keep-alive\r\n\r\n"),
4390 MockWrite("GET / HTTP/1.1\r\n"
4391 "Host: www.google.com\r\n"
4392 "Connection: keep-alive\r\n\r\n"),
4393 };
4394
4395 MockRead data_reads[] = {
4396 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4397 MockRead("HTTP/1.0 200 OK\r\n"),
4398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4399 MockRead("Content-Length: 100\r\n\r\n"),
4400 MockRead(SYNCHRONOUS, OK),
4401 };
4402
4403 StaticSocketDataProvider ssl_bad_certificate(
4404 proxy_reads, arraysize(proxy_reads),
4405 proxy_writes, arraysize(proxy_writes));
4406 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4407 data_writes, arraysize(data_writes));
4408 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
4409 SSLSocketDataProvider ssl(ASYNC, OK);
4410
4411 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4412 session_deps.socket_factory.AddSocketDataProvider(&data);
4413 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4414 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4415
4416 TestCompletionCallback callback;
4417
4418 for (int i = 0; i < 2; i++) {
4419 session_deps.socket_factory.ResetNextMockIndexes();
4420
4421 scoped_ptr<HttpTransaction> trans(
4422 new HttpNetworkTransaction(CreateSession(&session_deps)));
4423
4424 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4425 EXPECT_EQ(ERR_IO_PENDING, rv);
4426
4427 rv = callback.WaitForResult();
4428 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4429
4430 rv = trans->RestartIgnoringLastError(callback.callback());
4431 EXPECT_EQ(ERR_IO_PENDING, rv);
4432
4433 rv = callback.WaitForResult();
4434 EXPECT_EQ(OK, rv);
4435
4436 const HttpResponseInfo* response = trans->GetResponseInfo();
4437
4438 ASSERT_TRUE(response != NULL);
4439 EXPECT_EQ(100, response->headers->GetContentLength());
4440 }
4441 }
4442
4443
4444 // Test HTTPS connections to a site, going through an HTTPS proxy
4445 TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
4446 SessionDependencies session_deps(ProxyService::CreateFixed(
4447 "https://proxy:70"));
4448
4449 HttpRequestInfo request;
4450 request.method = "GET";
4451 request.url = GURL("https://www.google.com/");
4452 request.load_flags = 0;
4453
4454 MockWrite data_writes[] = {
4455 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4456 "Host: www.google.com\r\n"
4457 "Proxy-Connection: keep-alive\r\n\r\n"),
4458 MockWrite("GET / HTTP/1.1\r\n"
4459 "Host: www.google.com\r\n"
4460 "Connection: keep-alive\r\n\r\n"),
4461 };
4462
4463 MockRead data_reads[] = {
4464 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4465 MockRead("HTTP/1.1 200 OK\r\n"),
4466 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4467 MockRead("Content-Length: 100\r\n\r\n"),
4468 MockRead(SYNCHRONOUS, OK),
4469 };
4470
4471 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4472 data_writes, arraysize(data_writes));
4473 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
4474 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
4475
4476 session_deps.socket_factory.AddSocketDataProvider(&data);
4477 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4478 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4479
4480 TestCompletionCallback callback;
4481
4482 scoped_ptr<HttpTransaction> trans(
4483 new HttpNetworkTransaction(CreateSession(&session_deps)));
4484
4485 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4486 EXPECT_EQ(ERR_IO_PENDING, rv);
4487
4488 rv = callback.WaitForResult();
4489 EXPECT_EQ(OK, rv);
4490 const HttpResponseInfo* response = trans->GetResponseInfo();
4491
4492 ASSERT_TRUE(response != NULL);
4493
4494 EXPECT_TRUE(response->headers->IsKeepAlive());
4495 EXPECT_EQ(200, response->headers->response_code());
4496 EXPECT_EQ(100, response->headers->GetContentLength());
4497 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4498 }
4499
4500 // Test an HTTPS Proxy's ability to redirect a CONNECT request
4501 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4502 SessionDependencies session_deps(
4503 ProxyService::CreateFixed("https://proxy:70"));
4504
4505 HttpRequestInfo request;
4506 request.method = "GET";
4507 request.url = GURL("https://www.google.com/");
4508 request.load_flags = 0;
4509
4510 MockWrite data_writes[] = {
4511 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4512 "Host: www.google.com\r\n"
4513 "Proxy-Connection: keep-alive\r\n\r\n"),
4514 };
4515
4516 MockRead data_reads[] = {
4517 MockRead("HTTP/1.1 302 Redirect\r\n"),
4518 MockRead("Location: http://login.example.com/\r\n"),
4519 MockRead("Content-Length: 0\r\n\r\n"),
4520 MockRead(SYNCHRONOUS, OK),
4521 };
4522
4523 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4524 data_writes, arraysize(data_writes));
4525 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
4526
4527 session_deps.socket_factory.AddSocketDataProvider(&data);
4528 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4529
4530 TestCompletionCallback callback;
4531
4532 scoped_ptr<HttpTransaction> trans(
4533 new HttpNetworkTransaction(CreateSession(&session_deps)));
4534
4535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4536 EXPECT_EQ(ERR_IO_PENDING, rv);
4537
4538 rv = callback.WaitForResult();
4539 EXPECT_EQ(OK, rv);
4540 const HttpResponseInfo* response = trans->GetResponseInfo();
4541
4542 ASSERT_TRUE(response != NULL);
4543
4544 EXPECT_EQ(302, response->headers->response_code());
4545 std::string url;
4546 EXPECT_TRUE(response->headers->IsRedirect(&url));
4547 EXPECT_EQ("http://login.example.com/", url);
4548 }
4549
4550 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4551 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4552 SessionDependencies session_deps(
4553 ProxyService::CreateFixed("https://proxy:70"));
4554
4555 HttpRequestInfo request;
4556 request.method = "GET";
4557 request.url = GURL("https://www.google.com/");
4558 request.load_flags = 0;
4559
4560 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4561 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4562 MockWrite data_writes[] = {
4563 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
4564 };
4565
4566 static const char* const kExtraHeaders[] = {
4567 "location",
4568 "http://login.example.com/",
4569 };
4570 scoped_ptr<spdy::SpdyFrame> resp(
4571 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4572 arraysize(kExtraHeaders)/2, 1));
4573 MockRead data_reads[] = {
4574 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
4575 MockRead(ASYNC, 0, 2), // EOF
4576 };
4577
4578 scoped_ptr<DelayedSocketData> data(
4579 new DelayedSocketData(
4580 1, // wait for one write to finish before reading.
4581 data_reads, arraysize(data_reads),
4582 data_writes, arraysize(data_writes)));
4583 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
4584 proxy_ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
4585
4586 session_deps.socket_factory.AddSocketDataProvider(data.get());
4587 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4588
4589 TestCompletionCallback callback;
4590
4591 scoped_ptr<HttpTransaction> trans(
4592 new HttpNetworkTransaction(CreateSession(&session_deps)));
4593
4594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4595 EXPECT_EQ(ERR_IO_PENDING, rv);
4596
4597 rv = callback.WaitForResult();
4598 EXPECT_EQ(OK, rv);
4599 const HttpResponseInfo* response = trans->GetResponseInfo();
4600
4601 ASSERT_TRUE(response != NULL);
4602
4603 EXPECT_EQ(302, response->headers->response_code());
4604 std::string url;
4605 EXPECT_TRUE(response->headers->IsRedirect(&url));
4606 EXPECT_EQ("http://login.example.com/", url);
4607 }
4608
4609 // Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4610 TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4611 SessionDependencies session_deps(
4612 ProxyService::CreateFixed("https://proxy:70"));
4613
4614 HttpRequestInfo request;
4615 request.method = "GET";
4616 request.url = GURL("https://www.google.com/");
4617 request.load_flags = 0;
4618
4619 MockWrite data_writes[] = {
4620 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4621 "Host: www.google.com\r\n"
4622 "Proxy-Connection: keep-alive\r\n\r\n"),
4623 };
4624
4625 MockRead data_reads[] = {
4626 MockRead("HTTP/1.1 404 Not Found\r\n"),
4627 MockRead("Content-Length: 23\r\n\r\n"),
4628 MockRead("The host does not exist"),
4629 MockRead(SYNCHRONOUS, OK),
4630 };
4631
4632 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4633 data_writes, arraysize(data_writes));
4634 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
4635
4636 session_deps.socket_factory.AddSocketDataProvider(&data);
4637 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4638
4639 TestCompletionCallback callback;
4640
4641 scoped_ptr<HttpTransaction> trans(
4642 new HttpNetworkTransaction(CreateSession(&session_deps)));
4643
4644 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4645 EXPECT_EQ(ERR_IO_PENDING, rv);
4646
4647 rv = callback.WaitForResult();
4648 EXPECT_EQ(OK, rv);
4649 const HttpResponseInfo* response = trans->GetResponseInfo();
4650
4651 ASSERT_TRUE(response != NULL);
4652
4653 EXPECT_EQ(404, response->headers->response_code());
4654 EXPECT_EQ(23, response->headers->GetContentLength());
4655 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4656 EXPECT_FALSE(response->ssl_info.is_valid());
4657
4658 std::string response_data;
4659 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4660 EXPECT_EQ("The host does not exist", response_data);
4661 }
4662
4663 // Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4664 // request
4665 TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4666 SessionDependencies session_deps(
4667 ProxyService::CreateFixed("https://proxy:70"));
4668
4669 HttpRequestInfo request;
4670 request.method = "GET";
4671 request.url = GURL("https://www.google.com/");
4672 request.load_flags = 0;
4673
4674 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4675 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4676 MockWrite data_writes[] = {
4677 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
4678 };
4679
4680 static const char* const kExtraHeaders[] = {
4681 "location",
4682 "http://login.example.com/",
4683 };
4684 scoped_ptr<spdy::SpdyFrame> resp(
4685 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4686 arraysize(kExtraHeaders)/2, 1));
4687 scoped_ptr<spdy::SpdyFrame> body(
4688 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4689 MockRead data_reads[] = {
4690 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
4691 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
4692 MockRead(ASYNC, 0, 3), // EOF
4693 };
4694
4695 scoped_ptr<DelayedSocketData> data(
4696 new DelayedSocketData(
4697 1, // wait for one write to finish before reading.
4698 data_reads, arraysize(data_reads),
4699 data_writes, arraysize(data_writes)));
4700 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
4701 proxy_ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
4702
4703 session_deps.socket_factory.AddSocketDataProvider(data.get());
4704 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4705
4706 TestCompletionCallback callback;
4707
4708 scoped_ptr<HttpTransaction> trans(
4709 new HttpNetworkTransaction(CreateSession(&session_deps)));
4710
4711 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4712 EXPECT_EQ(ERR_IO_PENDING, rv);
4713
4714 rv = callback.WaitForResult();
4715 EXPECT_EQ(OK, rv);
4716 const HttpResponseInfo* response = trans->GetResponseInfo();
4717
4718 ASSERT_TRUE(response != NULL);
4719
4720 EXPECT_EQ(404, response->headers->response_code());
4721 EXPECT_FALSE(response->ssl_info.is_valid());
4722
4723 std::string response_data;
4724 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4725 EXPECT_EQ("The host does not exist", response_data);
4726 }
4727
4728 // Test the request-challenge-retry sequence for basic auth, through
4729 // a SPDY proxy over a single SPDY session.
4730 TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
4731 HttpRequestInfo request;
4732 request.method = "GET";
4733 request.url = GURL("https://www.google.com/");
4734 // when the no authentication data flag is set.
4735 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
4736
4737 // Configure against https proxy server "myproxy:70".
4738 SessionDependencies session_deps(
4739 ProxyService::CreateFixed("https://myproxy:70"));
4740 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
4741 session_deps.net_log = log.bound().net_log();
4742 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4743
4744 // Since we have proxy, should try to establish tunnel.
4745 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyConnect(NULL, 0, 1));
4746 scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(1, spdy::CANCEL));
4747
4748 // After calling trans->RestartWithAuth(), this is the request we should
4749 // be issuing -- the final header line contains the credentials.
4750 const char* const kAuthCredentials[] = {
4751 "proxy-authorization", "Basic Zm9vOmJhcg==",
4752 };
4753 scoped_ptr<spdy::SpdyFrame> connect2(
4754 ConstructSpdyConnect(kAuthCredentials, arraysize(kAuthCredentials)/2, 3));
4755 // fetch https://www.google.com/ via HTTP
4756 const char get[] = "GET / HTTP/1.1\r\n"
4757 "Host: www.google.com\r\n"
4758 "Connection: keep-alive\r\n\r\n";
4759 scoped_ptr<spdy::SpdyFrame> wrapped_get(
4760 ConstructSpdyBodyFrame(3, get, strlen(get), false));
4761
4762 MockWrite spdy_writes[] = {
4763 CreateMockWrite(*req, 0, ASYNC),
4764 CreateMockWrite(*rst, 2, ASYNC),
4765 CreateMockWrite(*connect2, 3),
4766 CreateMockWrite(*wrapped_get, 5)
4767 };
4768
4769 // The proxy responds to the connect with a 407, using a persistent
4770 // connection.
4771 const char* const kAuthChallenge[] = {
4772 "status", "407 Proxy Authentication Required",
4773 "version", "HTTP/1.1",
4774 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
4775 };
4776
4777 scoped_ptr<spdy::SpdyFrame> conn_auth_resp(
4778 ConstructSpdyControlFrame(NULL,
4779 0,
4780 false,
4781 1,
4782 LOWEST,
4783 spdy::SYN_REPLY,
4784 spdy::CONTROL_FLAG_NONE,
4785 kAuthChallenge,
4786 arraysize(kAuthChallenge)));
4787
4788 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
4789 const char resp[] = "HTTP/1.1 200 OK\r\n"
4790 "Content-Length: 5\r\n\r\n";
4791
4792 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
4793 ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
4794 scoped_ptr<spdy::SpdyFrame> wrapped_body(
4795 ConstructSpdyBodyFrame(3, "hello", 5, false));
4796 MockRead spdy_reads[] = {
4797 CreateMockRead(*conn_auth_resp, 1, ASYNC),
4798 CreateMockRead(*conn_resp, 4, ASYNC),
4799 CreateMockRead(*wrapped_get_resp, 5, ASYNC),
4800 CreateMockRead(*wrapped_body, 6, ASYNC),
4801 MockRead(SYNCHRONOUS, ERR_IO_PENDING),
4802 };
4803
4804 scoped_ptr<OrderedSocketData> spdy_data(
4805 new OrderedSocketData(
4806 spdy_reads, arraysize(spdy_reads),
4807 spdy_writes, arraysize(spdy_writes)));
4808 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
4809 // Negotiate SPDY to the proxy
4810 SSLSocketDataProvider proxy(ASYNC, OK);
4811 proxy.SetNextProto(SSLClientSocket::kProtoSPDY2);
4812 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy);
4813 // Vanilla SSL to the server
4814 SSLSocketDataProvider server(ASYNC, OK);
4815 session_deps.socket_factory.AddSSLSocketDataProvider(&server);
4816
4817 TestCompletionCallback callback1;
4818
4819 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4820
4821 int rv = trans->Start(&request, callback1.callback(), log.bound());
4822 EXPECT_EQ(ERR_IO_PENDING, rv);
4823
4824 rv = callback1.WaitForResult();
4825 EXPECT_EQ(OK, rv);
4826 net::CapturingNetLog::EntryList entries;
4827 log.GetEntries(&entries);
4828 size_t pos = ExpectLogContainsSomewhere(
4829 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4830 NetLog::PHASE_NONE);
4831 ExpectLogContainsSomewhere(
4832 entries, pos,
4833 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4834 NetLog::PHASE_NONE);
4835
4836 const HttpResponseInfo* response = trans->GetResponseInfo();
4837 ASSERT_TRUE(response != NULL);
4838 ASSERT_FALSE(response->headers == NULL);
4839 EXPECT_EQ(407, response->headers->response_code());
4840 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4841 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4842 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4843
4844 TestCompletionCallback callback2;
4845
4846 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
4847 callback2.callback());
4848 EXPECT_EQ(ERR_IO_PENDING, rv);
4849
4850 rv = callback2.WaitForResult();
4851 EXPECT_EQ(OK, rv);
4852
4853 response = trans->GetResponseInfo();
4854 ASSERT_TRUE(response != NULL);
4855
4856 EXPECT_TRUE(response->headers->IsKeepAlive());
4857 EXPECT_EQ(200, response->headers->response_code());
4858 EXPECT_EQ(5, response->headers->GetContentLength());
4859 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4860
4861 // The password prompt info should not be set.
4862 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4863
4864 trans.reset();
4865 session->CloseAllConnections();
4866 }
4867
4868 // Test HTTPS connections to a site with a bad certificate, going through an
4869 // HTTPS proxy
4870 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
4871 SessionDependencies session_deps(ProxyService::CreateFixed(
4872 "https://proxy:70"));
4873
4874 HttpRequestInfo request;
4875 request.method = "GET";
4876 request.url = GURL("https://www.google.com/");
4877 request.load_flags = 0;
4878
4879 // Attempt to fetch the URL from a server with a bad cert
4880 MockWrite bad_cert_writes[] = {
4881 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4882 "Host: www.google.com\r\n"
4883 "Proxy-Connection: keep-alive\r\n\r\n"),
4884 };
4885
4886 MockRead bad_cert_reads[] = {
4887 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4888 MockRead(SYNCHRONOUS, OK)
4889 };
4890
4891 // Attempt to fetch the URL with a good cert
4892 MockWrite good_data_writes[] = {
4893 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4894 "Host: www.google.com\r\n"
4895 "Proxy-Connection: keep-alive\r\n\r\n"),
4896 MockWrite("GET / HTTP/1.1\r\n"
4897 "Host: www.google.com\r\n"
4898 "Connection: keep-alive\r\n\r\n"),
4899 };
4900
4901 MockRead good_cert_reads[] = {
4902 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4903 MockRead("HTTP/1.0 200 OK\r\n"),
4904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4905 MockRead("Content-Length: 100\r\n\r\n"),
4906 MockRead(SYNCHRONOUS, OK),
4907 };
4908
4909 StaticSocketDataProvider ssl_bad_certificate(
4910 bad_cert_reads, arraysize(bad_cert_reads),
4911 bad_cert_writes, arraysize(bad_cert_writes));
4912 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4913 good_data_writes, arraysize(good_data_writes));
4914 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
4915 SSLSocketDataProvider ssl(ASYNC, OK);
4916
4917 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4918 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4919 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4920 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4921
4922 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4923 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4924 session_deps.socket_factory.AddSocketDataProvider(&data);
4925 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4926
4927 TestCompletionCallback callback;
4928
4929 scoped_ptr<HttpTransaction> trans(
4930 new HttpNetworkTransaction(CreateSession(&session_deps)));
4931
4932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4933 EXPECT_EQ(ERR_IO_PENDING, rv);
4934
4935 rv = callback.WaitForResult();
4936 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4937
4938 rv = trans->RestartIgnoringLastError(callback.callback());
4939 EXPECT_EQ(ERR_IO_PENDING, rv);
4940
4941 rv = callback.WaitForResult();
4942 EXPECT_EQ(OK, rv);
4943
4944 const HttpResponseInfo* response = trans->GetResponseInfo();
4945
4946 ASSERT_TRUE(response != NULL);
4947 EXPECT_EQ(100, response->headers->GetContentLength());
4948 }
4949
4950 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
4951 HttpRequestInfo request;
4952 request.method = "GET";
4953 request.url = GURL("http://www.google.com/");
4954 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4955 "Chromium Ultra Awesome X Edition");
4956
4957 SessionDependencies session_deps;
4958 scoped_ptr<HttpTransaction> trans(
4959 new HttpNetworkTransaction(CreateSession(&session_deps)));
4960
4961 MockWrite data_writes[] = {
4962 MockWrite("GET / HTTP/1.1\r\n"
4963 "Host: www.google.com\r\n"
4964 "Connection: keep-alive\r\n"
4965 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4966 };
4967
4968 // Lastly, the server responds with the actual content.
4969 MockRead data_reads[] = {
4970 MockRead("HTTP/1.0 200 OK\r\n"),
4971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4972 MockRead("Content-Length: 100\r\n\r\n"),
4973 MockRead(SYNCHRONOUS, OK),
4974 };
4975
4976 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4977 data_writes, arraysize(data_writes));
4978 session_deps.socket_factory.AddSocketDataProvider(&data);
4979
4980 TestCompletionCallback callback;
4981
4982 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4983 EXPECT_EQ(ERR_IO_PENDING, rv);
4984
4985 rv = callback.WaitForResult();
4986 EXPECT_EQ(OK, rv);
4987 }
4988
4989 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
4990 HttpRequestInfo request;
4991 request.method = "GET";
4992 request.url = GURL("https://www.google.com/");
4993 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4994 "Chromium Ultra Awesome X Edition");
4995
4996 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4997 scoped_ptr<HttpTransaction> trans(
4998 new HttpNetworkTransaction(CreateSession(&session_deps)));
4999
5000 MockWrite data_writes[] = {
5001 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5002 "Host: www.google.com\r\n"
5003 "Proxy-Connection: keep-alive\r\n"
5004 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
5005 };
5006 MockRead data_reads[] = {
5007 // Return an error, so the transaction stops here (this test isn't
5008 // interested in the rest).
5009 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5010 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5011 MockRead("Proxy-Connection: close\r\n\r\n"),
5012 };
5013
5014 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5015 data_writes, arraysize(data_writes));
5016 session_deps.socket_factory.AddSocketDataProvider(&data);
5017
5018 TestCompletionCallback callback;
5019
5020 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5021 EXPECT_EQ(ERR_IO_PENDING, rv);
5022
5023 rv = callback.WaitForResult();
5024 EXPECT_EQ(OK, rv);
5025 }
5026
5027 TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
5028 HttpRequestInfo request;
5029 request.method = "GET";
5030 request.url = GURL("http://www.google.com/");
5031 request.load_flags = 0;
5032 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5033 "http://the.previous.site.com/");
5034
5035 SessionDependencies session_deps;
5036 scoped_ptr<HttpTransaction> trans(
5037 new HttpNetworkTransaction(CreateSession(&session_deps)));
5038
5039 MockWrite data_writes[] = {
5040 MockWrite("GET / HTTP/1.1\r\n"
5041 "Host: www.google.com\r\n"
5042 "Connection: keep-alive\r\n"
5043 "Referer: http://the.previous.site.com/\r\n\r\n"),
5044 };
5045
5046 // Lastly, the server responds with the actual content.
5047 MockRead data_reads[] = {
5048 MockRead("HTTP/1.0 200 OK\r\n"),
5049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5050 MockRead("Content-Length: 100\r\n\r\n"),
5051 MockRead(SYNCHRONOUS, OK),
5052 };
5053
5054 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5055 data_writes, arraysize(data_writes));
5056 session_deps.socket_factory.AddSocketDataProvider(&data);
5057
5058 TestCompletionCallback callback;
5059
5060 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5061 EXPECT_EQ(ERR_IO_PENDING, rv);
5062
5063 rv = callback.WaitForResult();
5064 EXPECT_EQ(OK, rv);
5065 }
5066
5067 TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
5068 HttpRequestInfo request;
5069 request.method = "POST";
5070 request.url = GURL("http://www.google.com/");
5071
5072 SessionDependencies session_deps;
5073 scoped_ptr<HttpTransaction> trans(
5074 new HttpNetworkTransaction(CreateSession(&session_deps)));
5075
5076 MockWrite data_writes[] = {
5077 MockWrite("POST / HTTP/1.1\r\n"
5078 "Host: www.google.com\r\n"
5079 "Connection: keep-alive\r\n"
5080 "Content-Length: 0\r\n\r\n"),
5081 };
5082
5083 // Lastly, the server responds with the actual content.
5084 MockRead data_reads[] = {
5085 MockRead("HTTP/1.0 200 OK\r\n"),
5086 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5087 MockRead("Content-Length: 100\r\n\r\n"),
5088 MockRead(SYNCHRONOUS, OK),
5089 };
5090
5091 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5092 data_writes, arraysize(data_writes));
5093 session_deps.socket_factory.AddSocketDataProvider(&data);
5094
5095 TestCompletionCallback callback;
5096
5097 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5098 EXPECT_EQ(ERR_IO_PENDING, rv);
5099
5100 rv = callback.WaitForResult();
5101 EXPECT_EQ(OK, rv);
5102 }
5103
5104 TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
5105 HttpRequestInfo request;
5106 request.method = "PUT";
5107 request.url = GURL("http://www.google.com/");
5108
5109 SessionDependencies session_deps;
5110 scoped_ptr<HttpTransaction> trans(
5111 new HttpNetworkTransaction(CreateSession(&session_deps)));
5112
5113 MockWrite data_writes[] = {
5114 MockWrite("PUT / HTTP/1.1\r\n"
5115 "Host: www.google.com\r\n"
5116 "Connection: keep-alive\r\n"
5117 "Content-Length: 0\r\n\r\n"),
5118 };
5119
5120 // Lastly, the server responds with the actual content.
5121 MockRead data_reads[] = {
5122 MockRead("HTTP/1.0 200 OK\r\n"),
5123 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5124 MockRead("Content-Length: 100\r\n\r\n"),
5125 MockRead(SYNCHRONOUS, OK),
5126 };
5127
5128 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5129 data_writes, arraysize(data_writes));
5130 session_deps.socket_factory.AddSocketDataProvider(&data);
5131
5132 TestCompletionCallback callback;
5133
5134 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5135 EXPECT_EQ(ERR_IO_PENDING, rv);
5136
5137 rv = callback.WaitForResult();
5138 EXPECT_EQ(OK, rv);
5139 }
5140
5141 TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
5142 HttpRequestInfo request;
5143 request.method = "HEAD";
5144 request.url = GURL("http://www.google.com/");
5145
5146 SessionDependencies session_deps;
5147 scoped_ptr<HttpTransaction> trans(
5148 new HttpNetworkTransaction(CreateSession(&session_deps)));
5149
5150 MockWrite data_writes[] = {
5151 MockWrite("HEAD / HTTP/1.1\r\n"
5152 "Host: www.google.com\r\n"
5153 "Connection: keep-alive\r\n"
5154 "Content-Length: 0\r\n\r\n"),
5155 };
5156
5157 // Lastly, the server responds with the actual content.
5158 MockRead data_reads[] = {
5159 MockRead("HTTP/1.0 200 OK\r\n"),
5160 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5161 MockRead("Content-Length: 100\r\n\r\n"),
5162 MockRead(SYNCHRONOUS, OK),
5163 };
5164
5165 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5166 data_writes, arraysize(data_writes));
5167 session_deps.socket_factory.AddSocketDataProvider(&data);
5168
5169 TestCompletionCallback callback;
5170
5171 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5172 EXPECT_EQ(ERR_IO_PENDING, rv);
5173
5174 rv = callback.WaitForResult();
5175 EXPECT_EQ(OK, rv);
5176 }
5177
5178 TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
5179 HttpRequestInfo request;
5180 request.method = "GET";
5181 request.url = GURL("http://www.google.com/");
5182 request.load_flags = LOAD_BYPASS_CACHE;
5183
5184 SessionDependencies session_deps;
5185 scoped_ptr<HttpTransaction> trans(
5186 new HttpNetworkTransaction(CreateSession(&session_deps)));
5187
5188 MockWrite data_writes[] = {
5189 MockWrite("GET / HTTP/1.1\r\n"
5190 "Host: www.google.com\r\n"
5191 "Connection: keep-alive\r\n"
5192 "Pragma: no-cache\r\n"
5193 "Cache-Control: no-cache\r\n\r\n"),
5194 };
5195
5196 // Lastly, the server responds with the actual content.
5197 MockRead data_reads[] = {
5198 MockRead("HTTP/1.0 200 OK\r\n"),
5199 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5200 MockRead("Content-Length: 100\r\n\r\n"),
5201 MockRead(SYNCHRONOUS, OK),
5202 };
5203
5204 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5205 data_writes, arraysize(data_writes));
5206 session_deps.socket_factory.AddSocketDataProvider(&data);
5207
5208 TestCompletionCallback callback;
5209
5210 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5211 EXPECT_EQ(ERR_IO_PENDING, rv);
5212
5213 rv = callback.WaitForResult();
5214 EXPECT_EQ(OK, rv);
5215 }
5216
5217 TEST_F(HttpNetworkTransactionTest,
5218 BuildRequest_CacheControlValidateCache) {
5219 HttpRequestInfo request;
5220 request.method = "GET";
5221 request.url = GURL("http://www.google.com/");
5222 request.load_flags = LOAD_VALIDATE_CACHE;
5223
5224 SessionDependencies session_deps;
5225 scoped_ptr<HttpTransaction> trans(
5226 new HttpNetworkTransaction(CreateSession(&session_deps)));
5227
5228 MockWrite data_writes[] = {
5229 MockWrite("GET / HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n"
5232 "Cache-Control: max-age=0\r\n\r\n"),
5233 };
5234
5235 // Lastly, the server responds with the actual content.
5236 MockRead data_reads[] = {
5237 MockRead("HTTP/1.0 200 OK\r\n"),
5238 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5239 MockRead("Content-Length: 100\r\n\r\n"),
5240 MockRead(SYNCHRONOUS, OK),
5241 };
5242
5243 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5244 data_writes, arraysize(data_writes));
5245 session_deps.socket_factory.AddSocketDataProvider(&data);
5246
5247 TestCompletionCallback callback;
5248
5249 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5250 EXPECT_EQ(ERR_IO_PENDING, rv);
5251
5252 rv = callback.WaitForResult();
5253 EXPECT_EQ(OK, rv);
5254 }
5255
5256 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
5257 HttpRequestInfo request;
5258 request.method = "GET";
5259 request.url = GURL("http://www.google.com/");
5260 request.extra_headers.SetHeader("FooHeader", "Bar");
5261
5262 SessionDependencies session_deps;
5263 scoped_ptr<HttpTransaction> trans(
5264 new HttpNetworkTransaction(CreateSession(&session_deps)));
5265
5266 MockWrite data_writes[] = {
5267 MockWrite("GET / HTTP/1.1\r\n"
5268 "Host: www.google.com\r\n"
5269 "Connection: keep-alive\r\n"
5270 "FooHeader: Bar\r\n\r\n"),
5271 };
5272
5273 // Lastly, the server responds with the actual content.
5274 MockRead data_reads[] = {
5275 MockRead("HTTP/1.0 200 OK\r\n"),
5276 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5277 MockRead("Content-Length: 100\r\n\r\n"),
5278 MockRead(SYNCHRONOUS, OK),
5279 };
5280
5281 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5282 data_writes, arraysize(data_writes));
5283 session_deps.socket_factory.AddSocketDataProvider(&data);
5284
5285 TestCompletionCallback callback;
5286
5287 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5288 EXPECT_EQ(ERR_IO_PENDING, rv);
5289
5290 rv = callback.WaitForResult();
5291 EXPECT_EQ(OK, rv);
5292 }
5293
5294 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
5295 HttpRequestInfo request;
5296 request.method = "GET";
5297 request.url = GURL("http://www.google.com/");
5298 request.extra_headers.SetHeader("referer", "www.foo.com");
5299 request.extra_headers.SetHeader("hEllo", "Kitty");
5300 request.extra_headers.SetHeader("FoO", "bar");
5301
5302 SessionDependencies session_deps;
5303 scoped_ptr<HttpTransaction> trans(
5304 new HttpNetworkTransaction(CreateSession(&session_deps)));
5305
5306 MockWrite data_writes[] = {
5307 MockWrite("GET / HTTP/1.1\r\n"
5308 "Host: www.google.com\r\n"
5309 "Connection: keep-alive\r\n"
5310 "referer: www.foo.com\r\n"
5311 "hEllo: Kitty\r\n"
5312 "FoO: bar\r\n\r\n"),
5313 };
5314
5315 // Lastly, the server responds with the actual content.
5316 MockRead data_reads[] = {
5317 MockRead("HTTP/1.0 200 OK\r\n"),
5318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5319 MockRead("Content-Length: 100\r\n\r\n"),
5320 MockRead(SYNCHRONOUS, OK),
5321 };
5322
5323 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5324 data_writes, arraysize(data_writes));
5325 session_deps.socket_factory.AddSocketDataProvider(&data);
5326
5327 TestCompletionCallback callback;
5328
5329 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5330 EXPECT_EQ(ERR_IO_PENDING, rv);
5331
5332 rv = callback.WaitForResult();
5333 EXPECT_EQ(OK, rv);
5334 }
5335
5336 // http://crbug.com/112682
5337 #if defined(OS_MACOSX)
5338 #define MAYBE_SOCKS4_HTTP_GET DISABLED_SOCKS4_HTTP_GET
5339 #else
5340 #define MAYBE_SOCKS4_HTTP_GET SOCKS4_HTTP_GET
5341 #endif
5342
5343 TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_HTTP_GET) {
5344 HttpRequestInfo request;
5345 request.method = "GET";
5346 request.url = GURL("http://www.google.com/");
5347 request.load_flags = 0;
5348
5349 SessionDependencies session_deps(
5350 ProxyService::CreateFixed("socks4://myproxy:1080"));
5351
5352 scoped_ptr<HttpTransaction> trans(
5353 new HttpNetworkTransaction(CreateSession(&session_deps)));
5354
5355 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5356 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5357
5358 MockWrite data_writes[] = {
5359 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
5360 MockWrite("GET / HTTP/1.1\r\n"
5361 "Host: www.google.com\r\n"
5362 "Connection: keep-alive\r\n\r\n")
5363 };
5364
5365 MockRead data_reads[] = {
5366 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
5367 MockRead("HTTP/1.0 200 OK\r\n"),
5368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5369 MockRead("Payload"),
5370 MockRead(SYNCHRONOUS, OK)
5371 };
5372
5373 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5374 data_writes, arraysize(data_writes));
5375 session_deps.socket_factory.AddSocketDataProvider(&data);
5376
5377 TestCompletionCallback callback;
5378
5379 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5380 EXPECT_EQ(ERR_IO_PENDING, rv);
5381
5382 rv = callback.WaitForResult();
5383 EXPECT_EQ(OK, rv);
5384
5385 const HttpResponseInfo* response = trans->GetResponseInfo();
5386 ASSERT_TRUE(response != NULL);
5387
5388 std::string response_text;
5389 rv = ReadTransaction(trans.get(), &response_text);
5390 EXPECT_EQ(OK, rv);
5391 EXPECT_EQ("Payload", response_text);
5392 }
5393
5394 // http://crbug.com/112682
5395 #if defined(OS_MACOSX)
5396 #define MAYBE_SOCKS4_SSL_GET DISABLED_SOCKS4_SSL_GET
5397 #else
5398 #define MAYBE_SOCKS4_SSL_GET SOCKS4_SSL_GET
5399 #endif
5400
5401 TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_SSL_GET) {
5402 HttpRequestInfo request;
5403 request.method = "GET";
5404 request.url = GURL("https://www.google.com/");
5405 request.load_flags = 0;
5406
5407 SessionDependencies session_deps(
5408 ProxyService::CreateFixed("socks4://myproxy:1080"));
5409
5410 scoped_ptr<HttpTransaction> trans(
5411 new HttpNetworkTransaction(CreateSession(&session_deps)));
5412
5413 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5414 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5415
5416 MockWrite data_writes[] = {
5417 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
5418 arraysize(write_buffer)),
5419 MockWrite("GET / HTTP/1.1\r\n"
5420 "Host: www.google.com\r\n"
5421 "Connection: keep-alive\r\n\r\n")
5422 };
5423
5424 MockRead data_reads[] = {
5425 MockWrite(ASYNC, reinterpret_cast<char*>(read_buffer),
5426 arraysize(read_buffer)),
5427 MockRead("HTTP/1.0 200 OK\r\n"),
5428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5429 MockRead("Payload"),
5430 MockRead(SYNCHRONOUS, OK)
5431 };
5432
5433 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5434 data_writes, arraysize(data_writes));
5435 session_deps.socket_factory.AddSocketDataProvider(&data);
5436
5437 SSLSocketDataProvider ssl(ASYNC, OK);
5438 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5439
5440 TestCompletionCallback callback;
5441
5442 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5443 EXPECT_EQ(ERR_IO_PENDING, rv);
5444
5445 rv = callback.WaitForResult();
5446 EXPECT_EQ(OK, rv);
5447
5448 const HttpResponseInfo* response = trans->GetResponseInfo();
5449 ASSERT_TRUE(response != NULL);
5450
5451 std::string response_text;
5452 rv = ReadTransaction(trans.get(), &response_text);
5453 EXPECT_EQ(OK, rv);
5454 EXPECT_EQ("Payload", response_text);
5455 }
5456
5457 TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
5458 HttpRequestInfo request;
5459 request.method = "GET";
5460 request.url = GURL("http://www.google.com/");
5461 request.load_flags = 0;
5462
5463 SessionDependencies session_deps(
5464 ProxyService::CreateFixed("socks5://myproxy:1080"));
5465
5466 scoped_ptr<HttpTransaction> trans(
5467 new HttpNetworkTransaction(CreateSession(&session_deps)));
5468
5469 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5470 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
5471 const char kSOCKS5OkRequest[] = {
5472 0x05, // Version
5473 0x01, // Command (CONNECT)
5474 0x00, // Reserved.
5475 0x03, // Address type (DOMAINNAME).
5476 0x0E, // Length of domain (14)
5477 // Domain string:
5478 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5479 0x00, 0x50, // 16-bit port (80)
5480 };
5481 const char kSOCKS5OkResponse[] =
5482 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5483
5484 MockWrite data_writes[] = {
5485 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5486 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5487 MockWrite("GET / HTTP/1.1\r\n"
5488 "Host: www.google.com\r\n"
5489 "Connection: keep-alive\r\n\r\n")
5490 };
5491
5492 MockRead data_reads[] = {
5493 MockWrite(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5494 MockWrite(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5495 MockRead("HTTP/1.0 200 OK\r\n"),
5496 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5497 MockRead("Payload"),
5498 MockRead(SYNCHRONOUS, OK)
5499 };
5500
5501 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5502 data_writes, arraysize(data_writes));
5503 session_deps.socket_factory.AddSocketDataProvider(&data);
5504
5505 TestCompletionCallback callback;
5506
5507 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5508 EXPECT_EQ(ERR_IO_PENDING, rv);
5509
5510 rv = callback.WaitForResult();
5511 EXPECT_EQ(OK, rv);
5512
5513 const HttpResponseInfo* response = trans->GetResponseInfo();
5514 ASSERT_TRUE(response != NULL);
5515
5516 std::string response_text;
5517 rv = ReadTransaction(trans.get(), &response_text);
5518 EXPECT_EQ(OK, rv);
5519 EXPECT_EQ("Payload", response_text);
5520 }
5521
5522 TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
5523 HttpRequestInfo request;
5524 request.method = "GET";
5525 request.url = GURL("https://www.google.com/");
5526 request.load_flags = 0;
5527
5528 SessionDependencies session_deps(
5529 ProxyService::CreateFixed("socks5://myproxy:1080"));
5530
5531 scoped_ptr<HttpTransaction> trans(
5532 new HttpNetworkTransaction(CreateSession(&session_deps)));
5533
5534 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5535 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
5536 const unsigned char kSOCKS5OkRequest[] = {
5537 0x05, // Version
5538 0x01, // Command (CONNECT)
5539 0x00, // Reserved.
5540 0x03, // Address type (DOMAINNAME).
5541 0x0E, // Length of domain (14)
5542 // Domain string:
5543 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5544 0x01, 0xBB, // 16-bit port (443)
5545 };
5546
5547 const char kSOCKS5OkResponse[] =
5548 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5549
5550 MockWrite data_writes[] = {
5551 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5552 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5553 arraysize(kSOCKS5OkRequest)),
5554 MockWrite("GET / HTTP/1.1\r\n"
5555 "Host: www.google.com\r\n"
5556 "Connection: keep-alive\r\n\r\n")
5557 };
5558
5559 MockRead data_reads[] = {
5560 MockWrite(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5561 MockWrite(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5562 MockRead("HTTP/1.0 200 OK\r\n"),
5563 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5564 MockRead("Payload"),
5565 MockRead(SYNCHRONOUS, OK)
5566 };
5567
5568 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5569 data_writes, arraysize(data_writes));
5570 session_deps.socket_factory.AddSocketDataProvider(&data);
5571
5572 SSLSocketDataProvider ssl(ASYNC, OK);
5573 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5574
5575 TestCompletionCallback callback;
5576
5577 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5578 EXPECT_EQ(ERR_IO_PENDING, rv);
5579
5580 rv = callback.WaitForResult();
5581 EXPECT_EQ(OK, rv);
5582
5583 const HttpResponseInfo* response = trans->GetResponseInfo();
5584 ASSERT_TRUE(response != NULL);
5585
5586 std::string response_text;
5587 rv = ReadTransaction(trans.get(), &response_text);
5588 EXPECT_EQ(OK, rv);
5589 EXPECT_EQ("Payload", response_text);
5590 }
5591
5592 // Tests that for connection endpoints the group names are correctly set.
5593
5594 struct GroupNameTest {
5595 std::string proxy_server;
5596 std::string url;
5597 std::string expected_group_name;
5598 bool ssl;
5599 };
5600
5601 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5602 SessionDependencies* session_deps) {
5603 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
5604
5605 HttpServerProperties* http_server_properties =
5606 session->http_server_properties();
5607 http_server_properties->SetAlternateProtocol(
5608 HostPortPair("host.with.alternate", 80), 443,
5609 NPN_SPDY_21);
5610
5611 return session;
5612 }
5613
5614 int GroupNameTransactionHelper(
5615 const std::string& url,
5616 const scoped_refptr<HttpNetworkSession>& session) {
5617 HttpRequestInfo request;
5618 request.method = "GET";
5619 request.url = GURL(url);
5620 request.load_flags = 0;
5621
5622 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5623
5624 TestCompletionCallback callback;
5625
5626 // We do not complete this request, the dtor will clean the transaction up.
5627 return trans->Start(&request, callback.callback(), BoundNetLog());
5628 }
5629
5630 TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5631 const GroupNameTest tests[] = {
5632 {
5633 "", // unused
5634 "http://www.google.com/direct",
5635 "www.google.com:80",
5636 false,
5637 },
5638 {
5639 "", // unused
5640 "http://[2001:1418:13:1::25]/direct",
5641 "[2001:1418:13:1::25]:80",
5642 false,
5643 },
5644
5645 // SSL Tests
5646 {
5647 "", // unused
5648 "https://www.google.com/direct_ssl",
5649 "ssl/www.google.com:443",
5650 true,
5651 },
5652 {
5653 "", // unused
5654 "https://[2001:1418:13:1::25]/direct",
5655 "ssl/[2001:1418:13:1::25]:443",
5656 true,
5657 },
5658 {
5659 "", // unused
5660 "http://host.with.alternate/direct",
5661 "ssl/host.with.alternate:443",
5662 true,
5663 },
5664 };
5665
5666 HttpStreamFactory::set_use_alternate_protocols(true);
5667
5668 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5669 SessionDependencies session_deps(
5670 ProxyService::CreateFixed(tests[i].proxy_server));
5671 scoped_refptr<HttpNetworkSession> session(
5672 SetupSessionForGroupNameTests(&session_deps));
5673
5674 HttpNetworkSessionPeer peer(session);
5675 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5676 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5677 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5678 new CaptureGroupNameSSLSocketPool(NULL, NULL);
5679 MockClientSocketPoolManager* mock_pool_manager =
5680 new MockClientSocketPoolManager;
5681 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
5682 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
5683 peer.SetClientSocketPoolManager(mock_pool_manager);
5684
5685 EXPECT_EQ(ERR_IO_PENDING,
5686 GroupNameTransactionHelper(tests[i].url, session));
5687 if (tests[i].ssl)
5688 EXPECT_EQ(tests[i].expected_group_name,
5689 ssl_conn_pool->last_group_name_received());
5690 else
5691 EXPECT_EQ(tests[i].expected_group_name,
5692 transport_conn_pool->last_group_name_received());
5693 }
5694
5695 HttpStreamFactory::set_use_alternate_protocols(false);
5696 }
5697
5698 TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5699 const GroupNameTest tests[] = {
5700 {
5701 "http_proxy",
5702 "http://www.google.com/http_proxy_normal",
5703 "www.google.com:80",
5704 false,
5705 },
5706
5707 // SSL Tests
5708 {
5709 "http_proxy",
5710 "https://www.google.com/http_connect_ssl",
5711 "ssl/www.google.com:443",
5712 true,
5713 },
5714
5715 {
5716 "http_proxy",
5717 "http://host.with.alternate/direct",
5718 "ssl/host.with.alternate:443",
5719 true,
5720 },
5721 };
5722
5723 HttpStreamFactory::set_use_alternate_protocols(true);
5724
5725 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5726 SessionDependencies session_deps(
5727 ProxyService::CreateFixed(tests[i].proxy_server));
5728 scoped_refptr<HttpNetworkSession> session(
5729 SetupSessionForGroupNameTests(&session_deps));
5730
5731 HttpNetworkSessionPeer peer(session);
5732
5733 HostPortPair proxy_host("http_proxy", 80);
5734 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5735 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
5736 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5737 new CaptureGroupNameSSLSocketPool(NULL, NULL);
5738
5739 MockClientSocketPoolManager* mock_pool_manager =
5740 new MockClientSocketPoolManager;
5741 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
5742 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5743 peer.SetClientSocketPoolManager(mock_pool_manager);
5744
5745 EXPECT_EQ(ERR_IO_PENDING,
5746 GroupNameTransactionHelper(tests[i].url, session));
5747 if (tests[i].ssl)
5748 EXPECT_EQ(tests[i].expected_group_name,
5749 ssl_conn_pool->last_group_name_received());
5750 else
5751 EXPECT_EQ(tests[i].expected_group_name,
5752 http_proxy_pool->last_group_name_received());
5753 }
5754
5755 HttpStreamFactory::set_use_alternate_protocols(false);
5756 }
5757
5758 TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5759 const GroupNameTest tests[] = {
5760 {
5761 "socks4://socks_proxy:1080",
5762 "http://www.google.com/socks4_direct",
5763 "socks4/www.google.com:80",
5764 false,
5765 },
5766 {
5767 "socks5://socks_proxy:1080",
5768 "http://www.google.com/socks5_direct",
5769 "socks5/www.google.com:80",
5770 false,
5771 },
5772
5773 // SSL Tests
5774 {
5775 "socks4://socks_proxy:1080",
5776 "https://www.google.com/socks4_ssl",
5777 "socks4/ssl/www.google.com:443",
5778 true,
5779 },
5780 {
5781 "socks5://socks_proxy:1080",
5782 "https://www.google.com/socks5_ssl",
5783 "socks5/ssl/www.google.com:443",
5784 true,
5785 },
5786
5787 {
5788 "socks4://socks_proxy:1080",
5789 "http://host.with.alternate/direct",
5790 "socks4/ssl/host.with.alternate:443",
5791 true,
5792 },
5793 };
5794
5795 HttpStreamFactory::set_use_alternate_protocols(true);
5796
5797 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5798 SessionDependencies session_deps(
5799 ProxyService::CreateFixed(tests[i].proxy_server));
5800 scoped_refptr<HttpNetworkSession> session(
5801 SetupSessionForGroupNameTests(&session_deps));
5802
5803 HttpNetworkSessionPeer peer(session);
5804
5805 HostPortPair proxy_host("socks_proxy", 1080);
5806 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5807 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
5808 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5809 new CaptureGroupNameSSLSocketPool(NULL, NULL);
5810
5811 MockClientSocketPoolManager* mock_pool_manager =
5812 new MockClientSocketPoolManager;
5813 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
5814 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5815 peer.SetClientSocketPoolManager(mock_pool_manager);
5816
5817 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5818
5819 EXPECT_EQ(ERR_IO_PENDING,
5820 GroupNameTransactionHelper(tests[i].url, session));
5821 if (tests[i].ssl)
5822 EXPECT_EQ(tests[i].expected_group_name,
5823 ssl_conn_pool->last_group_name_received());
5824 else
5825 EXPECT_EQ(tests[i].expected_group_name,
5826 socks_conn_pool->last_group_name_received());
5827 }
5828
5829 HttpStreamFactory::set_use_alternate_protocols(false);
5830 }
5831
5832 TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
5833 HttpRequestInfo request;
5834 request.method = "GET";
5835 request.url = GURL("http://www.google.com/");
5836
5837 SessionDependencies session_deps(
5838 ProxyService::CreateFixed("myproxy:70;foobar:80"));
5839
5840 // This simulates failure resolving all hostnames; that means we will fail
5841 // connecting to both proxies (myproxy:70 and foobar:80).
5842 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5843
5844 scoped_ptr<HttpTransaction> trans(
5845 new HttpNetworkTransaction(CreateSession(&session_deps)));
5846
5847 TestCompletionCallback callback;
5848
5849 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5850 EXPECT_EQ(ERR_IO_PENDING, rv);
5851
5852 rv = callback.WaitForResult();
5853 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
5854 }
5855
5856 // Base test to make sure that when the load flags for a request specify to
5857 // bypass the cache, the DNS cache is not used.
5858 void BypassHostCacheOnRefreshHelper(int load_flags) {
5859 // Issue a request, asking to bypass the cache(s).
5860 HttpRequestInfo request;
5861 request.method = "GET";
5862 request.load_flags = load_flags;
5863 request.url = GURL("http://www.google.com/");
5864
5865 SessionDependencies session_deps;
5866
5867 // Select a host resolver that does caching.
5868 session_deps.host_resolver.reset(new MockCachingHostResolver);
5869
5870 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
5871 CreateSession(&session_deps)));
5872
5873 // Warm up the host cache so it has an entry for "www.google.com".
5874 AddressList addrlist;
5875 TestCompletionCallback callback;
5876 int rv = session_deps.host_resolver->Resolve(
5877 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
5878 callback.callback(), NULL, BoundNetLog());
5879 EXPECT_EQ(ERR_IO_PENDING, rv);
5880 rv = callback.WaitForResult();
5881 EXPECT_EQ(OK, rv);
5882
5883 // Verify that it was added to host cache, by doing a subsequent async lookup
5884 // and confirming it completes synchronously.
5885 rv = session_deps.host_resolver->Resolve(
5886 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
5887 callback.callback(), NULL, BoundNetLog());
5888 ASSERT_EQ(OK, rv);
5889
5890 // Inject a failure the next time that "www.google.com" is resolved. This way
5891 // we can tell if the next lookup hit the cache, or the "network".
5892 // (cache --> success, "network" --> failure).
5893 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
5894
5895 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5896 // first read -- this won't be reached as the host resolution will fail first.
5897 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
5898 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5899 session_deps.socket_factory.AddSocketDataProvider(&data);
5900
5901 // Run the request.
5902 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5903 ASSERT_EQ(ERR_IO_PENDING, rv);
5904 rv = callback.WaitForResult();
5905
5906 // If we bypassed the cache, we would have gotten a failure while resolving
5907 // "www.google.com".
5908 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5909 }
5910
5911 // There are multiple load flags that should trigger the host cache bypass.
5912 // Test each in isolation:
5913 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5914 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5915 }
5916
5917 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5918 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5919 }
5920
5921 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5922 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5923 }
5924
5925 // Make sure we can handle an error when writing the request.
5926 TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5927 SessionDependencies session_deps;
5928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5929
5930 HttpRequestInfo request;
5931 request.method = "GET";
5932 request.url = GURL("http://www.foo.com/");
5933 request.load_flags = 0;
5934
5935 MockWrite write_failure[] = {
5936 MockWrite(ASYNC, ERR_CONNECTION_RESET),
5937 };
5938 StaticSocketDataProvider data(NULL, 0,
5939 write_failure, arraysize(write_failure));
5940 session_deps.socket_factory.AddSocketDataProvider(&data);
5941
5942 TestCompletionCallback callback;
5943
5944 scoped_ptr<HttpTransaction> trans(
5945 new HttpNetworkTransaction(CreateSession(&session_deps)));
5946
5947 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5948 EXPECT_EQ(ERR_IO_PENDING, rv);
5949
5950 rv = callback.WaitForResult();
5951 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5952 }
5953
5954 // Check that a connection closed after the start of the headers finishes ok.
5955 TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5956 SessionDependencies session_deps;
5957 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5958
5959 HttpRequestInfo request;
5960 request.method = "GET";
5961 request.url = GURL("http://www.foo.com/");
5962 request.load_flags = 0;
5963
5964 MockRead data_reads[] = {
5965 MockRead("HTTP/1."),
5966 MockRead(SYNCHRONOUS, OK),
5967 };
5968
5969 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5970 session_deps.socket_factory.AddSocketDataProvider(&data);
5971
5972 TestCompletionCallback callback;
5973
5974 scoped_ptr<HttpTransaction> trans(
5975 new HttpNetworkTransaction(CreateSession(&session_deps)));
5976
5977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5978 EXPECT_EQ(ERR_IO_PENDING, rv);
5979
5980 rv = callback.WaitForResult();
5981 EXPECT_EQ(OK, rv);
5982
5983 const HttpResponseInfo* response = trans->GetResponseInfo();
5984 ASSERT_TRUE(response != NULL);
5985
5986 EXPECT_TRUE(response->headers != NULL);
5987 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5988
5989 std::string response_data;
5990 rv = ReadTransaction(trans.get(), &response_data);
5991 EXPECT_EQ(OK, rv);
5992 EXPECT_EQ("", response_data);
5993 }
5994
5995 // Make sure that a dropped connection while draining the body for auth
5996 // restart does the right thing.
5997 TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5998 SessionDependencies session_deps;
5999 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6000
6001 HttpRequestInfo request;
6002 request.method = "GET";
6003 request.url = GURL("http://www.google.com/");
6004 request.load_flags = 0;
6005
6006 MockWrite data_writes1[] = {
6007 MockWrite("GET / HTTP/1.1\r\n"
6008 "Host: www.google.com\r\n"
6009 "Connection: keep-alive\r\n\r\n"),
6010 };
6011
6012 MockRead data_reads1[] = {
6013 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6014 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6015 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6016 MockRead("Content-Length: 14\r\n\r\n"),
6017 MockRead("Unauth"),
6018 MockRead(ASYNC, ERR_CONNECTION_RESET),
6019 };
6020
6021 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6022 data_writes1, arraysize(data_writes1));
6023 session_deps.socket_factory.AddSocketDataProvider(&data1);
6024
6025 // After calling trans->RestartWithAuth(), this is the request we should
6026 // be issuing -- the final header line contains the credentials.
6027 MockWrite data_writes2[] = {
6028 MockWrite("GET / HTTP/1.1\r\n"
6029 "Host: www.google.com\r\n"
6030 "Connection: keep-alive\r\n"
6031 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6032 };
6033
6034 // Lastly, the server responds with the actual content.
6035 MockRead data_reads2[] = {
6036 MockRead("HTTP/1.1 200 OK\r\n"),
6037 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6038 MockRead("Content-Length: 100\r\n\r\n"),
6039 MockRead(SYNCHRONOUS, OK),
6040 };
6041
6042 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6043 data_writes2, arraysize(data_writes2));
6044 session_deps.socket_factory.AddSocketDataProvider(&data2);
6045
6046 TestCompletionCallback callback1;
6047
6048 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6049
6050 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6051 EXPECT_EQ(ERR_IO_PENDING, rv);
6052
6053 rv = callback1.WaitForResult();
6054 EXPECT_EQ(OK, rv);
6055
6056 const HttpResponseInfo* response = trans->GetResponseInfo();
6057 ASSERT_TRUE(response != NULL);
6058 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6059
6060 TestCompletionCallback callback2;
6061
6062 rv = trans->RestartWithAuth(
6063 AuthCredentials(kFoo, kBar), callback2.callback());
6064 EXPECT_EQ(ERR_IO_PENDING, rv);
6065
6066 rv = callback2.WaitForResult();
6067 EXPECT_EQ(OK, rv);
6068
6069 response = trans->GetResponseInfo();
6070 ASSERT_TRUE(response != NULL);
6071 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6072 EXPECT_EQ(100, response->headers->GetContentLength());
6073 }
6074
6075 // Test HTTPS connections going through a proxy that sends extra data.
6076 TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
6077 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
6078
6079 HttpRequestInfo request;
6080 request.method = "GET";
6081 request.url = GURL("https://www.google.com/");
6082 request.load_flags = 0;
6083
6084 MockRead proxy_reads[] = {
6085 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6086 MockRead(SYNCHRONOUS, OK)
6087 };
6088
6089 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
6090 SSLSocketDataProvider ssl(ASYNC, OK);
6091
6092 session_deps.socket_factory.AddSocketDataProvider(&data);
6093 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6094
6095 TestCompletionCallback callback;
6096
6097 session_deps.socket_factory.ResetNextMockIndexes();
6098
6099 scoped_ptr<HttpTransaction> trans(
6100 new HttpNetworkTransaction(CreateSession(&session_deps)));
6101
6102 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6103 EXPECT_EQ(ERR_IO_PENDING, rv);
6104
6105 rv = callback.WaitForResult();
6106 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6107 }
6108
6109 TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
6110 HttpRequestInfo request;
6111 request.method = "GET";
6112 request.url = GURL("http://www.google.com/");
6113 request.load_flags = 0;
6114
6115 SessionDependencies session_deps;
6116 scoped_ptr<HttpTransaction> trans(
6117 new HttpNetworkTransaction(CreateSession(&session_deps)));
6118
6119 MockRead data_reads[] = {
6120 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6121 MockRead(SYNCHRONOUS, OK),
6122 };
6123
6124 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6125 session_deps.socket_factory.AddSocketDataProvider(&data);
6126
6127 TestCompletionCallback callback;
6128
6129 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6130 EXPECT_EQ(ERR_IO_PENDING, rv);
6131
6132 EXPECT_EQ(OK, callback.WaitForResult());
6133
6134 const HttpResponseInfo* response = trans->GetResponseInfo();
6135 ASSERT_TRUE(response != NULL);
6136
6137 EXPECT_TRUE(response->headers != NULL);
6138 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6139
6140 std::string response_data;
6141 rv = ReadTransaction(trans.get(), &response_data);
6142 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
6143 }
6144
6145 TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
6146 HttpRequestInfo request;
6147 request.method = "POST";
6148 request.url = GURL("http://www.google.com/upload");
6149 request.upload_data = new UploadData;
6150 request.load_flags = 0;
6151
6152 SessionDependencies session_deps;
6153 scoped_ptr<HttpTransaction> trans(
6154 new HttpNetworkTransaction(CreateSession(&session_deps)));
6155
6156 FilePath temp_file_path;
6157 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6158 const uint64 kFakeSize = 100000; // file is actually blank
6159
6160 std::vector<UploadData::Element> elements;
6161 UploadData::Element element;
6162 element.SetToFilePath(temp_file_path);
6163 element.SetContentLength(kFakeSize);
6164 elements.push_back(element);
6165 request.upload_data->SetElements(elements);
6166 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLengthSync());
6167
6168 MockRead data_reads[] = {
6169 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6170 MockRead("hello world"),
6171 MockRead(SYNCHRONOUS, OK),
6172 };
6173 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6174 session_deps.socket_factory.AddSocketDataProvider(&data);
6175
6176 TestCompletionCallback callback;
6177
6178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6179 EXPECT_EQ(ERR_IO_PENDING, rv);
6180
6181 rv = callback.WaitForResult();
6182 EXPECT_EQ(OK, rv);
6183
6184 const HttpResponseInfo* response = trans->GetResponseInfo();
6185 ASSERT_TRUE(response != NULL);
6186
6187 EXPECT_TRUE(response->headers != NULL);
6188 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6189
6190 std::string response_data;
6191 rv = ReadTransaction(trans.get(), &response_data);
6192 EXPECT_EQ(OK, rv);
6193 EXPECT_EQ("hello world", response_data);
6194
6195 file_util::Delete(temp_file_path, false);
6196 }
6197
6198 TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
6199 HttpRequestInfo request;
6200 request.method = "POST";
6201 request.url = GURL("http://www.google.com/upload");
6202 request.upload_data = new UploadData;
6203 request.load_flags = 0;
6204
6205 // If we try to upload an unreadable file, the network stack should report
6206 // the file size as zero and upload zero bytes for that file.
6207 SessionDependencies session_deps;
6208 scoped_ptr<HttpTransaction> trans(
6209 new HttpNetworkTransaction(CreateSession(&session_deps)));
6210
6211 FilePath temp_file;
6212 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6213 std::string temp_file_content("Unreadable file.");
6214 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6215 temp_file_content.length()));
6216 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6217
6218 std::vector<UploadData::Element> elements;
6219 UploadData::Element element;
6220 element.SetToFilePath(temp_file);
6221 elements.push_back(element);
6222 request.upload_data->SetElements(elements);
6223
6224 MockRead data_reads[] = {
6225 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6226 MockRead(SYNCHRONOUS, OK),
6227 };
6228 MockWrite data_writes[] = {
6229 MockWrite("POST /upload HTTP/1.1\r\n"
6230 "Host: www.google.com\r\n"
6231 "Connection: keep-alive\r\n"
6232 "Content-Length: 0\r\n\r\n"),
6233 MockWrite(SYNCHRONOUS, OK),
6234 };
6235 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6236 arraysize(data_writes));
6237 session_deps.socket_factory.AddSocketDataProvider(&data);
6238
6239 TestCompletionCallback callback;
6240
6241 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6242 EXPECT_EQ(ERR_IO_PENDING, rv);
6243
6244 rv = callback.WaitForResult();
6245 EXPECT_EQ(OK, rv);
6246
6247 const HttpResponseInfo* response = trans->GetResponseInfo();
6248 ASSERT_TRUE(response != NULL);
6249 EXPECT_TRUE(response->headers != NULL);
6250 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6251
6252 file_util::Delete(temp_file, false);
6253 }
6254
6255 TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
6256 HttpRequestInfo request;
6257 request.method = "POST";
6258 request.url = GURL("http://www.google.com/upload");
6259 request.upload_data = new UploadData;
6260 request.load_flags = 0;
6261
6262 SessionDependencies session_deps;
6263 scoped_ptr<HttpTransaction> trans(
6264 new HttpNetworkTransaction(CreateSession(&session_deps)));
6265
6266 FilePath temp_file;
6267 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6268 std::string temp_file_contents("Unreadable file.");
6269 std::string unreadable_contents(temp_file_contents.length(), '\0');
6270 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6271 temp_file_contents.length()));
6272
6273 std::vector<UploadData::Element> elements;
6274 UploadData::Element element;
6275 element.SetToFilePath(temp_file);
6276 elements.push_back(element);
6277 request.upload_data->SetElements(elements);
6278
6279 MockRead data_reads[] = {
6280 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6281 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6282 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6283
6284 MockRead("HTTP/1.1 200 OK\r\n"),
6285 MockRead("Content-Length: 0\r\n\r\n"),
6286 MockRead(SYNCHRONOUS, OK),
6287 };
6288 MockWrite data_writes[] = {
6289 MockWrite("POST /upload HTTP/1.1\r\n"
6290 "Host: www.google.com\r\n"
6291 "Connection: keep-alive\r\n"
6292 "Content-Length: 16\r\n\r\n"),
6293 MockWrite(SYNCHRONOUS, temp_file_contents.c_str()),
6294
6295 MockWrite("POST /upload HTTP/1.1\r\n"
6296 "Host: www.google.com\r\n"
6297 "Connection: keep-alive\r\n"
6298 "Content-Length: 16\r\n"
6299 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6300 MockWrite(SYNCHRONOUS, unreadable_contents.c_str(),
6301 temp_file_contents.length()),
6302 MockWrite(SYNCHRONOUS, OK),
6303 };
6304 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6305 arraysize(data_writes));
6306 session_deps.socket_factory.AddSocketDataProvider(&data);
6307
6308 TestCompletionCallback callback1;
6309
6310 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6311 EXPECT_EQ(ERR_IO_PENDING, rv);
6312
6313 rv = callback1.WaitForResult();
6314 EXPECT_EQ(OK, rv);
6315
6316 const HttpResponseInfo* response = trans->GetResponseInfo();
6317 ASSERT_TRUE(response != NULL);
6318 ASSERT_TRUE(response->headers != NULL);
6319 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6320 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6321
6322 // Now make the file unreadable and try again.
6323 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6324
6325 TestCompletionCallback callback2;
6326
6327 rv = trans->RestartWithAuth(
6328 AuthCredentials(kFoo, kBar), callback2.callback());
6329 EXPECT_EQ(ERR_IO_PENDING, rv);
6330
6331 rv = callback2.WaitForResult();
6332 EXPECT_EQ(OK, rv);
6333
6334 response = trans->GetResponseInfo();
6335 ASSERT_TRUE(response != NULL);
6336 EXPECT_TRUE(response->headers != NULL);
6337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6338 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6339
6340 file_util::Delete(temp_file, false);
6341 }
6342
6343 // Tests that changes to Auth realms are treated like auth rejections.
6344 TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6345 SessionDependencies session_deps;
6346
6347 HttpRequestInfo request;
6348 request.method = "GET";
6349 request.url = GURL("http://www.google.com/");
6350 request.load_flags = 0;
6351
6352 // First transaction will request a resource and receive a Basic challenge
6353 // with realm="first_realm".
6354 MockWrite data_writes1[] = {
6355 MockWrite("GET / HTTP/1.1\r\n"
6356 "Host: www.google.com\r\n"
6357 "Connection: keep-alive\r\n"
6358 "\r\n"),
6359 };
6360 MockRead data_reads1[] = {
6361 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6362 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6363 "\r\n"),
6364 };
6365
6366 // After calling trans->RestartWithAuth(), provide an Authentication header
6367 // for first_realm. The server will reject and provide a challenge with
6368 // second_realm.
6369 MockWrite data_writes2[] = {
6370 MockWrite("GET / HTTP/1.1\r\n"
6371 "Host: www.google.com\r\n"
6372 "Connection: keep-alive\r\n"
6373 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6374 "\r\n"),
6375 };
6376 MockRead data_reads2[] = {
6377 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6378 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6379 "\r\n"),
6380 };
6381
6382 // This again fails, and goes back to first_realm. Make sure that the
6383 // entry is removed from cache.
6384 MockWrite data_writes3[] = {
6385 MockWrite("GET / HTTP/1.1\r\n"
6386 "Host: www.google.com\r\n"
6387 "Connection: keep-alive\r\n"
6388 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6389 "\r\n"),
6390 };
6391 MockRead data_reads3[] = {
6392 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6393 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6394 "\r\n"),
6395 };
6396
6397 // Try one last time (with the correct password) and get the resource.
6398 MockWrite data_writes4[] = {
6399 MockWrite("GET / HTTP/1.1\r\n"
6400 "Host: www.google.com\r\n"
6401 "Connection: keep-alive\r\n"
6402 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6403 "\r\n"),
6404 };
6405 MockRead data_reads4[] = {
6406 MockRead("HTTP/1.1 200 OK\r\n"
6407 "Content-Type: text/html; charset=iso-8859-1\r\n"
6408 "Content-Length: 5\r\n"
6409 "\r\n"
6410 "hello"),
6411 };
6412
6413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6414 data_writes1, arraysize(data_writes1));
6415 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6416 data_writes2, arraysize(data_writes2));
6417 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6418 data_writes3, arraysize(data_writes3));
6419 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6420 data_writes4, arraysize(data_writes4));
6421 session_deps.socket_factory.AddSocketDataProvider(&data1);
6422 session_deps.socket_factory.AddSocketDataProvider(&data2);
6423 session_deps.socket_factory.AddSocketDataProvider(&data3);
6424 session_deps.socket_factory.AddSocketDataProvider(&data4);
6425
6426 TestCompletionCallback callback1;
6427
6428 scoped_ptr<HttpTransaction> trans(
6429 new HttpNetworkTransaction(CreateSession(&session_deps)));
6430
6431 // Issue the first request with Authorize headers. There should be a
6432 // password prompt for first_realm waiting to be filled in after the
6433 // transaction completes.
6434 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6435 EXPECT_EQ(ERR_IO_PENDING, rv);
6436 rv = callback1.WaitForResult();
6437 EXPECT_EQ(OK, rv);
6438 const HttpResponseInfo* response = trans->GetResponseInfo();
6439 ASSERT_TRUE(response != NULL);
6440 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6441 ASSERT_FALSE(challenge == NULL);
6442 EXPECT_FALSE(challenge->is_proxy);
6443 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6444 EXPECT_EQ("first_realm", challenge->realm);
6445 EXPECT_EQ("basic", challenge->scheme);
6446
6447 // Issue the second request with an incorrect password. There should be a
6448 // password prompt for second_realm waiting to be filled in after the
6449 // transaction completes.
6450 TestCompletionCallback callback2;
6451 rv = trans->RestartWithAuth(
6452 AuthCredentials(kFirst, kBaz), callback2.callback());
6453 EXPECT_EQ(ERR_IO_PENDING, rv);
6454 rv = callback2.WaitForResult();
6455 EXPECT_EQ(OK, rv);
6456 response = trans->GetResponseInfo();
6457 ASSERT_TRUE(response != NULL);
6458 challenge = response->auth_challenge.get();
6459 ASSERT_FALSE(challenge == NULL);
6460 EXPECT_FALSE(challenge->is_proxy);
6461 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6462 EXPECT_EQ("second_realm", challenge->realm);
6463 EXPECT_EQ("basic", challenge->scheme);
6464
6465 // Issue the third request with another incorrect password. There should be
6466 // a password prompt for first_realm waiting to be filled in. If the password
6467 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6468 // first_realm was not correctly removed.
6469 TestCompletionCallback callback3;
6470 rv = trans->RestartWithAuth(
6471 AuthCredentials(kSecond, kFou), callback3.callback());
6472 EXPECT_EQ(ERR_IO_PENDING, rv);
6473 rv = callback3.WaitForResult();
6474 EXPECT_EQ(OK, rv);
6475 response = trans->GetResponseInfo();
6476 ASSERT_TRUE(response != NULL);
6477 challenge = response->auth_challenge.get();
6478 ASSERT_FALSE(challenge == NULL);
6479 EXPECT_FALSE(challenge->is_proxy);
6480 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6481 EXPECT_EQ("first_realm", challenge->realm);
6482 EXPECT_EQ("basic", challenge->scheme);
6483
6484 // Issue the fourth request with the correct password and username.
6485 TestCompletionCallback callback4;
6486 rv = trans->RestartWithAuth(
6487 AuthCredentials(kFirst, kBar), callback4.callback());
6488 EXPECT_EQ(ERR_IO_PENDING, rv);
6489 rv = callback4.WaitForResult();
6490 EXPECT_EQ(OK, rv);
6491 response = trans->GetResponseInfo();
6492 ASSERT_TRUE(response != NULL);
6493 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6494 }
6495
6496 TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
6497 HttpStreamFactory::set_use_alternate_protocols(true);
6498 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
6499
6500 SessionDependencies session_deps;
6501
6502 MockRead data_reads[] = {
6503 MockRead("HTTP/1.1 200 OK\r\n"),
6504 MockRead(kAlternateProtocolHttpHeader),
6505 MockRead("hello world"),
6506 MockRead(SYNCHRONOUS, OK),
6507 };
6508
6509 HttpRequestInfo request;
6510 request.method = "GET";
6511 request.url = GURL("http://www.google.com/");
6512 request.load_flags = 0;
6513
6514 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6515
6516 session_deps.socket_factory.AddSocketDataProvider(&data);
6517
6518 TestCompletionCallback callback;
6519
6520 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6521 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6522
6523 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6524 EXPECT_EQ(ERR_IO_PENDING, rv);
6525
6526 HostPortPair http_host_port_pair("www.google.com", 80);
6527 const HttpServerProperties& http_server_properties =
6528 *session->http_server_properties();
6529 EXPECT_FALSE(
6530 http_server_properties.HasAlternateProtocol(http_host_port_pair));
6531
6532 EXPECT_EQ(OK, callback.WaitForResult());
6533
6534 const HttpResponseInfo* response = trans->GetResponseInfo();
6535 ASSERT_TRUE(response != NULL);
6536 ASSERT_TRUE(response->headers != NULL);
6537 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6538 EXPECT_FALSE(response->was_fetched_via_spdy);
6539 EXPECT_FALSE(response->was_npn_negotiated);
6540
6541 std::string response_data;
6542 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6543 EXPECT_EQ("hello world", response_data);
6544
6545 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6546 const PortAlternateProtocolPair alternate =
6547 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6548 PortAlternateProtocolPair expected_alternate;
6549 expected_alternate.port = 443;
6550 expected_alternate.protocol = NPN_SPDY_21;
6551 EXPECT_TRUE(expected_alternate.Equals(alternate));
6552
6553 HttpStreamFactory::set_use_alternate_protocols(false);
6554 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
6555 }
6556
6557 TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
6558 HttpStreamFactory::set_use_alternate_protocols(true);
6559 SessionDependencies session_deps;
6560
6561 HttpRequestInfo request;
6562 request.method = "GET";
6563 request.url = GURL("http://www.google.com/");
6564 request.load_flags = 0;
6565
6566 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
6567 StaticSocketDataProvider first_data;
6568 first_data.set_connect_data(mock_connect);
6569 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6570
6571 MockRead data_reads[] = {
6572 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6573 MockRead("hello world"),
6574 MockRead(ASYNC, OK),
6575 };
6576 StaticSocketDataProvider second_data(
6577 data_reads, arraysize(data_reads), NULL, 0);
6578 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6579
6580 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6581
6582 HttpServerProperties* http_server_properties =
6583 session->http_server_properties();
6584 // Port must be < 1024, or the header will be ignored (since initial port was
6585 // port 80 (another restricted port).
6586 http_server_properties->SetAlternateProtocol(
6587 HostPortPair::FromURL(request.url),
6588 666 /* port is ignored by MockConnect anyway */,
6589 NPN_SPDY_21);
6590
6591 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6592 TestCompletionCallback callback;
6593
6594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6595 EXPECT_EQ(ERR_IO_PENDING, rv);
6596 EXPECT_EQ(OK, callback.WaitForResult());
6597
6598 const HttpResponseInfo* response = trans->GetResponseInfo();
6599 ASSERT_TRUE(response != NULL);
6600 ASSERT_TRUE(response->headers != NULL);
6601 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6602
6603 std::string response_data;
6604 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6605 EXPECT_EQ("hello world", response_data);
6606
6607 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
6608 HostPortPair::FromURL(request.url)));
6609 const PortAlternateProtocolPair alternate =
6610 http_server_properties->GetAlternateProtocol(
6611 HostPortPair::FromURL(request.url));
6612 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
6613 HttpStreamFactory::set_use_alternate_protocols(false);
6614 }
6615
6616 TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6617 // Ensure that we're not allowed to redirect traffic via an alternate
6618 // protocol to an unrestricted (port >= 1024) when the original traffic was
6619 // on a restricted port (port < 1024). Ensure that we can redirect in all
6620 // other cases.
6621 HttpStreamFactory::set_use_alternate_protocols(true);
6622 SessionDependencies session_deps;
6623
6624 HttpRequestInfo restricted_port_request;
6625 restricted_port_request.method = "GET";
6626 restricted_port_request.url = GURL("http://www.google.com:1023/");
6627 restricted_port_request.load_flags = 0;
6628
6629 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
6630 StaticSocketDataProvider first_data;
6631 first_data.set_connect_data(mock_connect);
6632 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6633
6634 MockRead data_reads[] = {
6635 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6636 MockRead("hello world"),
6637 MockRead(ASYNC, OK),
6638 };
6639 StaticSocketDataProvider second_data(
6640 data_reads, arraysize(data_reads), NULL, 0);
6641 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6642
6643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6644
6645 HttpServerProperties* http_server_properties =
6646 session->http_server_properties();
6647 const int kUnrestrictedAlternatePort = 1024;
6648 http_server_properties->SetAlternateProtocol(
6649 HostPortPair::FromURL(restricted_port_request.url),
6650 kUnrestrictedAlternatePort,
6651 NPN_SPDY_21);
6652
6653 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6654 TestCompletionCallback callback;
6655
6656 int rv = trans->Start(
6657 &restricted_port_request, callback.callback(), BoundNetLog());
6658 EXPECT_EQ(ERR_IO_PENDING, rv);
6659 // Invalid change to unrestricted port should fail.
6660 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6661
6662 HttpStreamFactory::set_use_alternate_protocols(false);
6663 }
6664
6665 TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6666 // Ensure that we're not allowed to redirect traffic via an alternate
6667 // protocol to an unrestricted (port >= 1024) when the original traffic was
6668 // on a restricted port (port < 1024). Ensure that we can redirect in all
6669 // other cases.
6670 HttpStreamFactory::set_use_alternate_protocols(true);
6671 SessionDependencies session_deps;
6672
6673 HttpRequestInfo restricted_port_request;
6674 restricted_port_request.method = "GET";
6675 restricted_port_request.url = GURL("http://www.google.com:1023/");
6676 restricted_port_request.load_flags = 0;
6677
6678 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
6679 StaticSocketDataProvider first_data;
6680 first_data.set_connect_data(mock_connect);
6681 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6682
6683 MockRead data_reads[] = {
6684 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6685 MockRead("hello world"),
6686 MockRead(ASYNC, OK),
6687 };
6688 StaticSocketDataProvider second_data(
6689 data_reads, arraysize(data_reads), NULL, 0);
6690 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6691
6692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6693
6694 HttpServerProperties* http_server_properties =
6695 session->http_server_properties();
6696 const int kRestrictedAlternatePort = 80;
6697 http_server_properties->SetAlternateProtocol(
6698 HostPortPair::FromURL(restricted_port_request.url),
6699 kRestrictedAlternatePort,
6700 NPN_SPDY_21);
6701
6702 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6703 TestCompletionCallback callback;
6704
6705 int rv = trans->Start(
6706 &restricted_port_request, callback.callback(), BoundNetLog());
6707 EXPECT_EQ(ERR_IO_PENDING, rv);
6708 // Valid change to restricted port should pass.
6709 EXPECT_EQ(OK, callback.WaitForResult());
6710
6711 HttpStreamFactory::set_use_alternate_protocols(false);
6712 }
6713
6714 TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6715 // Ensure that we're not allowed to redirect traffic via an alternate
6716 // protocol to an unrestricted (port >= 1024) when the original traffic was
6717 // on a restricted port (port < 1024). Ensure that we can redirect in all
6718 // other cases.
6719 HttpStreamFactory::set_use_alternate_protocols(true);
6720 SessionDependencies session_deps;
6721
6722 HttpRequestInfo unrestricted_port_request;
6723 unrestricted_port_request.method = "GET";
6724 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6725 unrestricted_port_request.load_flags = 0;
6726
6727 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
6728 StaticSocketDataProvider first_data;
6729 first_data.set_connect_data(mock_connect);
6730 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6731
6732 MockRead data_reads[] = {
6733 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6734 MockRead("hello world"),
6735 MockRead(ASYNC, OK),
6736 };
6737 StaticSocketDataProvider second_data(
6738 data_reads, arraysize(data_reads), NULL, 0);
6739 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6740
6741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6742
6743 HttpServerProperties* http_server_properties =
6744 session->http_server_properties();
6745 const int kRestrictedAlternatePort = 80;
6746 http_server_properties->SetAlternateProtocol(
6747 HostPortPair::FromURL(unrestricted_port_request.url),
6748 kRestrictedAlternatePort,
6749 NPN_SPDY_21);
6750
6751 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6752 TestCompletionCallback callback;
6753
6754 int rv = trans->Start(
6755 &unrestricted_port_request, callback.callback(), BoundNetLog());
6756 EXPECT_EQ(ERR_IO_PENDING, rv);
6757 // Valid change to restricted port should pass.
6758 EXPECT_EQ(OK, callback.WaitForResult());
6759
6760 HttpStreamFactory::set_use_alternate_protocols(false);
6761 }
6762
6763 TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6764 // Ensure that we're not allowed to redirect traffic via an alternate
6765 // protocol to an unrestricted (port >= 1024) when the original traffic was
6766 // on a restricted port (port < 1024). Ensure that we can redirect in all
6767 // other cases.
6768 HttpStreamFactory::set_use_alternate_protocols(true);
6769 SessionDependencies session_deps;
6770
6771 HttpRequestInfo unrestricted_port_request;
6772 unrestricted_port_request.method = "GET";
6773 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6774 unrestricted_port_request.load_flags = 0;
6775
6776 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
6777 StaticSocketDataProvider first_data;
6778 first_data.set_connect_data(mock_connect);
6779 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6780
6781 MockRead data_reads[] = {
6782 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6783 MockRead("hello world"),
6784 MockRead(ASYNC, OK),
6785 };
6786 StaticSocketDataProvider second_data(
6787 data_reads, arraysize(data_reads), NULL, 0);
6788 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6789
6790 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6791
6792 HttpServerProperties* http_server_properties =
6793 session->http_server_properties();
6794 const int kUnrestrictedAlternatePort = 1024;
6795 http_server_properties->SetAlternateProtocol(
6796 HostPortPair::FromURL(unrestricted_port_request.url),
6797 kUnrestrictedAlternatePort,
6798 NPN_SPDY_21);
6799
6800 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6801 TestCompletionCallback callback;
6802
6803 int rv = trans->Start(
6804 &unrestricted_port_request, callback.callback(), BoundNetLog());
6805 EXPECT_EQ(ERR_IO_PENDING, rv);
6806 // Valid change to an unrestricted port should pass.
6807 EXPECT_EQ(OK, callback.WaitForResult());
6808
6809 HttpStreamFactory::set_use_alternate_protocols(false);
6810 }
6811
6812 TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
6813 // Ensure that we're not allowed to redirect traffic via an alternate
6814 // protocol to an unsafe port, and that we resume the second
6815 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
6816 HttpStreamFactory::set_use_alternate_protocols(true);
6817 SessionDependencies session_deps;
6818
6819 HttpRequestInfo request;
6820 request.method = "GET";
6821 request.url = GURL("http://www.google.com/");
6822 request.load_flags = 0;
6823
6824 // The alternate protocol request will error out before we attempt to connect,
6825 // so only the standard HTTP request will try to connect.
6826 MockRead data_reads[] = {
6827 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6828 MockRead("hello world"),
6829 MockRead(ASYNC, OK),
6830 };
6831 StaticSocketDataProvider data(
6832 data_reads, arraysize(data_reads), NULL, 0);
6833 session_deps.socket_factory.AddSocketDataProvider(&data);
6834
6835 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6836
6837 HttpServerProperties* http_server_properties =
6838 session->http_server_properties();
6839 const int kUnsafePort = 7;
6840 http_server_properties->SetAlternateProtocol(
6841 HostPortPair::FromURL(request.url),
6842 kUnsafePort,
6843 NPN_SPDY_2);
6844
6845 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6846 TestCompletionCallback callback;
6847
6848 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6849 EXPECT_EQ(ERR_IO_PENDING, rv);
6850 // The HTTP request should succeed.
6851 EXPECT_EQ(OK, callback.WaitForResult());
6852
6853 // Disable alternate protocol before the asserts.
6854 HttpStreamFactory::set_use_alternate_protocols(false);
6855
6856 const HttpResponseInfo* response = trans->GetResponseInfo();
6857 ASSERT_TRUE(response != NULL);
6858 ASSERT_TRUE(response->headers != NULL);
6859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6860
6861 std::string response_data;
6862 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6863 EXPECT_EQ("hello world", response_data);
6864 }
6865
6866 TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
6867 HttpStreamFactory::set_use_alternate_protocols(true);
6868 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
6869 SessionDependencies session_deps;
6870
6871 HttpRequestInfo request;
6872 request.method = "GET";
6873 request.url = GURL("http://www.google.com/");
6874 request.load_flags = 0;
6875
6876 MockRead data_reads[] = {
6877 MockRead("HTTP/1.1 200 OK\r\n"),
6878 MockRead(kAlternateProtocolHttpHeader),
6879 MockRead("hello world"),
6880 MockRead(ASYNC, OK),
6881 };
6882
6883 StaticSocketDataProvider first_transaction(
6884 data_reads, arraysize(data_reads), NULL, 0);
6885 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6886
6887 SSLSocketDataProvider ssl(ASYNC, OK);
6888 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
6889 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6890
6891 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6892 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
6893
6894 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6895 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6896 MockRead spdy_reads[] = {
6897 CreateMockRead(*resp),
6898 CreateMockRead(*data),
6899 MockRead(ASYNC, 0, 0),
6900 };
6901
6902 scoped_ptr<DelayedSocketData> spdy_data(
6903 new DelayedSocketData(
6904 1, // wait for one write to finish before reading.
6905 spdy_reads, arraysize(spdy_reads),
6906 spdy_writes, arraysize(spdy_writes)));
6907 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
6908
6909 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
6910 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6911 NULL, 0, NULL, 0);
6912 hanging_non_alternate_protocol_socket.set_connect_data(
6913 never_finishing_connect);
6914 session_deps.socket_factory.AddSocketDataProvider(
6915 &hanging_non_alternate_protocol_socket);
6916
6917 TestCompletionCallback callback;
6918
6919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6920 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6921
6922 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6923 EXPECT_EQ(ERR_IO_PENDING, rv);
6924 EXPECT_EQ(OK, callback.WaitForResult());
6925
6926 const HttpResponseInfo* response = trans->GetResponseInfo();
6927 ASSERT_TRUE(response != NULL);
6928 ASSERT_TRUE(response->headers != NULL);
6929 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6930
6931 std::string response_data;
6932 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6933 EXPECT_EQ("hello world", response_data);
6934
6935 trans.reset(new HttpNetworkTransaction(session));
6936
6937 rv = trans->Start(&request, callback.callback(), BoundNetLog());
6938 EXPECT_EQ(ERR_IO_PENDING, rv);
6939 EXPECT_EQ(OK, callback.WaitForResult());
6940
6941 response = trans->GetResponseInfo();
6942 ASSERT_TRUE(response != NULL);
6943 ASSERT_TRUE(response->headers != NULL);
6944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6945 EXPECT_TRUE(response->was_fetched_via_spdy);
6946 EXPECT_TRUE(response->was_npn_negotiated);
6947
6948 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6949 EXPECT_EQ("hello!", response_data);
6950
6951 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
6952 HttpStreamFactory::set_use_alternate_protocols(false);
6953 }
6954
6955 TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6956 HttpStreamFactory::set_use_alternate_protocols(true);
6957 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
6958 SessionDependencies session_deps;
6959
6960 HttpRequestInfo request;
6961 request.method = "GET";
6962 request.url = GURL("http://www.google.com/");
6963 request.load_flags = 0;
6964
6965 MockRead data_reads[] = {
6966 MockRead("HTTP/1.1 200 OK\r\n"),
6967 MockRead(kAlternateProtocolHttpHeader),
6968 MockRead("hello world"),
6969 MockRead(ASYNC, OK),
6970 };
6971
6972 StaticSocketDataProvider first_transaction(
6973 data_reads, arraysize(data_reads), NULL, 0);
6974 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6975 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6976
6977 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
6978 StaticSocketDataProvider hanging_socket(
6979 NULL, 0, NULL, 0);
6980 hanging_socket.set_connect_data(never_finishing_connect);
6981 // Socket 2 and 3 are the hanging Alternate-Protocol and
6982 // non-Alternate-Protocol jobs from the 2nd transaction.
6983 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6984 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6985
6986 SSLSocketDataProvider ssl(ASYNC, OK);
6987 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
6988 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6989
6990 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6991 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6992 MockWrite spdy_writes[] = {
6993 CreateMockWrite(*req1),
6994 CreateMockWrite(*req2),
6995 };
6996 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6997 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6998 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6999 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
7000 MockRead spdy_reads[] = {
7001 CreateMockRead(*resp1),
7002 CreateMockRead(*data1),
7003 CreateMockRead(*resp2),
7004 CreateMockRead(*data2),
7005 MockRead(ASYNC, 0, 0),
7006 };
7007
7008 scoped_ptr<DelayedSocketData> spdy_data(
7009 new DelayedSocketData(
7010 2, // wait for writes to finish before reading.
7011 spdy_reads, arraysize(spdy_reads),
7012 spdy_writes, arraysize(spdy_writes)));
7013 // Socket 4 is the successful Alternate-Protocol for transaction 3.
7014 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
7015
7016 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
7017 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
7018
7019 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7020 TestCompletionCallback callback1;
7021 HttpNetworkTransaction trans1(session);
7022
7023 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
7024 EXPECT_EQ(ERR_IO_PENDING, rv);
7025 EXPECT_EQ(OK, callback1.WaitForResult());
7026
7027 const HttpResponseInfo* response = trans1.GetResponseInfo();
7028 ASSERT_TRUE(response != NULL);
7029 ASSERT_TRUE(response->headers != NULL);
7030 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7031
7032 std::string response_data;
7033 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
7034 EXPECT_EQ("hello world", response_data);
7035
7036 TestCompletionCallback callback2;
7037 HttpNetworkTransaction trans2(session);
7038 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
7039 EXPECT_EQ(ERR_IO_PENDING, rv);
7040
7041 TestCompletionCallback callback3;
7042 HttpNetworkTransaction trans3(session);
7043 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
7044 EXPECT_EQ(ERR_IO_PENDING, rv);
7045
7046 EXPECT_EQ(OK, callback2.WaitForResult());
7047 EXPECT_EQ(OK, callback3.WaitForResult());
7048
7049 response = trans2.GetResponseInfo();
7050 ASSERT_TRUE(response != NULL);
7051 ASSERT_TRUE(response->headers != NULL);
7052 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7053 EXPECT_TRUE(response->was_fetched_via_spdy);
7054 EXPECT_TRUE(response->was_npn_negotiated);
7055 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
7056 EXPECT_EQ("hello!", response_data);
7057
7058 response = trans3.GetResponseInfo();
7059 ASSERT_TRUE(response != NULL);
7060 ASSERT_TRUE(response->headers != NULL);
7061 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7062 EXPECT_TRUE(response->was_fetched_via_spdy);
7063 EXPECT_TRUE(response->was_npn_negotiated);
7064 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
7065 EXPECT_EQ("hello!", response_data);
7066
7067 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
7068 HttpStreamFactory::set_use_alternate_protocols(false);
7069 }
7070
7071 TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
7072 HttpStreamFactory::set_use_alternate_protocols(true);
7073 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
7074 SessionDependencies session_deps;
7075
7076 HttpRequestInfo request;
7077 request.method = "GET";
7078 request.url = GURL("http://www.google.com/");
7079 request.load_flags = 0;
7080
7081 MockRead data_reads[] = {
7082 MockRead("HTTP/1.1 200 OK\r\n"),
7083 MockRead(kAlternateProtocolHttpHeader),
7084 MockRead("hello world"),
7085 MockRead(ASYNC, OK),
7086 };
7087
7088 StaticSocketDataProvider first_transaction(
7089 data_reads, arraysize(data_reads), NULL, 0);
7090 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7091
7092 SSLSocketDataProvider ssl(ASYNC, OK);
7093 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
7094 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7095
7096 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
7097 StaticSocketDataProvider hanging_alternate_protocol_socket(
7098 NULL, 0, NULL, 0);
7099 hanging_alternate_protocol_socket.set_connect_data(
7100 never_finishing_connect);
7101 session_deps.socket_factory.AddSocketDataProvider(
7102 &hanging_alternate_protocol_socket);
7103
7104 // 2nd request is just a copy of the first one, over HTTP again.
7105 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7106
7107 TestCompletionCallback callback;
7108
7109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7110 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7111
7112 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7113 EXPECT_EQ(ERR_IO_PENDING, rv);
7114 EXPECT_EQ(OK, callback.WaitForResult());
7115
7116 const HttpResponseInfo* response = trans->GetResponseInfo();
7117 ASSERT_TRUE(response != NULL);
7118 ASSERT_TRUE(response->headers != NULL);
7119 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7120
7121 std::string response_data;
7122 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7123 EXPECT_EQ("hello world", response_data);
7124
7125 trans.reset(new HttpNetworkTransaction(session));
7126
7127 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7128 EXPECT_EQ(ERR_IO_PENDING, rv);
7129 EXPECT_EQ(OK, callback.WaitForResult());
7130
7131 response = trans->GetResponseInfo();
7132 ASSERT_TRUE(response != NULL);
7133 ASSERT_TRUE(response->headers != NULL);
7134 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7135 EXPECT_FALSE(response->was_fetched_via_spdy);
7136 EXPECT_FALSE(response->was_npn_negotiated);
7137
7138 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7139 EXPECT_EQ("hello world", response_data);
7140
7141 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
7142 HttpStreamFactory::set_use_alternate_protocols(false);
7143 }
7144
7145 class CapturingProxyResolver : public ProxyResolver {
7146 public:
7147 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7148 virtual ~CapturingProxyResolver() {}
7149
7150 virtual int GetProxyForURL(const GURL& url,
7151 ProxyInfo* results,
7152 const CompletionCallback& callback,
7153 RequestHandle* request,
7154 const BoundNetLog& net_log) {
7155 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7156 HostPortPair("myproxy", 80));
7157 results->UseProxyServer(proxy_server);
7158 resolved_.push_back(url);
7159 return OK;
7160 }
7161
7162 virtual void CancelRequest(RequestHandle request) {
7163 NOTREACHED();
7164 }
7165
7166 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7167 NOTREACHED();
7168 return LOAD_STATE_IDLE;
7169 }
7170
7171 virtual LoadState GetLoadStateThreadSafe(
7172 RequestHandle request) const OVERRIDE {
7173 NOTREACHED();
7174 return LOAD_STATE_IDLE;
7175 }
7176
7177 virtual void CancelSetPacScript() {
7178 NOTREACHED();
7179 }
7180
7181 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
7182 const CompletionCallback& /*callback*/) {
7183 return OK;
7184 }
7185
7186 const std::vector<GURL>& resolved() const { return resolved_; }
7187
7188 private:
7189 std::vector<GURL> resolved_;
7190
7191 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7192 };
7193
7194 TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
7195 HttpStreamFactory::set_use_alternate_protocols(true);
7196 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
7197
7198 ProxyConfig proxy_config;
7199 proxy_config.set_auto_detect(true);
7200 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7201
7202 CapturingProxyResolver* capturing_proxy_resolver =
7203 new CapturingProxyResolver();
7204 SessionDependencies session_deps(new ProxyService(
7205 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7206 NULL));
7207
7208 HttpRequestInfo request;
7209 request.method = "GET";
7210 request.url = GURL("http://www.google.com/");
7211 request.load_flags = 0;
7212
7213 MockRead data_reads[] = {
7214 MockRead("HTTP/1.1 200 OK\r\n"),
7215 MockRead(kAlternateProtocolHttpHeader),
7216 MockRead("hello world"),
7217 MockRead(ASYNC, OK),
7218 };
7219
7220 StaticSocketDataProvider first_transaction(
7221 data_reads, arraysize(data_reads), NULL, 0);
7222 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7223
7224 SSLSocketDataProvider ssl(ASYNC, OK);
7225 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
7226 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7227
7228 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7229 MockWrite spdy_writes[] = {
7230 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7231 "Host: www.google.com\r\n"
7232 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
7233 CreateMockWrite(*req) // 3
7234 };
7235
7236 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7237
7238 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7239 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7240 MockRead spdy_reads[] = {
7241 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
7242 CreateMockRead(*resp.get(), 4), // 2, 4
7243 CreateMockRead(*data.get(), 4), // 5
7244 MockRead(ASYNC, 0, 0, 4), // 6
7245 };
7246
7247 scoped_ptr<OrderedSocketData> spdy_data(
7248 new OrderedSocketData(
7249 spdy_reads, arraysize(spdy_reads),
7250 spdy_writes, arraysize(spdy_writes)));
7251 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
7252
7253 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
7254 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7255 NULL, 0, NULL, 0);
7256 hanging_non_alternate_protocol_socket.set_connect_data(
7257 never_finishing_connect);
7258 session_deps.socket_factory.AddSocketDataProvider(
7259 &hanging_non_alternate_protocol_socket);
7260
7261 TestCompletionCallback callback;
7262
7263 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7264 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7265
7266 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7267 EXPECT_EQ(ERR_IO_PENDING, rv);
7268 EXPECT_EQ(OK, callback.WaitForResult());
7269
7270 const HttpResponseInfo* response = trans->GetResponseInfo();
7271 ASSERT_TRUE(response != NULL);
7272 ASSERT_TRUE(response->headers != NULL);
7273 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7274 EXPECT_FALSE(response->was_fetched_via_spdy);
7275 EXPECT_FALSE(response->was_npn_negotiated);
7276
7277 std::string response_data;
7278 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7279 EXPECT_EQ("hello world", response_data);
7280
7281 trans.reset(new HttpNetworkTransaction(session));
7282
7283 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7284 EXPECT_EQ(ERR_IO_PENDING, rv);
7285 EXPECT_EQ(OK, callback.WaitForResult());
7286
7287 response = trans->GetResponseInfo();
7288 ASSERT_TRUE(response != NULL);
7289 ASSERT_TRUE(response->headers != NULL);
7290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7291 EXPECT_TRUE(response->was_fetched_via_spdy);
7292 EXPECT_TRUE(response->was_npn_negotiated);
7293
7294 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7295 EXPECT_EQ("hello!", response_data);
7296 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
7297 EXPECT_EQ("http://www.google.com/",
7298 capturing_proxy_resolver->resolved()[0].spec());
7299 EXPECT_EQ("https://www.google.com/",
7300 capturing_proxy_resolver->resolved()[1].spec());
7301
7302 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
7303 HttpStreamFactory::set_use_alternate_protocols(false);
7304 }
7305
7306 TEST_F(HttpNetworkTransactionTest,
7307 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
7308 HttpStreamFactory::set_use_alternate_protocols(true);
7309 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
7310 SessionDependencies session_deps;
7311
7312 HttpRequestInfo request;
7313 request.method = "GET";
7314 request.url = GURL("http://www.google.com/");
7315 request.load_flags = 0;
7316
7317 MockRead data_reads[] = {
7318 MockRead("HTTP/1.1 200 OK\r\n"),
7319 MockRead(kAlternateProtocolHttpHeader),
7320 MockRead("hello world"),
7321 MockRead(ASYNC, OK),
7322 };
7323
7324 StaticSocketDataProvider first_transaction(
7325 data_reads, arraysize(data_reads), NULL, 0);
7326 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7327
7328 SSLSocketDataProvider ssl(ASYNC, OK);
7329 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
7330 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7331 // Make sure we use ssl for spdy here.
7332 SpdySession::SetSSLMode(true);
7333
7334 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7335 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7336
7337 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7338 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7339 MockRead spdy_reads[] = {
7340 CreateMockRead(*resp),
7341 CreateMockRead(*data),
7342 MockRead(ASYNC, 0, 0),
7343 };
7344
7345 scoped_ptr<DelayedSocketData> spdy_data(
7346 new DelayedSocketData(
7347 1, // wait for one write to finish before reading.
7348 spdy_reads, arraysize(spdy_reads),
7349 spdy_writes, arraysize(spdy_writes)));
7350 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
7351
7352 TestCompletionCallback callback;
7353
7354 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7355
7356 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7357
7358 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7359 EXPECT_EQ(ERR_IO_PENDING, rv);
7360 EXPECT_EQ(OK, callback.WaitForResult());
7361
7362 const HttpResponseInfo* response = trans->GetResponseInfo();
7363 ASSERT_TRUE(response != NULL);
7364 ASSERT_TRUE(response->headers != NULL);
7365 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7366
7367 std::string response_data;
7368 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7369 EXPECT_EQ("hello world", response_data);
7370
7371 // Set up an initial SpdySession in the pool to reuse.
7372 HostPortPair host_port_pair("www.google.com", 443);
7373 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
7374 scoped_refptr<SpdySession> spdy_session =
7375 session->spdy_session_pool()->Get(pair, BoundNetLog());
7376 scoped_refptr<TransportSocketParams> transport_params(
7377 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
7378
7379 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7380 EXPECT_EQ(ERR_IO_PENDING,
7381 connection->Init(host_port_pair.ToString(),
7382 transport_params,
7383 LOWEST,
7384 callback.callback(),
7385 session->GetTransportSocketPool(),
7386 BoundNetLog()));
7387 EXPECT_EQ(OK, callback.WaitForResult());
7388
7389 SSLConfig ssl_config;
7390 session->ssl_config_service()->GetSSLConfig(&ssl_config);
7391 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
7392 SSLClientSocketContext context;
7393 context.cert_verifier = session_deps.cert_verifier.get();
7394 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7395 connection.release(), HostPortPair("" , 443), ssl_config,
7396 NULL /* ssl_host_info */, context));
7397 EXPECT_EQ(ERR_IO_PENDING,
7398 ssl_connection->socket()->Connect(callback.callback()));
7399 EXPECT_EQ(OK, callback.WaitForResult());
7400
7401 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
7402 true, OK));
7403
7404 trans.reset(new HttpNetworkTransaction(session));
7405
7406 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7407 EXPECT_EQ(ERR_IO_PENDING, rv);
7408 EXPECT_EQ(OK, callback.WaitForResult());
7409
7410 response = trans->GetResponseInfo();
7411 ASSERT_TRUE(response != NULL);
7412 ASSERT_TRUE(response->headers != NULL);
7413 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7414 EXPECT_TRUE(response->was_fetched_via_spdy);
7415 EXPECT_TRUE(response->was_npn_negotiated);
7416
7417 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7418 EXPECT_EQ("hello!", response_data);
7419
7420 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
7421 HttpStreamFactory::set_use_alternate_protocols(false);
7422 }
7423
7424 // GenerateAuthToken is a mighty big test.
7425 // It tests all permutation of GenerateAuthToken behavior:
7426 // - Synchronous and Asynchronous completion.
7427 // - OK or error on completion.
7428 // - Direct connection, non-authenticating proxy, and authenticating proxy.
7429 // - HTTP or HTTPS backend (to include proxy tunneling).
7430 // - Non-authenticating and authenticating backend.
7431 //
7432 // In all, there are 44 reasonable permuations (for example, if there are
7433 // problems generating an auth token for an authenticating proxy, we don't
7434 // need to test all permutations of the backend server).
7435 //
7436 // The test proceeds by going over each of the configuration cases, and
7437 // potentially running up to three rounds in each of the tests. The TestConfig
7438 // specifies both the configuration for the test as well as the expectations
7439 // for the results.
7440 TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
7441 static const char kServer[] = "http://www.example.com";
7442 static const char kSecureServer[] = "https://www.example.com";
7443 static const char kProxy[] = "myproxy:70";
7444 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7445
7446 enum AuthTiming {
7447 AUTH_NONE,
7448 AUTH_SYNC,
7449 AUTH_ASYNC,
7450 };
7451
7452 const MockWrite kGet(
7453 "GET / HTTP/1.1\r\n"
7454 "Host: www.example.com\r\n"
7455 "Connection: keep-alive\r\n\r\n");
7456 const MockWrite kGetProxy(
7457 "GET http://www.example.com/ HTTP/1.1\r\n"
7458 "Host: www.example.com\r\n"
7459 "Proxy-Connection: keep-alive\r\n\r\n");
7460 const MockWrite kGetAuth(
7461 "GET / HTTP/1.1\r\n"
7462 "Host: www.example.com\r\n"
7463 "Connection: keep-alive\r\n"
7464 "Authorization: auth_token\r\n\r\n");
7465 const MockWrite kGetProxyAuth(
7466 "GET http://www.example.com/ HTTP/1.1\r\n"
7467 "Host: www.example.com\r\n"
7468 "Proxy-Connection: keep-alive\r\n"
7469 "Proxy-Authorization: auth_token\r\n\r\n");
7470 const MockWrite kGetAuthThroughProxy(
7471 "GET http://www.example.com/ HTTP/1.1\r\n"
7472 "Host: www.example.com\r\n"
7473 "Proxy-Connection: keep-alive\r\n"
7474 "Authorization: auth_token\r\n\r\n");
7475 const MockWrite kGetAuthWithProxyAuth(
7476 "GET http://www.example.com/ HTTP/1.1\r\n"
7477 "Host: www.example.com\r\n"
7478 "Proxy-Connection: keep-alive\r\n"
7479 "Proxy-Authorization: auth_token\r\n"
7480 "Authorization: auth_token\r\n\r\n");
7481 const MockWrite kConnect(
7482 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7483 "Host: www.example.com\r\n"
7484 "Proxy-Connection: keep-alive\r\n\r\n");
7485 const MockWrite kConnectProxyAuth(
7486 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7487 "Host: www.example.com\r\n"
7488 "Proxy-Connection: keep-alive\r\n"
7489 "Proxy-Authorization: auth_token\r\n\r\n");
7490
7491 const MockRead kSuccess(
7492 "HTTP/1.1 200 OK\r\n"
7493 "Content-Type: text/html; charset=iso-8859-1\r\n"
7494 "Content-Length: 3\r\n\r\n"
7495 "Yes");
7496 const MockRead kFailure(
7497 "Should not be called.");
7498 const MockRead kServerChallenge(
7499 "HTTP/1.1 401 Unauthorized\r\n"
7500 "WWW-Authenticate: Mock realm=server\r\n"
7501 "Content-Type: text/html; charset=iso-8859-1\r\n"
7502 "Content-Length: 14\r\n\r\n"
7503 "Unauthorized\r\n");
7504 const MockRead kProxyChallenge(
7505 "HTTP/1.1 407 Unauthorized\r\n"
7506 "Proxy-Authenticate: Mock realm=proxy\r\n"
7507 "Proxy-Connection: close\r\n"
7508 "Content-Type: text/html; charset=iso-8859-1\r\n"
7509 "Content-Length: 14\r\n\r\n"
7510 "Unauthorized\r\n");
7511 const MockRead kProxyConnected(
7512 "HTTP/1.1 200 Connection Established\r\n\r\n");
7513
7514 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7515 // no constructors, but the C++ compiler on Windows warns about
7516 // unspecified data in compound literals. So, moved to using constructors,
7517 // and TestRound's created with the default constructor should not be used.
7518 struct TestRound {
7519 TestRound()
7520 : expected_rv(ERR_UNEXPECTED),
7521 extra_write(NULL),
7522 extra_read(NULL) {
7523 }
7524 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7525 int expected_rv_arg)
7526 : write(write_arg),
7527 read(read_arg),
7528 expected_rv(expected_rv_arg),
7529 extra_write(NULL),
7530 extra_read(NULL) {
7531 }
7532 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7533 int expected_rv_arg, const MockWrite* extra_write_arg,
7534 const MockWrite* extra_read_arg)
7535 : write(write_arg),
7536 read(read_arg),
7537 expected_rv(expected_rv_arg),
7538 extra_write(extra_write_arg),
7539 extra_read(extra_read_arg) {
7540 }
7541 MockWrite write;
7542 MockRead read;
7543 int expected_rv;
7544 const MockWrite* extra_write;
7545 const MockRead* extra_read;
7546 };
7547
7548 static const int kNoSSL = 500;
7549
7550 struct TestConfig {
7551 const char* proxy_url;
7552 AuthTiming proxy_auth_timing;
7553 int proxy_auth_rv;
7554 const char* server_url;
7555 AuthTiming server_auth_timing;
7556 int server_auth_rv;
7557 int num_auth_rounds;
7558 int first_ssl_round;
7559 TestRound rounds[3];
7560 } test_configs[] = {
7561 // Non-authenticating HTTP server with a direct connection.
7562 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7563 { TestRound(kGet, kSuccess, OK)}},
7564 // Authenticating HTTP server with a direct connection.
7565 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7566 { TestRound(kGet, kServerChallenge, OK),
7567 TestRound(kGetAuth, kSuccess, OK)}},
7568 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7569 { TestRound(kGet, kServerChallenge, OK),
7570 TestRound(kGetAuth, kFailure, kAuthErr)}},
7571 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7572 { TestRound(kGet, kServerChallenge, OK),
7573 TestRound(kGetAuth, kSuccess, OK)}},
7574 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7575 { TestRound(kGet, kServerChallenge, OK),
7576 TestRound(kGetAuth, kFailure, kAuthErr)}},
7577 // Non-authenticating HTTP server through a non-authenticating proxy.
7578 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7579 { TestRound(kGetProxy, kSuccess, OK)}},
7580 // Authenticating HTTP server through a non-authenticating proxy.
7581 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7582 { TestRound(kGetProxy, kServerChallenge, OK),
7583 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7584 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7585 { TestRound(kGetProxy, kServerChallenge, OK),
7586 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7587 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7588 { TestRound(kGetProxy, kServerChallenge, OK),
7589 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7590 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7591 { TestRound(kGetProxy, kServerChallenge, OK),
7592 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7593 // Non-authenticating HTTP server through an authenticating proxy.
7594 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7595 { TestRound(kGetProxy, kProxyChallenge, OK),
7596 TestRound(kGetProxyAuth, kSuccess, OK)}},
7597 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7598 { TestRound(kGetProxy, kProxyChallenge, OK),
7599 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7600 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7601 { TestRound(kGetProxy, kProxyChallenge, OK),
7602 TestRound(kGetProxyAuth, kSuccess, OK)}},
7603 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7604 { TestRound(kGetProxy, kProxyChallenge, OK),
7605 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7606 // Authenticating HTTP server through an authenticating proxy.
7607 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7608 { TestRound(kGetProxy, kProxyChallenge, OK),
7609 TestRound(kGetProxyAuth, kServerChallenge, OK),
7610 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7611 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7612 { TestRound(kGetProxy, kProxyChallenge, OK),
7613 TestRound(kGetProxyAuth, kServerChallenge, OK),
7614 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7615 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7616 { TestRound(kGetProxy, kProxyChallenge, OK),
7617 TestRound(kGetProxyAuth, kServerChallenge, OK),
7618 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7619 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7620 { TestRound(kGetProxy, kProxyChallenge, OK),
7621 TestRound(kGetProxyAuth, kServerChallenge, OK),
7622 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7623 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7624 { TestRound(kGetProxy, kProxyChallenge, OK),
7625 TestRound(kGetProxyAuth, kServerChallenge, OK),
7626 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7627 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7628 { TestRound(kGetProxy, kProxyChallenge, OK),
7629 TestRound(kGetProxyAuth, kServerChallenge, OK),
7630 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7631 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7632 { TestRound(kGetProxy, kProxyChallenge, OK),
7633 TestRound(kGetProxyAuth, kServerChallenge, OK),
7634 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7635 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7636 { TestRound(kGetProxy, kProxyChallenge, OK),
7637 TestRound(kGetProxyAuth, kServerChallenge, OK),
7638 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7639 // Non-authenticating HTTPS server with a direct connection.
7640 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7641 { TestRound(kGet, kSuccess, OK)}},
7642 // Authenticating HTTPS server with a direct connection.
7643 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7644 { TestRound(kGet, kServerChallenge, OK),
7645 TestRound(kGetAuth, kSuccess, OK)}},
7646 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7647 { TestRound(kGet, kServerChallenge, OK),
7648 TestRound(kGetAuth, kFailure, kAuthErr)}},
7649 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7650 { TestRound(kGet, kServerChallenge, OK),
7651 TestRound(kGetAuth, kSuccess, OK)}},
7652 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7653 { TestRound(kGet, kServerChallenge, OK),
7654 TestRound(kGetAuth, kFailure, kAuthErr)}},
7655 // Non-authenticating HTTPS server with a non-authenticating proxy.
7656 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7657 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7658 // Authenticating HTTPS server through a non-authenticating proxy.
7659 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7660 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7661 TestRound(kGetAuth, kSuccess, OK)}},
7662 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7663 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7664 TestRound(kGetAuth, kFailure, kAuthErr)}},
7665 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7666 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7667 TestRound(kGetAuth, kSuccess, OK)}},
7668 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7669 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7670 TestRound(kGetAuth, kFailure, kAuthErr)}},
7671 // Non-Authenticating HTTPS server through an authenticating proxy.
7672 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7673 { TestRound(kConnect, kProxyChallenge, OK),
7674 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7675 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7676 { TestRound(kConnect, kProxyChallenge, OK),
7677 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7678 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7679 { TestRound(kConnect, kProxyChallenge, OK),
7680 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7681 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7682 { TestRound(kConnect, kProxyChallenge, OK),
7683 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7684 // Authenticating HTTPS server through an authenticating proxy.
7685 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7686 { TestRound(kConnect, kProxyChallenge, OK),
7687 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7688 &kGet, &kServerChallenge),
7689 TestRound(kGetAuth, kSuccess, OK)}},
7690 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7691 { TestRound(kConnect, kProxyChallenge, OK),
7692 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7693 &kGet, &kServerChallenge),
7694 TestRound(kGetAuth, kFailure, kAuthErr)}},
7695 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7696 { TestRound(kConnect, kProxyChallenge, OK),
7697 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7698 &kGet, &kServerChallenge),
7699 TestRound(kGetAuth, kSuccess, OK)}},
7700 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7701 { TestRound(kConnect, kProxyChallenge, OK),
7702 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7703 &kGet, &kServerChallenge),
7704 TestRound(kGetAuth, kFailure, kAuthErr)}},
7705 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7706 { TestRound(kConnect, kProxyChallenge, OK),
7707 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7708 &kGet, &kServerChallenge),
7709 TestRound(kGetAuth, kSuccess, OK)}},
7710 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7711 { TestRound(kConnect, kProxyChallenge, OK),
7712 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7713 &kGet, &kServerChallenge),
7714 TestRound(kGetAuth, kFailure, kAuthErr)}},
7715 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7716 { TestRound(kConnect, kProxyChallenge, OK),
7717 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7718 &kGet, &kServerChallenge),
7719 TestRound(kGetAuth, kSuccess, OK)}},
7720 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7721 { TestRound(kConnect, kProxyChallenge, OK),
7722 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7723 &kGet, &kServerChallenge),
7724 TestRound(kGetAuth, kFailure, kAuthErr)}},
7725 };
7726
7727 SessionDependencies session_deps;
7728 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7729 HttpAuthHandlerMock::Factory* auth_factory(
7730 new HttpAuthHandlerMock::Factory());
7731 session_deps.http_auth_handler_factory.reset(auth_factory);
7732 const TestConfig& test_config = test_configs[i];
7733
7734 // Set up authentication handlers as necessary.
7735 if (test_config.proxy_auth_timing != AUTH_NONE) {
7736 for (int n = 0; n < 2; n++) {
7737 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7738 std::string auth_challenge = "Mock realm=proxy";
7739 GURL origin(test_config.proxy_url);
7740 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7741 auth_challenge.end());
7742 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7743 origin, BoundNetLog());
7744 auth_handler->SetGenerateExpectation(
7745 test_config.proxy_auth_timing == AUTH_ASYNC,
7746 test_config.proxy_auth_rv);
7747 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7748 }
7749 }
7750 if (test_config.server_auth_timing != AUTH_NONE) {
7751 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7752 std::string auth_challenge = "Mock realm=server";
7753 GURL origin(test_config.server_url);
7754 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7755 auth_challenge.end());
7756 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7757 origin, BoundNetLog());
7758 auth_handler->SetGenerateExpectation(
7759 test_config.server_auth_timing == AUTH_ASYNC,
7760 test_config.server_auth_rv);
7761 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
7762 }
7763 if (test_config.proxy_url) {
7764 session_deps.proxy_service.reset(
7765 ProxyService::CreateFixed(test_config.proxy_url));
7766 } else {
7767 session_deps.proxy_service.reset(ProxyService::CreateDirect());
7768 }
7769
7770 HttpRequestInfo request;
7771 request.method = "GET";
7772 request.url = GURL(test_config.server_url);
7773 request.load_flags = 0;
7774
7775 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7776 HttpNetworkTransaction trans(CreateSession(&session_deps));
7777
7778 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7779 const TestRound& read_write_round = test_config.rounds[round];
7780
7781 // Set up expected reads and writes.
7782 MockRead reads[2];
7783 reads[0] = read_write_round.read;
7784 size_t length_reads = 1;
7785 if (read_write_round.extra_read) {
7786 reads[1] = *read_write_round.extra_read;
7787 length_reads = 2;
7788 }
7789
7790 MockWrite writes[2];
7791 writes[0] = read_write_round.write;
7792 size_t length_writes = 1;
7793 if (read_write_round.extra_write) {
7794 writes[1] = *read_write_round.extra_write;
7795 length_writes = 2;
7796 }
7797 StaticSocketDataProvider data_provider(
7798 reads, length_reads, writes, length_writes);
7799 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7800
7801 // Add an SSL sequence if necessary.
7802 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
7803 if (round >= test_config.first_ssl_round)
7804 session_deps.socket_factory.AddSSLSocketDataProvider(
7805 &ssl_socket_data_provider);
7806
7807 // Start or restart the transaction.
7808 TestCompletionCallback callback;
7809 int rv;
7810 if (round == 0) {
7811 rv = trans.Start(&request, callback.callback(), BoundNetLog());
7812 } else {
7813 rv = trans.RestartWithAuth(
7814 AuthCredentials(kFoo, kBar), callback.callback());
7815 }
7816 if (rv == ERR_IO_PENDING)
7817 rv = callback.WaitForResult();
7818
7819 // Compare results with expected data.
7820 EXPECT_EQ(read_write_round.expected_rv, rv);
7821 const HttpResponseInfo* response = trans.GetResponseInfo();
7822 if (read_write_round.expected_rv == OK) {
7823 ASSERT_TRUE(response != NULL);
7824 } else {
7825 EXPECT_TRUE(response == NULL);
7826 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7827 continue;
7828 }
7829 if (round + 1 < test_config.num_auth_rounds) {
7830 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7831 } else {
7832 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7833 }
7834 }
7835 }
7836 }
7837
7838 TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7839 // Do multi-round authentication and make sure it works correctly.
7840 SessionDependencies session_deps;
7841 HttpAuthHandlerMock::Factory* auth_factory(
7842 new HttpAuthHandlerMock::Factory());
7843 session_deps.http_auth_handler_factory.reset(auth_factory);
7844 session_deps.proxy_service.reset(ProxyService::CreateDirect());
7845 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7846 session_deps.host_resolver->set_synchronous_mode(true);
7847
7848 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7849 auth_handler->set_connection_based(true);
7850 std::string auth_challenge = "Mock realm=server";
7851 GURL origin("http://www.example.com");
7852 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7853 auth_challenge.end());
7854 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7855 origin, BoundNetLog());
7856 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
7857
7858 int rv = OK;
7859 const HttpResponseInfo* response = NULL;
7860 HttpRequestInfo request;
7861 request.method = "GET";
7862 request.url = origin;
7863 request.load_flags = 0;
7864
7865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7866
7867 // Use a TCP Socket Pool with only one connection per group. This is used
7868 // to validate that the TCP socket is not released to the pool between
7869 // each round of multi-round authentication.
7870 HttpNetworkSessionPeer session_peer(session);
7871 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7872 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
7873 50, // Max sockets for pool
7874 1, // Max sockets per group
7875 &transport_pool_histograms,
7876 session_deps.host_resolver.get(),
7877 &session_deps.socket_factory,
7878 session_deps.net_log);
7879 MockClientSocketPoolManager* mock_pool_manager =
7880 new MockClientSocketPoolManager;
7881 mock_pool_manager->SetTransportSocketPool(transport_pool);
7882 session_peer.SetClientSocketPoolManager(mock_pool_manager);
7883
7884 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7885 TestCompletionCallback callback;
7886
7887 const MockWrite kGet(
7888 "GET / HTTP/1.1\r\n"
7889 "Host: www.example.com\r\n"
7890 "Connection: keep-alive\r\n\r\n");
7891 const MockWrite kGetAuth(
7892 "GET / HTTP/1.1\r\n"
7893 "Host: www.example.com\r\n"
7894 "Connection: keep-alive\r\n"
7895 "Authorization: auth_token\r\n\r\n");
7896
7897 const MockRead kServerChallenge(
7898 "HTTP/1.1 401 Unauthorized\r\n"
7899 "WWW-Authenticate: Mock realm=server\r\n"
7900 "Content-Type: text/html; charset=iso-8859-1\r\n"
7901 "Content-Length: 14\r\n\r\n"
7902 "Unauthorized\r\n");
7903 const MockRead kSuccess(
7904 "HTTP/1.1 200 OK\r\n"
7905 "Content-Type: text/html; charset=iso-8859-1\r\n"
7906 "Content-Length: 3\r\n\r\n"
7907 "Yes");
7908
7909 MockWrite writes[] = {
7910 // First round
7911 kGet,
7912 // Second round
7913 kGetAuth,
7914 // Third round
7915 kGetAuth,
7916 // Fourth round
7917 kGetAuth,
7918 // Competing request
7919 kGet,
7920 };
7921 MockRead reads[] = {
7922 // First round
7923 kServerChallenge,
7924 // Second round
7925 kServerChallenge,
7926 // Third round
7927 kServerChallenge,
7928 // Fourth round
7929 kSuccess,
7930 // Competing response
7931 kSuccess,
7932 };
7933 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7934 writes, arraysize(writes));
7935 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7936
7937 const char* const kSocketGroup = "www.example.com:80";
7938
7939 // First round of authentication.
7940 auth_handler->SetGenerateExpectation(false, OK);
7941 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7942 if (rv == ERR_IO_PENDING)
7943 rv = callback.WaitForResult();
7944 EXPECT_EQ(OK, rv);
7945 response = trans->GetResponseInfo();
7946 ASSERT_TRUE(response != NULL);
7947 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7948 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7949
7950 // In between rounds, another request comes in for the same domain.
7951 // It should not be able to grab the TCP socket that trans has already
7952 // claimed.
7953 scoped_ptr<HttpTransaction> trans_compete(
7954 new HttpNetworkTransaction(session));
7955 TestCompletionCallback callback_compete;
7956 rv = trans_compete->Start(
7957 &request, callback_compete.callback(), BoundNetLog());
7958 EXPECT_EQ(ERR_IO_PENDING, rv);
7959 // callback_compete.WaitForResult at this point would stall forever,
7960 // since the HttpNetworkTransaction does not release the request back to
7961 // the pool until after authentication completes.
7962
7963 // Second round of authentication.
7964 auth_handler->SetGenerateExpectation(false, OK);
7965 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
7966 if (rv == ERR_IO_PENDING)
7967 rv = callback.WaitForResult();
7968 EXPECT_EQ(OK, rv);
7969 response = trans->GetResponseInfo();
7970 ASSERT_TRUE(response != NULL);
7971 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7972 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7973
7974 // Third round of authentication.
7975 auth_handler->SetGenerateExpectation(false, OK);
7976 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
7977 if (rv == ERR_IO_PENDING)
7978 rv = callback.WaitForResult();
7979 EXPECT_EQ(OK, rv);
7980 response = trans->GetResponseInfo();
7981 ASSERT_TRUE(response != NULL);
7982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7983 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7984
7985 // Fourth round of authentication, which completes successfully.
7986 auth_handler->SetGenerateExpectation(false, OK);
7987 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
7988 if (rv == ERR_IO_PENDING)
7989 rv = callback.WaitForResult();
7990 EXPECT_EQ(OK, rv);
7991 response = trans->GetResponseInfo();
7992 ASSERT_TRUE(response != NULL);
7993 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7994 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7995
7996 // Read the body since the fourth round was successful. This will also
7997 // release the socket back to the pool.
7998 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7999 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
8000 if (rv == ERR_IO_PENDING)
8001 rv = callback.WaitForResult();
8002 EXPECT_EQ(3, rv);
8003 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
8004 EXPECT_EQ(0, rv);
8005 // There are still 0 idle sockets, since the trans_compete transaction
8006 // will be handed it immediately after trans releases it to the group.
8007 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
8008
8009 // The competing request can now finish. Wait for the headers and then
8010 // read the body.
8011 rv = callback_compete.WaitForResult();
8012 EXPECT_EQ(OK, rv);
8013 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
8014 if (rv == ERR_IO_PENDING)
8015 rv = callback.WaitForResult();
8016 EXPECT_EQ(3, rv);
8017 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
8018 EXPECT_EQ(0, rv);
8019
8020 // Finally, the socket is released to the group.
8021 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
8022 }
8023
8024 class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
8025 public:
8026 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
8027 : fail_all_(fail_all) {
8028 }
8029
8030 virtual MockRead GetNextRead() {
8031 if (fail_all_)
8032 return MockRead(SYNCHRONOUS, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
8033
8034 return MockRead(SYNCHRONOUS,
8035 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
8036 }
8037
8038 virtual MockWriteResult OnWrite(const std::string& data) {
8039 return MockWriteResult(SYNCHRONOUS /* async */, data.size());
8040 }
8041
8042 void Reset() {
8043 }
8044
8045 private:
8046 const bool fail_all_;
8047 };
8048
8049 // Test that we restart a connection when we see a decompression failure from
8050 // the peer during the handshake. (In the real world we'll restart with SSLv3
8051 // and we won't offer DEFLATE in that case.)
8052 TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
8053 HttpRequestInfo request;
8054 request.method = "GET";
8055 request.url = GURL("https://tlsdecompressionfailure.example.com/");
8056 request.load_flags = 0;
8057
8058 SessionDependencies session_deps;
8059 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8060 false /* fail all reads */);
8061 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8062 SSLSocketDataProvider ssl_socket_data_provider1(
8063 SYNCHRONOUS, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
8064 SSLSocketDataProvider ssl_socket_data_provider2(SYNCHRONOUS, OK);
8065 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8066 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8067 session_deps.socket_factory.AddSSLSocketDataProvider(
8068 &ssl_socket_data_provider1);
8069 session_deps.socket_factory.AddSSLSocketDataProvider(
8070 &ssl_socket_data_provider2);
8071
8072 // Work around http://crbug.com/37454
8073 StaticSocketDataProvider bug37454_connection;
8074 bug37454_connection.set_connect_data(MockConnect(ASYNC, ERR_UNEXPECTED));
8075 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
8076
8077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8078 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8079 TestCompletionCallback callback;
8080
8081 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8082 EXPECT_EQ(ERR_IO_PENDING, rv);
8083 EXPECT_EQ(OK, callback.WaitForResult());
8084
8085 const HttpResponseInfo* response = trans->GetResponseInfo();
8086 ASSERT_TRUE(response != NULL);
8087 ASSERT_TRUE(response->headers != NULL);
8088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8089
8090 std::string response_data;
8091 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8092 EXPECT_EQ("ok.", response_data);
8093 }
8094
8095 // Test that we restart a connection if we get a decompression failure from the
8096 // peer while reading the first bytes from the connection. This occurs when the
8097 // peer cannot handle DEFLATE but we're using False Start, so we don't notice
8098 // in the handshake.
8099 TEST_F(HttpNetworkTransactionTest,
8100 RestartAfterTLSDecompressionFailureWithFalseStart) {
8101 HttpRequestInfo request;
8102 request.method = "GET";
8103 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
8104 request.load_flags = 0;
8105
8106 SessionDependencies session_deps;
8107 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8108 true /* fail all reads */);
8109 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8110 SSLSocketDataProvider ssl_socket_data_provider1(SYNCHRONOUS, OK);
8111 SSLSocketDataProvider ssl_socket_data_provider2(SYNCHRONOUS, OK);
8112 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8113 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8114 session_deps.socket_factory.AddSSLSocketDataProvider(
8115 &ssl_socket_data_provider1);
8116 session_deps.socket_factory.AddSSLSocketDataProvider(
8117 &ssl_socket_data_provider2);
8118
8119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8120 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8121 TestCompletionCallback callback;
8122
8123 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8124 EXPECT_EQ(ERR_IO_PENDING, rv);
8125 EXPECT_EQ(OK, callback.WaitForResult());
8126
8127 const HttpResponseInfo* response = trans->GetResponseInfo();
8128 ASSERT_TRUE(response != NULL);
8129 ASSERT_TRUE(response->headers != NULL);
8130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8131
8132 std::string response_data;
8133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8134 EXPECT_EQ("ok.", response_data);
8135 }
8136
8137 // This tests the case that a request is issued via http instead of spdy after
8138 // npn is negotiated.
8139 TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
8140 HttpStreamFactory::set_use_alternate_protocols(true);
8141 HttpStreamFactory::SetNextProtos(
8142 MakeNextProtos("http/1.1", "http1.1", NULL));
8143 SessionDependencies session_deps;
8144 HttpRequestInfo request;
8145 request.method = "GET";
8146 request.url = GURL("https://www.google.com/");
8147 request.load_flags = 0;
8148
8149 MockWrite data_writes[] = {
8150 MockWrite("GET / HTTP/1.1\r\n"
8151 "Host: www.google.com\r\n"
8152 "Connection: keep-alive\r\n\r\n"),
8153 };
8154
8155 MockRead data_reads[] = {
8156 MockRead("HTTP/1.1 200 OK\r\n"),
8157 MockRead(kAlternateProtocolHttpHeader),
8158 MockRead("hello world"),
8159 MockRead(SYNCHRONOUS, OK),
8160 };
8161
8162 SSLSocketDataProvider ssl(ASYNC, OK);
8163 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8164 ssl.next_proto = "http/1.1";
8165 ssl.protocol_negotiated = SSLClientSocket::kProtoHTTP11;
8166
8167 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8168
8169 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8170 data_writes, arraysize(data_writes));
8171 session_deps.socket_factory.AddSocketDataProvider(&data);
8172
8173 TestCompletionCallback callback;
8174
8175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8176 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8177
8178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8179
8180 EXPECT_EQ(ERR_IO_PENDING, rv);
8181 EXPECT_EQ(OK, callback.WaitForResult());
8182
8183 const HttpResponseInfo* response = trans->GetResponseInfo();
8184 ASSERT_TRUE(response != NULL);
8185 ASSERT_TRUE(response->headers != NULL);
8186 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8187
8188 std::string response_data;
8189 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8190 EXPECT_EQ("hello world", response_data);
8191
8192 EXPECT_FALSE(response->was_fetched_via_spdy);
8193 EXPECT_TRUE(response->was_npn_negotiated);
8194
8195 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
8196 HttpStreamFactory::set_use_alternate_protocols(false);
8197 }
8198
8199 TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8200 // Simulate the SSL handshake completing with an NPN negotiation
8201 // followed by an immediate server closing of the socket.
8202 // Fix crash: http://crbug.com/46369
8203 HttpStreamFactory::set_use_alternate_protocols(true);
8204 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8205 SessionDependencies session_deps;
8206
8207 HttpRequestInfo request;
8208 request.method = "GET";
8209 request.url = GURL("https://www.google.com/");
8210 request.load_flags = 0;
8211
8212 SSLSocketDataProvider ssl(ASYNC, OK);
8213 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
8214 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8215
8216 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8217 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8218
8219 MockRead spdy_reads[] = {
8220 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
8221 };
8222
8223 scoped_ptr<DelayedSocketData> spdy_data(
8224 new DelayedSocketData(
8225 0, // don't wait in this case, immediate hangup.
8226 spdy_reads, arraysize(spdy_reads),
8227 spdy_writes, arraysize(spdy_writes)));
8228 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
8229
8230 TestCompletionCallback callback;
8231
8232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8233 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8234
8235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8236 EXPECT_EQ(ERR_IO_PENDING, rv);
8237 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8238
8239 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
8240 HttpStreamFactory::set_use_alternate_protocols(false);
8241 }
8242
8243 TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8244 // This test ensures that the URL passed into the proxy is upgraded
8245 // to https when doing an Alternate Protocol upgrade.
8246 HttpStreamFactory::set_use_alternate_protocols(true);
8247 HttpStreamFactory::SetNextProtos(
8248 MakeNextProtos(
8249 "http/1.1", "http1.1", "spdy/2.1", "spdy/2", "spdy", NULL));
8250
8251 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8252 HttpAuthHandlerMock::Factory* auth_factory =
8253 new HttpAuthHandlerMock::Factory();
8254 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
8255 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
8256 auth_factory->set_do_init_from_challenge(true);
8257 session_deps.http_auth_handler_factory.reset(auth_factory);
8258
8259 HttpRequestInfo request;
8260 request.method = "GET";
8261 request.url = GURL("http://www.google.com");
8262 request.load_flags = 0;
8263
8264 // First round goes unauthenticated through the proxy.
8265 MockWrite data_writes_1[] = {
8266 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8267 "Host: www.google.com\r\n"
8268 "Proxy-Connection: keep-alive\r\n"
8269 "\r\n"),
8270 };
8271 MockRead data_reads_1[] = {
8272 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8273 MockRead("HTTP/1.1 200 OK\r\n"
8274 "Alternate-Protocol: 443:npn-spdy/2.1\r\n"
8275 "Proxy-Connection: close\r\n"
8276 "\r\n"),
8277 };
8278 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8279 data_writes_1, arraysize(data_writes_1));
8280
8281 // Second round tries to tunnel to www.google.com due to the
8282 // Alternate-Protocol announcement in the first round. It fails due
8283 // to a proxy authentication challenge.
8284 // After the failure, a tunnel is established to www.google.com using
8285 // Proxy-Authorization headers. There is then a SPDY request round.
8286 //
8287 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8288 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8289 // does a Disconnect and Connect on the same socket, rather than trying
8290 // to obtain a new one.
8291 //
8292 // NOTE: Originally, the proxy response to the second CONNECT request
8293 // simply returned another 407 so the unit test could skip the SSL connection
8294 // establishment and SPDY framing issues. Alas, the
8295 // retry-http-when-alternate-protocol fails logic kicks in, which was more
8296 // complicated to set up expectations for than the SPDY session.
8297
8298 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8299 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8300 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8301
8302 MockWrite data_writes_2[] = {
8303 // First connection attempt without Proxy-Authorization.
8304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8305 "Host: www.google.com\r\n"
8306 "Proxy-Connection: keep-alive\r\n"
8307 "\r\n"),
8308
8309 // Second connection attempt with Proxy-Authorization.
8310 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8311 "Host: www.google.com\r\n"
8312 "Proxy-Connection: keep-alive\r\n"
8313 "Proxy-Authorization: auth_token\r\n"
8314 "\r\n"),
8315
8316 // SPDY request
8317 CreateMockWrite(*req),
8318 };
8319 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8320 "Proxy-Authenticate: Mock\r\n"
8321 "Proxy-Connection: close\r\n"
8322 "\r\n");
8323 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8324 MockRead data_reads_2[] = {
8325 // First connection attempt fails
8326 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8327 MockRead(ASYNC, kRejectConnectResponse,
8328 arraysize(kRejectConnectResponse) - 1, 1),
8329
8330 // Second connection attempt passes
8331 MockRead(ASYNC, kAcceptConnectResponse,
8332 arraysize(kAcceptConnectResponse) -1, 4),
8333
8334 // SPDY response
8335 CreateMockRead(*resp.get(), 6),
8336 CreateMockRead(*data.get(), 6),
8337 MockRead(ASYNC, 0, 0, 6),
8338 };
8339 scoped_ptr<OrderedSocketData> data_2(
8340 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8341 data_writes_2, arraysize(data_writes_2)));
8342
8343 SSLSocketDataProvider ssl(ASYNC, OK);
8344 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
8345
8346 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8347 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8348 NULL, 0, NULL, 0);
8349 hanging_non_alternate_protocol_socket.set_connect_data(
8350 never_finishing_connect);
8351
8352 session_deps.socket_factory.AddSocketDataProvider(&data_1);
8353 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
8354 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8355 session_deps.socket_factory.AddSocketDataProvider(
8356 &hanging_non_alternate_protocol_socket);
8357 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8358
8359 // First round should work and provide the Alternate-Protocol state.
8360 TestCompletionCallback callback_1;
8361 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8362 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
8363 EXPECT_EQ(ERR_IO_PENDING, rv);
8364 EXPECT_EQ(OK, callback_1.WaitForResult());
8365
8366 // Second round should attempt a tunnel connect and get an auth challenge.
8367 TestCompletionCallback callback_2;
8368 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8369 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
8370 EXPECT_EQ(ERR_IO_PENDING, rv);
8371 EXPECT_EQ(OK, callback_2.WaitForResult());
8372 const HttpResponseInfo* response = trans_2->GetResponseInfo();
8373 ASSERT_TRUE(response != NULL);
8374 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8375
8376 // Restart with auth. Tunnel should work and response received.
8377 TestCompletionCallback callback_3;
8378 rv = trans_2->RestartWithAuth(
8379 AuthCredentials(kFoo, kBar), callback_3.callback());
8380 EXPECT_EQ(ERR_IO_PENDING, rv);
8381 EXPECT_EQ(OK, callback_3.WaitForResult());
8382
8383 // After all that work, these two lines (or actually, just the scheme) are
8384 // what this test is all about. Make sure it happens correctly.
8385 const GURL& request_url = auth_handler->request_url();
8386 EXPECT_EQ("https", request_url.scheme());
8387 EXPECT_EQ("www.google.com", request_url.host());
8388
8389 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
8390 HttpStreamFactory::set_use_alternate_protocols(false);
8391 }
8392
8393 // Test that if we cancel the transaction as the connection is completing, that
8394 // everything tears down correctly.
8395 TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8396 // Setup everything about the connection to complete synchronously, so that
8397 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8398 // for is the callback from the HttpStreamRequest.
8399 // Then cancel the transaction.
8400 // Verify that we don't crash.
8401 MockConnect mock_connect(SYNCHRONOUS, OK);
8402 MockRead data_reads[] = {
8403 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
8404 MockRead(SYNCHRONOUS, "hello world"),
8405 MockRead(SYNCHRONOUS, OK),
8406 };
8407
8408 HttpRequestInfo request;
8409 request.method = "GET";
8410 request.url = GURL("http://www.google.com/");
8411 request.load_flags = 0;
8412
8413 SessionDependencies session_deps;
8414 session_deps.host_resolver->set_synchronous_mode(true);
8415 scoped_ptr<HttpTransaction> trans(
8416 new HttpNetworkTransaction(CreateSession(&session_deps)));
8417
8418 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8419 data.set_connect_data(mock_connect);
8420 session_deps.socket_factory.AddSocketDataProvider(&data);
8421
8422 TestCompletionCallback callback;
8423
8424 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8425 int rv = trans->Start(&request, callback.callback(), log.bound());
8426 EXPECT_EQ(ERR_IO_PENDING, rv);
8427 trans.reset(); // Cancel the transaction here.
8428
8429 MessageLoop::current()->RunAllPending();
8430 }
8431
8432 // Test a basic GET request through a proxy.
8433 TEST_F(HttpNetworkTransactionTest, ProxyGet) {
8434 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8435 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8436 session_deps.net_log = log.bound().net_log();
8437 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8438
8439 HttpRequestInfo request;
8440 request.method = "GET";
8441 request.url = GURL("http://www.google.com/");
8442
8443 MockWrite data_writes1[] = {
8444 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8445 "Host: www.google.com\r\n"
8446 "Proxy-Connection: keep-alive\r\n\r\n"),
8447 };
8448
8449 MockRead data_reads1[] = {
8450 MockRead("HTTP/1.1 200 OK\r\n"),
8451 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8452 MockRead("Content-Length: 100\r\n\r\n"),
8453 MockRead(SYNCHRONOUS, OK),
8454 };
8455
8456 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8457 data_writes1, arraysize(data_writes1));
8458 session_deps.socket_factory.AddSocketDataProvider(&data1);
8459
8460 TestCompletionCallback callback1;
8461
8462 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8463
8464 int rv = trans->Start(&request, callback1.callback(), log.bound());
8465 EXPECT_EQ(ERR_IO_PENDING, rv);
8466
8467 rv = callback1.WaitForResult();
8468 EXPECT_EQ(OK, rv);
8469
8470 const HttpResponseInfo* response = trans->GetResponseInfo();
8471 ASSERT_TRUE(response != NULL);
8472
8473 EXPECT_TRUE(response->headers->IsKeepAlive());
8474 EXPECT_EQ(200, response->headers->response_code());
8475 EXPECT_EQ(100, response->headers->GetContentLength());
8476 EXPECT_TRUE(response->was_fetched_via_proxy);
8477 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8478 }
8479
8480 // Test a basic HTTPS GET request through a proxy.
8481 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
8482 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8483 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8484 session_deps.net_log = log.bound().net_log();
8485 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8486
8487 HttpRequestInfo request;
8488 request.method = "GET";
8489 request.url = GURL("https://www.google.com/");
8490
8491 // Since we have proxy, should try to establish tunnel.
8492 MockWrite data_writes1[] = {
8493 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8494 "Host: www.google.com\r\n"
8495 "Proxy-Connection: keep-alive\r\n\r\n"),
8496
8497 MockWrite("GET / HTTP/1.1\r\n"
8498 "Host: www.google.com\r\n"
8499 "Connection: keep-alive\r\n\r\n"),
8500 };
8501
8502 MockRead data_reads1[] = {
8503 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8504
8505 MockRead("HTTP/1.1 200 OK\r\n"),
8506 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8507 MockRead("Content-Length: 100\r\n\r\n"),
8508 MockRead(SYNCHRONOUS, OK),
8509 };
8510
8511 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8512 data_writes1, arraysize(data_writes1));
8513 session_deps.socket_factory.AddSocketDataProvider(&data1);
8514 SSLSocketDataProvider ssl(ASYNC, OK);
8515 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8516
8517 TestCompletionCallback callback1;
8518
8519 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8520
8521 int rv = trans->Start(&request, callback1.callback(), log.bound());
8522 EXPECT_EQ(ERR_IO_PENDING, rv);
8523
8524 rv = callback1.WaitForResult();
8525 EXPECT_EQ(OK, rv);
8526 net::CapturingNetLog::EntryList entries;
8527 log.GetEntries(&entries);
8528 size_t pos = ExpectLogContainsSomewhere(
8529 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
8530 NetLog::PHASE_NONE);
8531 ExpectLogContainsSomewhere(
8532 entries, pos,
8533 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8534 NetLog::PHASE_NONE);
8535
8536 const HttpResponseInfo* response = trans->GetResponseInfo();
8537 ASSERT_TRUE(response != NULL);
8538
8539 EXPECT_TRUE(response->headers->IsKeepAlive());
8540 EXPECT_EQ(200, response->headers->response_code());
8541 EXPECT_EQ(100, response->headers->GetContentLength());
8542 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8543 EXPECT_TRUE(response->was_fetched_via_proxy);
8544 }
8545
8546 // Test a basic HTTPS GET request through a proxy, but the server hangs up
8547 // while establishing the tunnel.
8548 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
8549 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8550 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8551 session_deps.net_log = log.bound().net_log();
8552 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8553
8554 HttpRequestInfo request;
8555 request.method = "GET";
8556 request.url = GURL("https://www.google.com/");
8557
8558 // Since we have proxy, should try to establish tunnel.
8559 MockWrite data_writes1[] = {
8560 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8561 "Host: www.google.com\r\n"
8562 "Proxy-Connection: keep-alive\r\n\r\n"),
8563
8564 MockWrite("GET / HTTP/1.1\r\n"
8565 "Host: www.google.com\r\n"
8566 "Connection: keep-alive\r\n\r\n"),
8567 };
8568
8569 MockRead data_reads1[] = {
8570 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8571 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8572 MockRead(ASYNC, 0, 0), // EOF
8573 };
8574
8575 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8576 data_writes1, arraysize(data_writes1));
8577 session_deps.socket_factory.AddSocketDataProvider(&data1);
8578 SSLSocketDataProvider ssl(ASYNC, OK);
8579 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8580
8581 TestCompletionCallback callback1;
8582
8583 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8584
8585 int rv = trans->Start(&request, callback1.callback(), log.bound());
8586 EXPECT_EQ(ERR_IO_PENDING, rv);
8587
8588 rv = callback1.WaitForResult();
8589 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
8590 net::CapturingNetLog::EntryList entries;
8591 log.GetEntries(&entries);
8592 size_t pos = ExpectLogContainsSomewhere(
8593 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
8594 NetLog::PHASE_NONE);
8595 ExpectLogContainsSomewhere(
8596 entries, pos,
8597 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8598 NetLog::PHASE_NONE);
8599 }
8600
8601 // Test for crbug.com/55424.
8602 TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8603 SessionDependencies session_deps;
8604
8605 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8606 "https://www.google.com", false, 1, LOWEST));
8607 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8608
8609 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8610 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8611 MockRead spdy_reads[] = {
8612 CreateMockRead(*resp),
8613 CreateMockRead(*data),
8614 MockRead(ASYNC, 0, 0),
8615 };
8616
8617 scoped_ptr<DelayedSocketData> spdy_data(
8618 new DelayedSocketData(
8619 1, // wait for one write to finish before reading.
8620 spdy_reads, arraysize(spdy_reads),
8621 spdy_writes, arraysize(spdy_writes)));
8622 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
8623
8624 SSLSocketDataProvider ssl(ASYNC, OK);
8625 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
8626 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8627
8628 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8629
8630 // Set up an initial SpdySession in the pool to reuse.
8631 HostPortPair host_port_pair("www.google.com", 443);
8632 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
8633 scoped_refptr<SpdySession> spdy_session =
8634 session->spdy_session_pool()->Get(pair, BoundNetLog());
8635 scoped_refptr<TransportSocketParams> transport_params(
8636 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
8637 TestCompletionCallback callback;
8638
8639 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8640 EXPECT_EQ(ERR_IO_PENDING,
8641 connection->Init(host_port_pair.ToString(), transport_params,
8642 LOWEST, callback.callback(),
8643 session->GetTransportSocketPool(), BoundNetLog()));
8644 EXPECT_EQ(OK, callback.WaitForResult());
8645 spdy_session->InitializeWithSocket(connection.release(), false, OK);
8646
8647 HttpRequestInfo request;
8648 request.method = "GET";
8649 request.url = GURL("https://www.google.com/");
8650 request.load_flags = 0;
8651
8652 // This is the important line that marks this as a preconnect.
8653 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8654
8655 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8656
8657 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8658 EXPECT_EQ(ERR_IO_PENDING, rv);
8659 EXPECT_EQ(OK, callback.WaitForResult());
8660 }
8661
8662 // Given a net error, cause that error to be returned from the first Write()
8663 // call and verify that the HttpTransaction fails with that error.
8664 static void CheckErrorIsPassedBack(int error, IoMode mode) {
8665 net::HttpRequestInfo request_info;
8666 request_info.url = GURL("https://www.example.com/");
8667 request_info.method = "GET";
8668 request_info.load_flags = net::LOAD_NORMAL;
8669
8670 SessionDependencies session_deps;
8671
8672 SSLSocketDataProvider ssl_data(mode, OK);
8673 net::MockWrite data_writes[] = {
8674 net::MockWrite(mode, error),
8675 };
8676 net::StaticSocketDataProvider data(NULL, 0,
8677 data_writes, arraysize(data_writes));
8678 session_deps.socket_factory.AddSocketDataProvider(&data);
8679 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8680
8681 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8682 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8683
8684 TestCompletionCallback callback;
8685 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
8686 if (rv == net::ERR_IO_PENDING)
8687 rv = callback.WaitForResult();
8688 ASSERT_EQ(error, rv);
8689 }
8690
8691 TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8692 // Just check a grab bag of cert errors.
8693 static const int kErrors[] = {
8694 ERR_CERT_COMMON_NAME_INVALID,
8695 ERR_CERT_AUTHORITY_INVALID,
8696 ERR_CERT_DATE_INVALID,
8697 };
8698 for (size_t i = 0; i < arraysize(kErrors); i++) {
8699 CheckErrorIsPassedBack(kErrors[i], ASYNC);
8700 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
8701 }
8702 }
8703
8704 // Ensure that a client certificate is removed from the SSL client auth
8705 // cache when:
8706 // 1) No proxy is involved.
8707 // 2) TLS False Start is disabled.
8708 // 3) The initial TLS handshake requests a client certificate.
8709 // 4) The client supplies an invalid/unacceptable certificate.
8710 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
8711 net::HttpRequestInfo request_info;
8712 request_info.url = GURL("https://www.example.com/");
8713 request_info.method = "GET";
8714 request_info.load_flags = net::LOAD_NORMAL;
8715
8716 SessionDependencies session_deps;
8717
8718 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8719 cert_request->host_and_port = "www.example.com:443";
8720
8721 // [ssl_]data1 contains the data for the first SSL handshake. When a
8722 // CertificateRequest is received for the first time, the handshake will
8723 // be aborted to allow the caller to provide a certificate.
8724 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8725 ssl_data1.cert_request_info = cert_request.get();
8726 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8727 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8728 session_deps.socket_factory.AddSocketDataProvider(&data1);
8729
8730 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8731 // False Start is not being used, the result of the SSL handshake will be
8732 // returned as part of the SSLClientSocket::Connect() call. This test
8733 // matches the result of a server sending a handshake_failure alert,
8734 // rather than a Finished message, because it requires a client
8735 // certificate and none was supplied.
8736 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
8737 ssl_data2.cert_request_info = cert_request.get();
8738 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8739 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8740 session_deps.socket_factory.AddSocketDataProvider(&data2);
8741
8742 // [ssl_]data3 contains the data for the third SSL handshake. When a
8743 // connection to a server fails during an SSL handshake,
8744 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8745 // connection was attempted with TLSv1. This is transparent to the caller
8746 // of the HttpNetworkTransaction. Because this test failure is due to
8747 // requiring a client certificate, this fallback handshake should also
8748 // fail.
8749 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
8750 ssl_data3.cert_request_info = cert_request.get();
8751 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8752 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8753 session_deps.socket_factory.AddSocketDataProvider(&data3);
8754
8755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8756 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8757
8758 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8759 TestCompletionCallback callback;
8760 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
8761 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8762
8763 // Complete the SSL handshake, which should abort due to requiring a
8764 // client certificate.
8765 rv = callback.WaitForResult();
8766 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8767
8768 // Indicate that no certificate should be supplied. From the perspective
8769 // of SSLClientCertCache, NULL is just as meaningful as a real
8770 // certificate, so this is the same as supply a
8771 // legitimate-but-unacceptable certificate.
8772 rv = trans->RestartWithCertificate(NULL, callback.callback());
8773 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8774
8775 // Ensure the certificate was added to the client auth cache before
8776 // allowing the connection to continue restarting.
8777 scoped_refptr<X509Certificate> client_cert;
8778 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8779 &client_cert));
8780 ASSERT_EQ(NULL, client_cert.get());
8781
8782 // Restart the handshake. This will consume ssl_data2, which fails, and
8783 // then consume ssl_data3, which should also fail. The result code is
8784 // checked against what ssl_data3 should return.
8785 rv = callback.WaitForResult();
8786 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8787
8788 // Ensure that the client certificate is removed from the cache on a
8789 // handshake failure.
8790 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8791 &client_cert));
8792 }
8793
8794 // Ensure that a client certificate is removed from the SSL client auth
8795 // cache when:
8796 // 1) No proxy is involved.
8797 // 2) TLS False Start is enabled.
8798 // 3) The initial TLS handshake requests a client certificate.
8799 // 4) The client supplies an invalid/unacceptable certificate.
8800 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
8801 net::HttpRequestInfo request_info;
8802 request_info.url = GURL("https://www.example.com/");
8803 request_info.method = "GET";
8804 request_info.load_flags = net::LOAD_NORMAL;
8805
8806 SessionDependencies session_deps;
8807
8808 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8809 cert_request->host_and_port = "www.example.com:443";
8810
8811 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8812 // return successfully after reading up to the peer's Certificate message.
8813 // This is to allow the caller to call SSLClientSocket::Write(), which can
8814 // enqueue application data to be sent in the same packet as the
8815 // ChangeCipherSpec and Finished messages.
8816 // The actual handshake will be finished when SSLClientSocket::Read() is
8817 // called, which expects to process the peer's ChangeCipherSpec and
8818 // Finished messages. If there was an error negotiating with the peer,
8819 // such as due to the peer requiring a client certificate when none was
8820 // supplied, the alert sent by the peer won't be processed until Read() is
8821 // called.
8822
8823 // Like the non-False Start case, when a client certificate is requested by
8824 // the peer, the handshake is aborted during the Connect() call.
8825 // [ssl_]data1 represents the initial SSL handshake with the peer.
8826 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8827 ssl_data1.cert_request_info = cert_request.get();
8828 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8829 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8830 session_deps.socket_factory.AddSocketDataProvider(&data1);
8831
8832 // When a client certificate is supplied, Connect() will not be aborted
8833 // when the peer requests the certificate. Instead, the handshake will
8834 // artificially succeed, allowing the caller to write the HTTP request to
8835 // the socket. The handshake messages are not processed until Read() is
8836 // called, which then detects that the handshake was aborted, due to the
8837 // peer sending a handshake_failure because it requires a client
8838 // certificate.
8839 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
8840 ssl_data2.cert_request_info = cert_request.get();
8841 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8842 net::MockRead data2_reads[] = {
8843 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8844 };
8845 net::StaticSocketDataProvider data2(
8846 data2_reads, arraysize(data2_reads), NULL, 0);
8847 session_deps.socket_factory.AddSocketDataProvider(&data2);
8848
8849 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8850 // the data for the SSL handshake once the TLSv1 connection falls back to
8851 // SSLv3. It has the same behaviour as [ssl_]data2.
8852 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
8853 ssl_data3.cert_request_info = cert_request.get();
8854 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8855 net::StaticSocketDataProvider data3(
8856 data2_reads, arraysize(data2_reads), NULL, 0);
8857 session_deps.socket_factory.AddSocketDataProvider(&data3);
8858
8859 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8860 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8861
8862 // Begin the initial SSL handshake.
8863 TestCompletionCallback callback;
8864 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
8865 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8866
8867 // Complete the SSL handshake, which should abort due to requiring a
8868 // client certificate.
8869 rv = callback.WaitForResult();
8870 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8871
8872 // Indicate that no certificate should be supplied. From the perspective
8873 // of SSLClientCertCache, NULL is just as meaningful as a real
8874 // certificate, so this is the same as supply a
8875 // legitimate-but-unacceptable certificate.
8876 rv = trans->RestartWithCertificate(NULL, callback.callback());
8877 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8878
8879 // Ensure the certificate was added to the client auth cache before
8880 // allowing the connection to continue restarting.
8881 scoped_refptr<X509Certificate> client_cert;
8882 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8883 &client_cert));
8884 ASSERT_EQ(NULL, client_cert.get());
8885
8886
8887 // Restart the handshake. This will consume ssl_data2, which fails, and
8888 // then consume ssl_data3, which should also fail. The result code is
8889 // checked against what ssl_data3 should return.
8890 rv = callback.WaitForResult();
8891 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8892
8893 // Ensure that the client certificate is removed from the cache on a
8894 // handshake failure.
8895 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8896 &client_cert));
8897 }
8898
8899 // Ensure that a client certificate is removed from the SSL client auth
8900 // cache when:
8901 // 1) An HTTPS proxy is involved.
8902 // 3) The HTTPS proxy requests a client certificate.
8903 // 4) The client supplies an invalid/unacceptable certificate for the
8904 // proxy.
8905 // The test is repeated twice, first for connecting to an HTTPS endpoint,
8906 // then for connecting to an HTTP endpoint.
8907 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8908 SessionDependencies session_deps(
8909 ProxyService::CreateFixed("https://proxy:70"));
8910 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8911 session_deps.net_log = log.bound().net_log();
8912
8913 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8914 cert_request->host_and_port = "proxy:70";
8915
8916 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8917 // [ssl_]data[1-3]. Rather than represending the endpoint
8918 // (www.example.com:443), they represent failures with the HTTPS proxy
8919 // (proxy:70).
8920 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8921 ssl_data1.cert_request_info = cert_request.get();
8922 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8923 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8924 session_deps.socket_factory.AddSocketDataProvider(&data1);
8925
8926 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
8927 ssl_data2.cert_request_info = cert_request.get();
8928 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8929 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8930 session_deps.socket_factory.AddSocketDataProvider(&data2);
8931
8932 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
8933 ssl_data3.cert_request_info = cert_request.get();
8934 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8935 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8936 session_deps.socket_factory.AddSocketDataProvider(&data3);
8937
8938 net::HttpRequestInfo requests[2];
8939 requests[0].url = GURL("https://www.example.com/");
8940 requests[0].method = "GET";
8941 requests[0].load_flags = net::LOAD_NORMAL;
8942
8943 requests[1].url = GURL("http://www.example.com/");
8944 requests[1].method = "GET";
8945 requests[1].load_flags = net::LOAD_NORMAL;
8946
8947 for (size_t i = 0; i < arraysize(requests); ++i) {
8948 session_deps.socket_factory.ResetNextMockIndexes();
8949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8950 scoped_ptr<HttpNetworkTransaction> trans(
8951 new HttpNetworkTransaction(session));
8952
8953 // Begin the SSL handshake with the proxy.
8954 TestCompletionCallback callback;
8955 int rv = trans->Start(
8956 &requests[i], callback.callback(), net::BoundNetLog());
8957 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8958
8959 // Complete the SSL handshake, which should abort due to requiring a
8960 // client certificate.
8961 rv = callback.WaitForResult();
8962 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8963
8964 // Indicate that no certificate should be supplied. From the perspective
8965 // of SSLClientCertCache, NULL is just as meaningful as a real
8966 // certificate, so this is the same as supply a
8967 // legitimate-but-unacceptable certificate.
8968 rv = trans->RestartWithCertificate(NULL, callback.callback());
8969 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8970
8971 // Ensure the certificate was added to the client auth cache before
8972 // allowing the connection to continue restarting.
8973 scoped_refptr<X509Certificate> client_cert;
8974 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8975 &client_cert));
8976 ASSERT_EQ(NULL, client_cert.get());
8977 // Ensure the certificate was NOT cached for the endpoint. This only
8978 // applies to HTTPS requests, but is fine to check for HTTP requests.
8979 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8980 &client_cert));
8981
8982 // Restart the handshake. This will consume ssl_data2, which fails, and
8983 // then consume ssl_data3, which should also fail. The result code is
8984 // checked against what ssl_data3 should return.
8985 rv = callback.WaitForResult();
8986 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8987
8988 // Now that the new handshake has failed, ensure that the client
8989 // certificate was removed from the client auth cache.
8990 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8991 &client_cert));
8992 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8993 &client_cert));
8994 }
8995 }
8996
8997 void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8998 SpdySessionPoolPeer* pool_peer,
8999 std::string host,
9000 int port,
9001 std::string iplist) {
9002 // Create a host resolver dependency that returns address |iplist| for
9003 // resolutions of |host|.
9004 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
9005
9006 // Setup a HostPortProxyPair.
9007 HostPortPair host_port_pair(host, port);
9008 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
9009 ProxyServer::Direct());
9010
9011 // Resolve the host and port.
9012 AddressList addresses;
9013 HostResolver::RequestInfo info(host_port_pair);
9014 TestCompletionCallback callback;
9015 int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL,
9016 BoundNetLog());
9017 if (rv == ERR_IO_PENDING)
9018 rv = callback.WaitForResult();
9019 DCHECK_EQ(OK, rv);
9020
9021 // Add the first address as an alias. It would have been better to call
9022 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
9023 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
9024 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
9025 // the |pair|.
9026 const addrinfo* address = addresses.head();
9027 pool_peer->AddAlias(address, pair);
9028 }
9029
9030 TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
9031 HttpStreamFactory::set_use_alternate_protocols(true);
9032 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9033
9034 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
9035 SessionDependencies session_deps;
9036 MockCachingHostResolver host_resolver;
9037 net::HttpNetworkSession::Params params;
9038 params.client_socket_factory = &session_deps.socket_factory;
9039 params.host_resolver = &host_resolver;
9040 params.cert_verifier = session_deps.cert_verifier.get();
9041 params.proxy_service = session_deps.proxy_service.get();
9042 params.ssl_config_service = session_deps.ssl_config_service;
9043 params.http_auth_handler_factory =
9044 session_deps.http_auth_handler_factory.get();
9045 params.http_server_properties = &session_deps.http_server_properties;
9046 params.net_log = session_deps.net_log;
9047 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
9048 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9049 pool_peer.DisableDomainAuthenticationVerification();
9050
9051 SSLSocketDataProvider ssl(ASYNC, OK);
9052 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
9053 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9054
9055 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9056 "https://www.google.com", false, 1, LOWEST));
9057 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9058 "https://www.gmail.com", false, 3, LOWEST));
9059 MockWrite spdy_writes[] = {
9060 CreateMockWrite(*host1_req, 1),
9061 CreateMockWrite(*host2_req, 4),
9062 };
9063 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9064 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9065 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9066 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9067 MockRead spdy_reads[] = {
9068 CreateMockRead(*host1_resp, 2),
9069 CreateMockRead(*host1_resp_body, 3),
9070 CreateMockRead(*host2_resp, 5),
9071 CreateMockRead(*host2_resp_body, 6),
9072 MockRead(ASYNC, 0, 7),
9073 };
9074
9075 scoped_ptr<OrderedSocketData> spdy_data(
9076 new OrderedSocketData(
9077 spdy_reads, arraysize(spdy_reads),
9078 spdy_writes, arraysize(spdy_writes)));
9079 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
9080
9081 TestCompletionCallback callback;
9082 HttpRequestInfo request1;
9083 request1.method = "GET";
9084 request1.url = GURL("https://www.google.com/");
9085 request1.load_flags = 0;
9086 HttpNetworkTransaction trans1(session);
9087
9088 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
9089 EXPECT_EQ(ERR_IO_PENDING, rv);
9090 EXPECT_EQ(OK, callback.WaitForResult());
9091
9092 const HttpResponseInfo* response = trans1.GetResponseInfo();
9093 ASSERT_TRUE(response != NULL);
9094 ASSERT_TRUE(response->headers != NULL);
9095 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9096
9097 std::string response_data;
9098 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9099 EXPECT_EQ("hello!", response_data);
9100
9101 // Preload www.gmail.com into HostCache.
9102 HostPortPair host_port("www.gmail.com", 443);
9103 HostResolver::RequestInfo resolve_info(host_port);
9104 AddressList ignored;
9105 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
9106 BoundNetLog());
9107 EXPECT_EQ(ERR_IO_PENDING, rv);
9108 rv = callback.WaitForResult();
9109 EXPECT_EQ(OK, rv);
9110
9111 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9112 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9113 // (www.google.com, 443).
9114 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9115 "127.0.0.1");
9116
9117 HttpRequestInfo request2;
9118 request2.method = "GET";
9119 request2.url = GURL("https://www.gmail.com/");
9120 request2.load_flags = 0;
9121 HttpNetworkTransaction trans2(session);
9122
9123 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
9124 EXPECT_EQ(ERR_IO_PENDING, rv);
9125 EXPECT_EQ(OK, callback.WaitForResult());
9126
9127 response = trans2.GetResponseInfo();
9128 ASSERT_TRUE(response != NULL);
9129 ASSERT_TRUE(response->headers != NULL);
9130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9131 EXPECT_TRUE(response->was_fetched_via_spdy);
9132 EXPECT_TRUE(response->was_npn_negotiated);
9133 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9134 EXPECT_EQ("hello!", response_data);
9135
9136 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
9137 HttpStreamFactory::set_use_alternate_protocols(false);
9138 }
9139
9140 class OneTimeCachingHostResolver : public net::HostResolver {
9141 public:
9142 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9143 : host_port_(host_port) {}
9144 virtual ~OneTimeCachingHostResolver() {}
9145
9146 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9147
9148 // HostResolver methods:
9149 virtual int Resolve(const RequestInfo& info,
9150 AddressList* addresses,
9151 const CompletionCallback& callback,
9152 RequestHandle* out_req,
9153 const BoundNetLog& net_log) OVERRIDE {
9154 return host_resolver_.Resolve(
9155 info, addresses, callback, out_req, net_log);
9156 }
9157
9158 virtual int ResolveFromCache(const RequestInfo& info,
9159 AddressList* addresses,
9160 const BoundNetLog& net_log) OVERRIDE {
9161 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9162 if (rv == OK && info.host_port_pair().Equals(host_port_))
9163 host_resolver_.GetHostCache()->clear();
9164 return rv;
9165 }
9166
9167 virtual void CancelRequest(RequestHandle req) OVERRIDE {
9168 host_resolver_.CancelRequest(req);
9169 }
9170
9171 MockCachingHostResolver* GetMockHostResolver() {
9172 return &host_resolver_;
9173 }
9174
9175 private:
9176 MockCachingHostResolver host_resolver_;
9177 const HostPortPair host_port_;
9178 };
9179
9180 TEST_F(HttpNetworkTransactionTest,
9181 UseIPConnectionPoolingWithHostCacheExpiration) {
9182 HttpStreamFactory::set_use_alternate_protocols(true);
9183 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9184
9185 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9186 SessionDependencies session_deps;
9187 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9188 net::HttpNetworkSession::Params params;
9189 params.client_socket_factory = &session_deps.socket_factory;
9190 params.host_resolver = &host_resolver;
9191 params.cert_verifier = session_deps.cert_verifier.get();
9192 params.proxy_service = session_deps.proxy_service.get();
9193 params.ssl_config_service = session_deps.ssl_config_service;
9194 params.http_auth_handler_factory =
9195 session_deps.http_auth_handler_factory.get();
9196 params.http_server_properties = &session_deps.http_server_properties;
9197 params.net_log = session_deps.net_log;
9198 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
9199 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9200 pool_peer.DisableDomainAuthenticationVerification();
9201
9202 SSLSocketDataProvider ssl(ASYNC, OK);
9203 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
9204 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9205
9206 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9207 "https://www.google.com", false, 1, LOWEST));
9208 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9209 "https://www.gmail.com", false, 3, LOWEST));
9210 MockWrite spdy_writes[] = {
9211 CreateMockWrite(*host1_req, 1),
9212 CreateMockWrite(*host2_req, 4),
9213 };
9214 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9215 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9216 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9217 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9218 MockRead spdy_reads[] = {
9219 CreateMockRead(*host1_resp, 2),
9220 CreateMockRead(*host1_resp_body, 3),
9221 CreateMockRead(*host2_resp, 5),
9222 CreateMockRead(*host2_resp_body, 6),
9223 MockRead(ASYNC, 0, 7),
9224 };
9225
9226 scoped_ptr<OrderedSocketData> spdy_data(
9227 new OrderedSocketData(
9228 spdy_reads, arraysize(spdy_reads),
9229 spdy_writes, arraysize(spdy_writes)));
9230 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
9231
9232 TestCompletionCallback callback;
9233 HttpRequestInfo request1;
9234 request1.method = "GET";
9235 request1.url = GURL("https://www.google.com/");
9236 request1.load_flags = 0;
9237 HttpNetworkTransaction trans1(session);
9238
9239 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
9240 EXPECT_EQ(ERR_IO_PENDING, rv);
9241 EXPECT_EQ(OK, callback.WaitForResult());
9242
9243 const HttpResponseInfo* response = trans1.GetResponseInfo();
9244 ASSERT_TRUE(response != NULL);
9245 ASSERT_TRUE(response->headers != NULL);
9246 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9247
9248 std::string response_data;
9249 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9250 EXPECT_EQ("hello!", response_data);
9251
9252 // Preload cache entries into HostCache.
9253 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9254 AddressList ignored;
9255 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
9256 BoundNetLog());
9257 EXPECT_EQ(ERR_IO_PENDING, rv);
9258 rv = callback.WaitForResult();
9259 EXPECT_EQ(OK, rv);
9260
9261 HttpRequestInfo request2;
9262 request2.method = "GET";
9263 request2.url = GURL("https://www.gmail.com/");
9264 request2.load_flags = 0;
9265 HttpNetworkTransaction trans2(session);
9266
9267 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9268 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9269 // (www.google.com, 443).
9270 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9271 "www.google.com", 443, "127.0.0.1");
9272
9273 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
9274 EXPECT_EQ(ERR_IO_PENDING, rv);
9275 EXPECT_EQ(OK, callback.WaitForResult());
9276
9277 response = trans2.GetResponseInfo();
9278 ASSERT_TRUE(response != NULL);
9279 ASSERT_TRUE(response->headers != NULL);
9280 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9281 EXPECT_TRUE(response->was_fetched_via_spdy);
9282 EXPECT_TRUE(response->was_npn_negotiated);
9283 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9284 EXPECT_EQ("hello!", response_data);
9285
9286 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
9287 HttpStreamFactory::set_use_alternate_protocols(false);
9288 }
9289
9290 TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9291 MockRead data_reads1[] = {
9292 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
9293 };
9294 MockRead data_reads2[] = {
9295 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9296 MockRead("hello world"),
9297 MockRead(SYNCHRONOUS, OK),
9298 };
9299 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9300 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9301 StaticSocketDataProvider* data[] = { &data1, &data2 };
9302
9303 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9304
9305 EXPECT_EQ(OK, out.rv);
9306 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9307 EXPECT_EQ("hello world", out.response_data);
9308 }
9309
9310 TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9311 MockWrite data_writes1[] = {
9312 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
9313 };
9314 MockWrite data_writes2[] = {
9315 MockWrite("GET / HTTP/1.1\r\n"
9316 "Host: www.google.com\r\n"
9317 "Connection: keep-alive\r\n\r\n"),
9318 };
9319 MockRead data_reads2[] = {
9320 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9321 MockRead("hello world"),
9322 MockRead(SYNCHRONOUS, OK),
9323 };
9324 StaticSocketDataProvider data1(NULL, 0,
9325 data_writes1, arraysize(data_writes1));
9326 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9327 data_writes2, arraysize(data_writes2));
9328 StaticSocketDataProvider* data[] = { &data1, &data2 };
9329
9330 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9331
9332 EXPECT_EQ(OK, out.rv);
9333 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9334 EXPECT_EQ("hello world", out.response_data);
9335 }
9336
9337 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_network_transaction_spdy3_unittest.cc ('k') | net/http/http_proxy_client_socket_pool_spdy21_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698