OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/websockets/websocket_stream.h" | 5 #include "net/websockets/websocket_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); | 103 stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); |
104 } | 104 } |
105 }; | 105 }; |
106 | 106 |
107 class WebSocketStreamCreateTest : public ::testing::Test { | 107 class WebSocketStreamCreateTest : public ::testing::Test { |
108 public: | 108 public: |
109 WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {} | 109 WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {} |
110 | 110 |
111 void CreateAndConnectCustomResponse( | 111 void CreateAndConnectCustomResponse( |
112 const std::string& socket_url, | 112 const std::string& socket_url, |
| 113 const std::string& socket_host, |
113 const std::string& socket_path, | 114 const std::string& socket_path, |
114 const std::vector<std::string>& sub_protocols, | 115 const std::vector<std::string>& sub_protocols, |
115 const std::string& origin, | 116 const std::string& origin, |
116 const std::string& extra_request_headers, | 117 const std::string& extra_request_headers, |
117 const std::string& response_body, | 118 const std::string& response_body, |
118 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { | 119 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { |
119 url_request_context_host_.SetExpectations( | 120 url_request_context_host_.SetExpectations( |
120 WebSocketStandardRequest(socket_path, origin, extra_request_headers), | 121 WebSocketStandardRequest(socket_path, socket_host, origin, |
| 122 extra_request_headers), |
121 response_body); | 123 response_body); |
122 CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass()); | 124 CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass()); |
123 } | 125 } |
124 | 126 |
125 // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or | 127 // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or |
126 // errors like "Unable to perform synchronous IO while stopped" will occur. | 128 // errors like "Unable to perform synchronous IO while stopped" will occur. |
127 void CreateAndConnectStandard(const std::string& socket_url, | 129 void CreateAndConnectStandard( |
128 const std::string& socket_path, | 130 const std::string& socket_url, |
129 const std::vector<std::string>& sub_protocols, | 131 const std::string& socket_host, |
130 const std::string& origin, | 132 const std::string& socket_path, |
131 const std::string& extra_request_headers, | 133 const std::vector<std::string>& sub_protocols, |
132 const std::string& extra_response_headers, | 134 const std::string& origin, |
133 scoped_ptr<base::Timer> timer = | 135 const std::string& extra_request_headers, |
134 scoped_ptr<base::Timer>()) { | 136 const std::string& extra_response_headers, |
| 137 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { |
135 CreateAndConnectCustomResponse( | 138 CreateAndConnectCustomResponse( |
136 socket_url, | 139 socket_url, socket_host, socket_path, sub_protocols, origin, |
137 socket_path, | |
138 sub_protocols, | |
139 origin, | |
140 extra_request_headers, | 140 extra_request_headers, |
141 WebSocketStandardResponse(extra_response_headers), | 141 WebSocketStandardResponse(extra_response_headers), timer.Pass()); |
142 timer.Pass()); | |
143 } | 142 } |
144 | 143 |
145 void CreateAndConnectRawExpectations( | 144 void CreateAndConnectRawExpectations( |
146 const std::string& socket_url, | 145 const std::string& socket_url, |
147 const std::vector<std::string>& sub_protocols, | 146 const std::vector<std::string>& sub_protocols, |
148 const std::string& origin, | 147 const std::string& origin, |
149 scoped_ptr<DeterministicSocketData> socket_data, | 148 scoped_ptr<DeterministicSocketData> socket_data, |
150 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { | 149 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { |
151 AddRawExpectations(socket_data.Pass()); | 150 AddRawExpectations(socket_data.Pass()); |
152 CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass()); | 151 CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass()); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 // There are enough tests of the Sec-WebSocket-Extensions header that they | 253 // There are enough tests of the Sec-WebSocket-Extensions header that they |
255 // deserve their own test fixture. | 254 // deserve their own test fixture. |
256 class WebSocketStreamCreateExtensionTest : public WebSocketStreamCreateTest { | 255 class WebSocketStreamCreateExtensionTest : public WebSocketStreamCreateTest { |
257 public: | 256 public: |
258 // Performs a standard connect, with the value of the Sec-WebSocket-Extensions | 257 // Performs a standard connect, with the value of the Sec-WebSocket-Extensions |
259 // header in the response set to |extensions_header_value|. Runs the event | 258 // header in the response set to |extensions_header_value|. Runs the event |
260 // loop to allow the connect to complete. | 259 // loop to allow the connect to complete. |
261 void CreateAndConnectWithExtensions( | 260 void CreateAndConnectWithExtensions( |
262 const std::string& extensions_header_value) { | 261 const std::string& extensions_header_value) { |
263 CreateAndConnectStandard( | 262 CreateAndConnectStandard( |
264 "ws://localhost/testing_path", | 263 "ws://localhost/testing_path", "localhost", "/testing_path", |
265 "/testing_path", | 264 NoSubProtocols(), "http://localhost", "", |
266 NoSubProtocols(), | |
267 "http://localhost", | |
268 "", | |
269 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); | 265 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); |
270 RunUntilIdle(); | 266 RunUntilIdle(); |
271 } | 267 } |
272 }; | 268 }; |
273 | 269 |
274 // Common code to construct expectations for authentication tests that receive | 270 // Common code to construct expectations for authentication tests that receive |
275 // the auth challenge on one connection and then create a second connection to | 271 // the auth challenge on one connection and then create a second connection to |
276 // send the authenticated request on. | 272 // send the authenticated request on. |
277 class CommonAuthTestHelper { | 273 class CommonAuthTestHelper { |
278 public: | 274 public: |
279 CommonAuthTestHelper() : reads1_(), writes1_(), reads2_(), writes2_() {} | 275 CommonAuthTestHelper() : reads1_(), writes1_(), reads2_(), writes2_() {} |
280 | 276 |
281 scoped_ptr<DeterministicSocketData> BuildSocketData1( | 277 scoped_ptr<DeterministicSocketData> BuildSocketData1( |
282 const std::string& response) { | 278 const std::string& response) { |
283 request1_ = WebSocketStandardRequest("/", "http://localhost", ""); | 279 request1_ = |
| 280 WebSocketStandardRequest("/", "localhost", "http://localhost", ""); |
284 writes1_[0] = MockWrite(SYNCHRONOUS, 0, request1_.c_str()); | 281 writes1_[0] = MockWrite(SYNCHRONOUS, 0, request1_.c_str()); |
285 response1_ = response; | 282 response1_ = response; |
286 reads1_[0] = MockRead(SYNCHRONOUS, 1, response1_.c_str()); | 283 reads1_[0] = MockRead(SYNCHRONOUS, 1, response1_.c_str()); |
287 reads1_[1] = MockRead(SYNCHRONOUS, OK, 2); // Close connection | 284 reads1_[1] = MockRead(SYNCHRONOUS, OK, 2); // Close connection |
288 | 285 |
289 return BuildSocketData(reads1_, writes1_); | 286 return BuildSocketData(reads1_, writes1_); |
290 } | 287 } |
291 | 288 |
292 scoped_ptr<DeterministicSocketData> BuildSocketData2( | 289 scoped_ptr<DeterministicSocketData> BuildSocketData2( |
293 const std::string& request, | 290 const std::string& request, |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 scoped_ptr<base::HistogramSamples> GetSamples(const std::string& name) { | 411 scoped_ptr<base::HistogramSamples> GetSamples(const std::string& name) { |
415 base::HistogramBase* histogram = | 412 base::HistogramBase* histogram = |
416 base::StatisticsRecorder::FindHistogram(name); | 413 base::StatisticsRecorder::FindHistogram(name); |
417 return histogram ? histogram->SnapshotSamples() | 414 return histogram ? histogram->SnapshotSamples() |
418 : scoped_ptr<base::HistogramSamples>(); | 415 : scoped_ptr<base::HistogramSamples>(); |
419 } | 416 } |
420 }; | 417 }; |
421 | 418 |
422 // Confirm that the basic case works as expected. | 419 // Confirm that the basic case works as expected. |
423 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { | 420 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { |
424 CreateAndConnectStandard( | 421 CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
425 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); | 422 NoSubProtocols(), "http://localhost", "", ""); |
426 EXPECT_FALSE(request_info_); | 423 EXPECT_FALSE(request_info_); |
427 EXPECT_FALSE(response_info_); | 424 EXPECT_FALSE(response_info_); |
428 RunUntilIdle(); | 425 RunUntilIdle(); |
429 EXPECT_FALSE(has_failed()); | 426 EXPECT_FALSE(has_failed()); |
430 EXPECT_TRUE(stream_); | 427 EXPECT_TRUE(stream_); |
431 EXPECT_TRUE(request_info_); | 428 EXPECT_TRUE(request_info_); |
432 EXPECT_TRUE(response_info_); | 429 EXPECT_TRUE(response_info_); |
433 } | 430 } |
434 | 431 |
435 TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { | 432 TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { |
436 static const char kResponse[] = | 433 static const char kResponse[] = |
437 "HTTP/1.1 101 Switching Protocols\r\n" | 434 "HTTP/1.1 101 Switching Protocols\r\n" |
438 "Upgrade: websocket\r\n" | 435 "Upgrade: websocket\r\n" |
439 "Connection: Upgrade\r\n" | 436 "Connection: Upgrade\r\n" |
440 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 437 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
441 "foo: bar, baz\r\n" | 438 "foo: bar, baz\r\n" |
442 "hoge: fuga\r\n" | 439 "hoge: fuga\r\n" |
443 "hoge: piyo\r\n" | 440 "hoge: piyo\r\n" |
444 "\r\n"; | 441 "\r\n"; |
445 | 442 |
446 CreateAndConnectCustomResponse( | 443 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
447 "ws://localhost/", | 444 NoSubProtocols(), "http://localhost", "", |
448 "/", | 445 kResponse); |
449 NoSubProtocols(), | |
450 "http://localhost", | |
451 "", | |
452 kResponse); | |
453 EXPECT_FALSE(request_info_); | 446 EXPECT_FALSE(request_info_); |
454 EXPECT_FALSE(response_info_); | 447 EXPECT_FALSE(response_info_); |
455 RunUntilIdle(); | 448 RunUntilIdle(); |
456 EXPECT_TRUE(stream_); | 449 EXPECT_TRUE(stream_); |
457 ASSERT_TRUE(request_info_); | 450 ASSERT_TRUE(request_info_); |
458 ASSERT_TRUE(response_info_); | 451 ASSERT_TRUE(response_info_); |
459 std::vector<HeaderKeyValuePair> request_headers = | 452 std::vector<HeaderKeyValuePair> request_headers = |
460 ToVector(request_info_->headers); | 453 ToVector(request_info_->headers); |
461 // We examine the contents of request_info_ and response_info_ | 454 // We examine the contents of request_info_ and response_info_ |
462 // mainly only in this test case. | 455 // mainly only in this test case. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]); | 487 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]); |
495 EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); | 488 EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); |
496 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); | 489 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); |
497 EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); | 490 EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); |
498 EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); | 491 EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); |
499 EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); | 492 EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); |
500 } | 493 } |
501 | 494 |
502 // Confirm that the stream isn't established until the message loop runs. | 495 // Confirm that the stream isn't established until the message loop runs. |
503 TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { | 496 TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { |
504 CreateAndConnectStandard( | 497 CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
505 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); | 498 NoSubProtocols(), "http://localhost", "", ""); |
506 EXPECT_FALSE(has_failed()); | 499 EXPECT_FALSE(has_failed()); |
507 EXPECT_FALSE(stream_); | 500 EXPECT_FALSE(stream_); |
508 } | 501 } |
509 | 502 |
510 // Check the path is used. | 503 // Check the path is used. |
511 TEST_F(WebSocketStreamCreateTest, PathIsUsed) { | 504 TEST_F(WebSocketStreamCreateTest, PathIsUsed) { |
512 CreateAndConnectStandard("ws://localhost/testing_path", | 505 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
513 "/testing_path", | 506 "/testing_path", NoSubProtocols(), |
514 NoSubProtocols(), | 507 "http://localhost", "", ""); |
515 "http://localhost", | |
516 "", | |
517 ""); | |
518 RunUntilIdle(); | 508 RunUntilIdle(); |
519 EXPECT_FALSE(has_failed()); | 509 EXPECT_FALSE(has_failed()); |
520 EXPECT_TRUE(stream_); | 510 EXPECT_TRUE(stream_); |
521 } | 511 } |
522 | 512 |
523 // Check that the origin is used. | 513 // Check that the origin is used. |
524 TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { | 514 TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { |
525 CreateAndConnectStandard("ws://localhost/testing_path", | 515 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
526 "/testing_path", | 516 "/testing_path", NoSubProtocols(), |
527 NoSubProtocols(), | 517 "http://google.com", "", ""); |
528 "http://google.com", | |
529 "", | |
530 ""); | |
531 RunUntilIdle(); | 518 RunUntilIdle(); |
532 EXPECT_FALSE(has_failed()); | 519 EXPECT_FALSE(has_failed()); |
533 EXPECT_TRUE(stream_); | 520 EXPECT_TRUE(stream_); |
534 } | 521 } |
535 | 522 |
536 // Check that sub-protocols are sent and parsed. | 523 // Check that sub-protocols are sent and parsed. |
537 TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { | 524 TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { |
538 std::vector<std::string> sub_protocols; | 525 std::vector<std::string> sub_protocols; |
539 sub_protocols.push_back("chatv11.chromium.org"); | 526 sub_protocols.push_back("chatv11.chromium.org"); |
540 sub_protocols.push_back("chatv20.chromium.org"); | 527 sub_protocols.push_back("chatv20.chromium.org"); |
541 CreateAndConnectStandard("ws://localhost/testing_path", | 528 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
542 "/testing_path", | 529 "/testing_path", sub_protocols, "http://google.com", |
543 sub_protocols, | |
544 "http://google.com", | |
545 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 530 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
546 "chatv20.chromium.org\r\n", | 531 "chatv20.chromium.org\r\n", |
547 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); | 532 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); |
548 RunUntilIdle(); | 533 RunUntilIdle(); |
549 EXPECT_TRUE(stream_); | 534 EXPECT_TRUE(stream_); |
550 EXPECT_FALSE(has_failed()); | 535 EXPECT_FALSE(has_failed()); |
551 EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); | 536 EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); |
552 } | 537 } |
553 | 538 |
554 // Unsolicited sub-protocols are rejected. | 539 // Unsolicited sub-protocols are rejected. |
555 TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { | 540 TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { |
556 CreateAndConnectStandard("ws://localhost/testing_path", | 541 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
557 "/testing_path", | 542 "/testing_path", NoSubProtocols(), |
558 NoSubProtocols(), | 543 "http://google.com", "", |
559 "http://google.com", | |
560 "", | |
561 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); | 544 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); |
562 RunUntilIdle(); | 545 RunUntilIdle(); |
563 EXPECT_FALSE(stream_); | 546 EXPECT_FALSE(stream_); |
564 EXPECT_TRUE(has_failed()); | 547 EXPECT_TRUE(has_failed()); |
565 EXPECT_EQ("Error during WebSocket handshake: " | 548 EXPECT_EQ("Error during WebSocket handshake: " |
566 "Response must not include 'Sec-WebSocket-Protocol' header " | 549 "Response must not include 'Sec-WebSocket-Protocol' header " |
567 "if not present in request: chatv20.chromium.org", | 550 "if not present in request: chatv20.chromium.org", |
568 failure_message()); | 551 failure_message()); |
569 } | 552 } |
570 | 553 |
571 // Missing sub-protocol response is rejected. | 554 // Missing sub-protocol response is rejected. |
572 TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { | 555 TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { |
573 std::vector<std::string> sub_protocols; | 556 std::vector<std::string> sub_protocols; |
574 sub_protocols.push_back("chat.example.com"); | 557 sub_protocols.push_back("chat.example.com"); |
575 CreateAndConnectStandard("ws://localhost/testing_path", | 558 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
576 "/testing_path", | 559 "/testing_path", sub_protocols, "http://localhost", |
577 sub_protocols, | 560 "Sec-WebSocket-Protocol: chat.example.com\r\n", ""); |
578 "http://localhost", | |
579 "Sec-WebSocket-Protocol: chat.example.com\r\n", | |
580 ""); | |
581 RunUntilIdle(); | 561 RunUntilIdle(); |
582 EXPECT_FALSE(stream_); | 562 EXPECT_FALSE(stream_); |
583 EXPECT_TRUE(has_failed()); | 563 EXPECT_TRUE(has_failed()); |
584 EXPECT_EQ("Error during WebSocket handshake: " | 564 EXPECT_EQ("Error during WebSocket handshake: " |
585 "Sent non-empty 'Sec-WebSocket-Protocol' header " | 565 "Sent non-empty 'Sec-WebSocket-Protocol' header " |
586 "but no response was received", | 566 "but no response was received", |
587 failure_message()); | 567 failure_message()); |
588 } | 568 } |
589 | 569 |
590 // Only one sub-protocol can be accepted. | 570 // Only one sub-protocol can be accepted. |
591 TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { | 571 TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { |
592 std::vector<std::string> sub_protocols; | 572 std::vector<std::string> sub_protocols; |
593 sub_protocols.push_back("chatv11.chromium.org"); | 573 sub_protocols.push_back("chatv11.chromium.org"); |
594 sub_protocols.push_back("chatv20.chromium.org"); | 574 sub_protocols.push_back("chatv20.chromium.org"); |
595 CreateAndConnectStandard("ws://localhost/testing_path", | 575 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
596 "/testing_path", | 576 "/testing_path", sub_protocols, "http://google.com", |
597 sub_protocols, | |
598 "http://google.com", | |
599 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 577 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
600 "chatv20.chromium.org\r\n", | 578 "chatv20.chromium.org\r\n", |
601 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 579 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
602 "chatv20.chromium.org\r\n"); | 580 "chatv20.chromium.org\r\n"); |
603 RunUntilIdle(); | 581 RunUntilIdle(); |
604 EXPECT_FALSE(stream_); | 582 EXPECT_FALSE(stream_); |
605 EXPECT_TRUE(has_failed()); | 583 EXPECT_TRUE(has_failed()); |
606 EXPECT_EQ("Error during WebSocket handshake: " | 584 EXPECT_EQ("Error during WebSocket handshake: " |
607 "'Sec-WebSocket-Protocol' header must not appear " | 585 "'Sec-WebSocket-Protocol' header must not appear " |
608 "more than once in a response", | 586 "more than once in a response", |
609 failure_message()); | 587 failure_message()); |
610 } | 588 } |
611 | 589 |
612 // Unmatched sub-protocol should be rejected. | 590 // Unmatched sub-protocol should be rejected. |
613 TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { | 591 TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { |
614 std::vector<std::string> sub_protocols; | 592 std::vector<std::string> sub_protocols; |
615 sub_protocols.push_back("chatv11.chromium.org"); | 593 sub_protocols.push_back("chatv11.chromium.org"); |
616 sub_protocols.push_back("chatv20.chromium.org"); | 594 sub_protocols.push_back("chatv20.chromium.org"); |
617 CreateAndConnectStandard("ws://localhost/testing_path", | 595 CreateAndConnectStandard("ws://localhost/testing_path", "localhost", |
618 "/testing_path", | 596 "/testing_path", sub_protocols, "http://google.com", |
619 sub_protocols, | |
620 "http://google.com", | |
621 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 597 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
622 "chatv20.chromium.org\r\n", | 598 "chatv20.chromium.org\r\n", |
623 "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); | 599 "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); |
624 RunUntilIdle(); | 600 RunUntilIdle(); |
625 EXPECT_FALSE(stream_); | 601 EXPECT_FALSE(stream_); |
626 EXPECT_TRUE(has_failed()); | 602 EXPECT_TRUE(has_failed()); |
627 EXPECT_EQ("Error during WebSocket handshake: " | 603 EXPECT_EQ("Error during WebSocket handshake: " |
628 "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " | 604 "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " |
629 "in response does not match any of sent values", | 605 "in response does not match any of sent values", |
630 failure_message()); | 606 failure_message()); |
(...skipping 13 matching lines...) Expand all Loading... |
644 "server_max_window_bits=11; client_max_window_bits=13; " | 620 "server_max_window_bits=11; client_max_window_bits=13; " |
645 "server_no_context_takeover"); | 621 "server_no_context_takeover"); |
646 EXPECT_TRUE(stream_); | 622 EXPECT_TRUE(stream_); |
647 EXPECT_FALSE(has_failed()); | 623 EXPECT_FALSE(has_failed()); |
648 } | 624 } |
649 | 625 |
650 // Verify that incoming messages are actually decompressed with | 626 // Verify that incoming messages are actually decompressed with |
651 // permessage-deflate enabled. | 627 // permessage-deflate enabled. |
652 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { | 628 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { |
653 CreateAndConnectCustomResponse( | 629 CreateAndConnectCustomResponse( |
654 "ws://localhost/testing_path", | 630 "ws://localhost/testing_path", "localhost", "/testing_path", |
655 "/testing_path", | 631 NoSubProtocols(), "http://localhost", "", |
656 NoSubProtocols(), | |
657 "http://localhost", | |
658 "", | |
659 WebSocketStandardResponse( | 632 WebSocketStandardResponse( |
660 "Sec-WebSocket-Extensions: permessage-deflate\r\n") + | 633 "Sec-WebSocket-Extensions: permessage-deflate\r\n") + |
661 std::string( | 634 std::string( |
662 "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) | 635 "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) |
663 "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed | 636 "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed |
664 9)); | 637 9)); |
665 RunUntilIdle(); | 638 RunUntilIdle(); |
666 | 639 |
667 ASSERT_TRUE(stream_); | 640 ASSERT_TRUE(stream_); |
668 ScopedVector<WebSocketFrame> frames; | 641 ScopedVector<WebSocketFrame> frames; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 failure_message()); | 803 failure_message()); |
831 } | 804 } |
832 | 805 |
833 // TODO(ricea): Check that WebSocketDeflateStream is initialised with the | 806 // TODO(ricea): Check that WebSocketDeflateStream is initialised with the |
834 // arguments from the server. This is difficult because the data written to the | 807 // arguments from the server. This is difficult because the data written to the |
835 // socket is randomly masked. | 808 // socket is randomly masked. |
836 | 809 |
837 // Additional Sec-WebSocket-Accept headers should be rejected. | 810 // Additional Sec-WebSocket-Accept headers should be rejected. |
838 TEST_F(WebSocketStreamCreateTest, DoubleAccept) { | 811 TEST_F(WebSocketStreamCreateTest, DoubleAccept) { |
839 CreateAndConnectStandard( | 812 CreateAndConnectStandard( |
840 "ws://localhost/", | 813 "ws://localhost/", "localhost", "/", NoSubProtocols(), "http://localhost", |
841 "/", | 814 "", "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); |
842 NoSubProtocols(), | |
843 "http://localhost", | |
844 "", | |
845 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); | |
846 RunUntilIdle(); | 815 RunUntilIdle(); |
847 EXPECT_FALSE(stream_); | 816 EXPECT_FALSE(stream_); |
848 EXPECT_TRUE(has_failed()); | 817 EXPECT_TRUE(has_failed()); |
849 EXPECT_EQ("Error during WebSocket handshake: " | 818 EXPECT_EQ("Error during WebSocket handshake: " |
850 "'Sec-WebSocket-Accept' header must not appear " | 819 "'Sec-WebSocket-Accept' header must not appear " |
851 "more than once in a response", | 820 "more than once in a response", |
852 failure_message()); | 821 failure_message()); |
853 } | 822 } |
854 | 823 |
855 // Response code 200 must be rejected. | 824 // Response code 200 must be rejected. |
856 TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { | 825 TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { |
857 static const char kInvalidStatusCodeResponse[] = | 826 static const char kInvalidStatusCodeResponse[] = |
858 "HTTP/1.1 200 OK\r\n" | 827 "HTTP/1.1 200 OK\r\n" |
859 "Upgrade: websocket\r\n" | 828 "Upgrade: websocket\r\n" |
860 "Connection: Upgrade\r\n" | 829 "Connection: Upgrade\r\n" |
861 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 830 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
862 "\r\n"; | 831 "\r\n"; |
863 CreateAndConnectCustomResponse("ws://localhost/", | 832 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
864 "/", | 833 NoSubProtocols(), "http://localhost", "", |
865 NoSubProtocols(), | |
866 "http://localhost", | |
867 "", | |
868 kInvalidStatusCodeResponse); | 834 kInvalidStatusCodeResponse); |
869 RunUntilIdle(); | 835 RunUntilIdle(); |
870 EXPECT_TRUE(has_failed()); | 836 EXPECT_TRUE(has_failed()); |
871 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", | 837 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", |
872 failure_message()); | 838 failure_message()); |
873 } | 839 } |
874 | 840 |
875 // Redirects are not followed (according to the WHATWG WebSocket API, which | 841 // Redirects are not followed (according to the WHATWG WebSocket API, which |
876 // overrides RFC6455 for browser applications). | 842 // overrides RFC6455 for browser applications). |
877 TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { | 843 TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { |
878 static const char kRedirectResponse[] = | 844 static const char kRedirectResponse[] = |
879 "HTTP/1.1 302 Moved Temporarily\r\n" | 845 "HTTP/1.1 302 Moved Temporarily\r\n" |
880 "Content-Type: text/html\r\n" | 846 "Content-Type: text/html\r\n" |
881 "Content-Length: 34\r\n" | 847 "Content-Length: 34\r\n" |
882 "Connection: keep-alive\r\n" | 848 "Connection: keep-alive\r\n" |
883 "Location: ws://localhost/other\r\n" | 849 "Location: ws://localhost/other\r\n" |
884 "\r\n" | 850 "\r\n" |
885 "<title>Moved</title><h1>Moved</h1>"; | 851 "<title>Moved</title><h1>Moved</h1>"; |
886 CreateAndConnectCustomResponse("ws://localhost/", | 852 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
887 "/", | 853 NoSubProtocols(), "http://localhost", "", |
888 NoSubProtocols(), | |
889 "http://localhost", | |
890 "", | |
891 kRedirectResponse); | 854 kRedirectResponse); |
892 RunUntilIdle(); | 855 RunUntilIdle(); |
893 EXPECT_TRUE(has_failed()); | 856 EXPECT_TRUE(has_failed()); |
894 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", | 857 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", |
895 failure_message()); | 858 failure_message()); |
896 } | 859 } |
897 | 860 |
898 // Malformed responses should be rejected. HttpStreamParser will accept just | 861 // Malformed responses should be rejected. HttpStreamParser will accept just |
899 // about any garbage in the middle of the headers. To make it give up, the junk | 862 // about any garbage in the middle of the headers. To make it give up, the junk |
900 // has to be at the start of the response. Even then, it just gets treated as an | 863 // has to be at the start of the response. Even then, it just gets treated as an |
901 // HTTP/0.9 response. | 864 // HTTP/0.9 response. |
902 TEST_F(WebSocketStreamCreateTest, MalformedResponse) { | 865 TEST_F(WebSocketStreamCreateTest, MalformedResponse) { |
903 static const char kMalformedResponse[] = | 866 static const char kMalformedResponse[] = |
904 "220 mx.google.com ESMTP\r\n" | 867 "220 mx.google.com ESMTP\r\n" |
905 "HTTP/1.1 101 OK\r\n" | 868 "HTTP/1.1 101 OK\r\n" |
906 "Upgrade: websocket\r\n" | 869 "Upgrade: websocket\r\n" |
907 "Connection: Upgrade\r\n" | 870 "Connection: Upgrade\r\n" |
908 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 871 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
909 "\r\n"; | 872 "\r\n"; |
910 CreateAndConnectCustomResponse("ws://localhost/", | 873 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
911 "/", | 874 NoSubProtocols(), "http://localhost", "", |
912 NoSubProtocols(), | |
913 "http://localhost", | |
914 "", | |
915 kMalformedResponse); | 875 kMalformedResponse); |
916 RunUntilIdle(); | 876 RunUntilIdle(); |
917 EXPECT_TRUE(has_failed()); | 877 EXPECT_TRUE(has_failed()); |
918 EXPECT_EQ("Error during WebSocket handshake: Invalid status line", | 878 EXPECT_EQ("Error during WebSocket handshake: Invalid status line", |
919 failure_message()); | 879 failure_message()); |
920 } | 880 } |
921 | 881 |
922 // Upgrade header must be present. | 882 // Upgrade header must be present. |
923 TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { | 883 TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { |
924 static const char kMissingUpgradeResponse[] = | 884 static const char kMissingUpgradeResponse[] = |
925 "HTTP/1.1 101 Switching Protocols\r\n" | 885 "HTTP/1.1 101 Switching Protocols\r\n" |
926 "Connection: Upgrade\r\n" | 886 "Connection: Upgrade\r\n" |
927 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 887 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
928 "\r\n"; | 888 "\r\n"; |
929 CreateAndConnectCustomResponse("ws://localhost/", | 889 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
930 "/", | 890 NoSubProtocols(), "http://localhost", "", |
931 NoSubProtocols(), | |
932 "http://localhost", | |
933 "", | |
934 kMissingUpgradeResponse); | 891 kMissingUpgradeResponse); |
935 RunUntilIdle(); | 892 RunUntilIdle(); |
936 EXPECT_TRUE(has_failed()); | 893 EXPECT_TRUE(has_failed()); |
937 EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", | 894 EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", |
938 failure_message()); | 895 failure_message()); |
939 } | 896 } |
940 | 897 |
941 // There must only be one upgrade header. | 898 // There must only be one upgrade header. |
942 TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { | 899 TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { |
943 CreateAndConnectStandard( | 900 CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
944 "ws://localhost/", | 901 NoSubProtocols(), "http://localhost", "", |
945 "/", | 902 "Upgrade: HTTP/2.0\r\n"); |
946 NoSubProtocols(), | |
947 "http://localhost", | |
948 "", "Upgrade: HTTP/2.0\r\n"); | |
949 RunUntilIdle(); | 903 RunUntilIdle(); |
950 EXPECT_TRUE(has_failed()); | 904 EXPECT_TRUE(has_failed()); |
951 EXPECT_EQ("Error during WebSocket handshake: " | 905 EXPECT_EQ("Error during WebSocket handshake: " |
952 "'Upgrade' header must not appear more than once in a response", | 906 "'Upgrade' header must not appear more than once in a response", |
953 failure_message()); | 907 failure_message()); |
954 } | 908 } |
955 | 909 |
956 // There must only be one correct upgrade header. | 910 // There must only be one correct upgrade header. |
957 TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { | 911 TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { |
958 static const char kMissingUpgradeResponse[] = | 912 static const char kMissingUpgradeResponse[] = |
959 "HTTP/1.1 101 Switching Protocols\r\n" | 913 "HTTP/1.1 101 Switching Protocols\r\n" |
960 "Connection: Upgrade\r\n" | 914 "Connection: Upgrade\r\n" |
961 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 915 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
962 "Upgrade: hogefuga\r\n" | 916 "Upgrade: hogefuga\r\n" |
963 "\r\n"; | 917 "\r\n"; |
964 CreateAndConnectCustomResponse("ws://localhost/", | 918 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
965 "/", | 919 NoSubProtocols(), "http://localhost", "", |
966 NoSubProtocols(), | |
967 "http://localhost", | |
968 "", | |
969 kMissingUpgradeResponse); | 920 kMissingUpgradeResponse); |
970 RunUntilIdle(); | 921 RunUntilIdle(); |
971 EXPECT_TRUE(has_failed()); | 922 EXPECT_TRUE(has_failed()); |
972 EXPECT_EQ("Error during WebSocket handshake: " | 923 EXPECT_EQ("Error during WebSocket handshake: " |
973 "'Upgrade' header value is not 'WebSocket': hogefuga", | 924 "'Upgrade' header value is not 'WebSocket': hogefuga", |
974 failure_message()); | 925 failure_message()); |
975 } | 926 } |
976 | 927 |
977 // Connection header must be present. | 928 // Connection header must be present. |
978 TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { | 929 TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { |
979 static const char kMissingConnectionResponse[] = | 930 static const char kMissingConnectionResponse[] = |
980 "HTTP/1.1 101 Switching Protocols\r\n" | 931 "HTTP/1.1 101 Switching Protocols\r\n" |
981 "Upgrade: websocket\r\n" | 932 "Upgrade: websocket\r\n" |
982 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 933 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
983 "\r\n"; | 934 "\r\n"; |
984 CreateAndConnectCustomResponse("ws://localhost/", | 935 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
985 "/", | 936 NoSubProtocols(), "http://localhost", "", |
986 NoSubProtocols(), | |
987 "http://localhost", | |
988 "", | |
989 kMissingConnectionResponse); | 937 kMissingConnectionResponse); |
990 RunUntilIdle(); | 938 RunUntilIdle(); |
991 EXPECT_TRUE(has_failed()); | 939 EXPECT_TRUE(has_failed()); |
992 EXPECT_EQ("Error during WebSocket handshake: " | 940 EXPECT_EQ("Error during WebSocket handshake: " |
993 "'Connection' header is missing", | 941 "'Connection' header is missing", |
994 failure_message()); | 942 failure_message()); |
995 } | 943 } |
996 | 944 |
997 // Connection header must contain "Upgrade". | 945 // Connection header must contain "Upgrade". |
998 TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { | 946 TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { |
999 static const char kMissingConnectionResponse[] = | 947 static const char kMissingConnectionResponse[] = |
1000 "HTTP/1.1 101 Switching Protocols\r\n" | 948 "HTTP/1.1 101 Switching Protocols\r\n" |
1001 "Upgrade: websocket\r\n" | 949 "Upgrade: websocket\r\n" |
1002 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 950 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
1003 "Connection: hogefuga\r\n" | 951 "Connection: hogefuga\r\n" |
1004 "\r\n"; | 952 "\r\n"; |
1005 CreateAndConnectCustomResponse("ws://localhost/", | 953 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
1006 "/", | 954 NoSubProtocols(), "http://localhost", "", |
1007 NoSubProtocols(), | |
1008 "http://localhost", | |
1009 "", | |
1010 kMissingConnectionResponse); | 955 kMissingConnectionResponse); |
1011 RunUntilIdle(); | 956 RunUntilIdle(); |
1012 EXPECT_TRUE(has_failed()); | 957 EXPECT_TRUE(has_failed()); |
1013 EXPECT_EQ("Error during WebSocket handshake: " | 958 EXPECT_EQ("Error during WebSocket handshake: " |
1014 "'Connection' header value must contain 'Upgrade'", | 959 "'Connection' header value must contain 'Upgrade'", |
1015 failure_message()); | 960 failure_message()); |
1016 } | 961 } |
1017 | 962 |
1018 // Connection header is permitted to contain other tokens. | 963 // Connection header is permitted to contain other tokens. |
1019 TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { | 964 TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { |
1020 static const char kAdditionalConnectionTokenResponse[] = | 965 static const char kAdditionalConnectionTokenResponse[] = |
1021 "HTTP/1.1 101 Switching Protocols\r\n" | 966 "HTTP/1.1 101 Switching Protocols\r\n" |
1022 "Upgrade: websocket\r\n" | 967 "Upgrade: websocket\r\n" |
1023 "Connection: Upgrade, Keep-Alive\r\n" | 968 "Connection: Upgrade, Keep-Alive\r\n" |
1024 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 969 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
1025 "\r\n"; | 970 "\r\n"; |
1026 CreateAndConnectCustomResponse("ws://localhost/", | 971 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
1027 "/", | 972 NoSubProtocols(), "http://localhost", "", |
1028 NoSubProtocols(), | |
1029 "http://localhost", | |
1030 "", | |
1031 kAdditionalConnectionTokenResponse); | 973 kAdditionalConnectionTokenResponse); |
1032 RunUntilIdle(); | 974 RunUntilIdle(); |
1033 EXPECT_FALSE(has_failed()); | 975 EXPECT_FALSE(has_failed()); |
1034 EXPECT_TRUE(stream_); | 976 EXPECT_TRUE(stream_); |
1035 } | 977 } |
1036 | 978 |
1037 // Sec-WebSocket-Accept header must be present. | 979 // Sec-WebSocket-Accept header must be present. |
1038 TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { | 980 TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { |
1039 static const char kMissingAcceptResponse[] = | 981 static const char kMissingAcceptResponse[] = |
1040 "HTTP/1.1 101 Switching Protocols\r\n" | 982 "HTTP/1.1 101 Switching Protocols\r\n" |
1041 "Upgrade: websocket\r\n" | 983 "Upgrade: websocket\r\n" |
1042 "Connection: Upgrade\r\n" | 984 "Connection: Upgrade\r\n" |
1043 "\r\n"; | 985 "\r\n"; |
1044 CreateAndConnectCustomResponse("ws://localhost/", | 986 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
1045 "/", | 987 NoSubProtocols(), "http://localhost", "", |
1046 NoSubProtocols(), | |
1047 "http://localhost", | |
1048 "", | |
1049 kMissingAcceptResponse); | 988 kMissingAcceptResponse); |
1050 RunUntilIdle(); | 989 RunUntilIdle(); |
1051 EXPECT_TRUE(has_failed()); | 990 EXPECT_TRUE(has_failed()); |
1052 EXPECT_EQ("Error during WebSocket handshake: " | 991 EXPECT_EQ("Error during WebSocket handshake: " |
1053 "'Sec-WebSocket-Accept' header is missing", | 992 "'Sec-WebSocket-Accept' header is missing", |
1054 failure_message()); | 993 failure_message()); |
1055 } | 994 } |
1056 | 995 |
1057 // Sec-WebSocket-Accept header must match the key that was sent. | 996 // Sec-WebSocket-Accept header must match the key that was sent. |
1058 TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { | 997 TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { |
1059 static const char kIncorrectAcceptResponse[] = | 998 static const char kIncorrectAcceptResponse[] = |
1060 "HTTP/1.1 101 Switching Protocols\r\n" | 999 "HTTP/1.1 101 Switching Protocols\r\n" |
1061 "Upgrade: websocket\r\n" | 1000 "Upgrade: websocket\r\n" |
1062 "Connection: Upgrade\r\n" | 1001 "Connection: Upgrade\r\n" |
1063 "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" | 1002 "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" |
1064 "\r\n"; | 1003 "\r\n"; |
1065 CreateAndConnectCustomResponse("ws://localhost/", | 1004 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
1066 "/", | 1005 NoSubProtocols(), "http://localhost", "", |
1067 NoSubProtocols(), | |
1068 "http://localhost", | |
1069 "", | |
1070 kIncorrectAcceptResponse); | 1006 kIncorrectAcceptResponse); |
1071 RunUntilIdle(); | 1007 RunUntilIdle(); |
1072 EXPECT_TRUE(has_failed()); | 1008 EXPECT_TRUE(has_failed()); |
1073 EXPECT_EQ("Error during WebSocket handshake: " | 1009 EXPECT_EQ("Error during WebSocket handshake: " |
1074 "Incorrect 'Sec-WebSocket-Accept' header value", | 1010 "Incorrect 'Sec-WebSocket-Accept' header value", |
1075 failure_message()); | 1011 failure_message()); |
1076 } | 1012 } |
1077 | 1013 |
1078 // Cancellation works. | 1014 // Cancellation works. |
1079 TEST_F(WebSocketStreamCreateTest, Cancellation) { | 1015 TEST_F(WebSocketStreamCreateTest, Cancellation) { |
1080 CreateAndConnectStandard( | 1016 CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
1081 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); | 1017 NoSubProtocols(), "http://localhost", "", ""); |
1082 stream_request_.reset(); | 1018 stream_request_.reset(); |
1083 RunUntilIdle(); | 1019 RunUntilIdle(); |
1084 EXPECT_FALSE(has_failed()); | 1020 EXPECT_FALSE(has_failed()); |
1085 EXPECT_FALSE(stream_); | 1021 EXPECT_FALSE(stream_); |
1086 EXPECT_FALSE(request_info_); | 1022 EXPECT_FALSE(request_info_); |
1087 EXPECT_FALSE(response_info_); | 1023 EXPECT_FALSE(response_info_); |
1088 } | 1024 } |
1089 | 1025 |
1090 // Connect failure must look just like negotiation failure. | 1026 // Connect failure must look just like negotiation failure. |
1091 TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { | 1027 TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 EXPECT_EQ("WebSocket opening handshake timed out", failure_message()); | 1073 EXPECT_EQ("WebSocket opening handshake timed out", failure_message()); |
1138 ASSERT_TRUE(weak_timer.get()); | 1074 ASSERT_TRUE(weak_timer.get()); |
1139 EXPECT_FALSE(weak_timer->IsRunning()); | 1075 EXPECT_FALSE(weak_timer->IsRunning()); |
1140 } | 1076 } |
1141 | 1077 |
1142 // When the connection establishes the timer should be stopped. | 1078 // When the connection establishes the timer should be stopped. |
1143 TEST_F(WebSocketStreamCreateTest, HandshakeTimerOnSuccess) { | 1079 TEST_F(WebSocketStreamCreateTest, HandshakeTimerOnSuccess) { |
1144 scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); | 1080 scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); |
1145 base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); | 1081 base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); |
1146 | 1082 |
1147 CreateAndConnectStandard("ws://localhost/", | 1083 CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
1148 "/", | 1084 NoSubProtocols(), "http://localhost", "", "", |
1149 NoSubProtocols(), | |
1150 "http://localhost", | |
1151 "", | |
1152 "", | |
1153 timer.Pass()); | 1085 timer.Pass()); |
1154 ASSERT_TRUE(weak_timer); | 1086 ASSERT_TRUE(weak_timer); |
1155 EXPECT_TRUE(weak_timer->IsRunning()); | 1087 EXPECT_TRUE(weak_timer->IsRunning()); |
1156 | 1088 |
1157 RunUntilIdle(); | 1089 RunUntilIdle(); |
1158 EXPECT_FALSE(has_failed()); | 1090 EXPECT_FALSE(has_failed()); |
1159 EXPECT_TRUE(stream_); | 1091 EXPECT_TRUE(stream_); |
1160 ASSERT_TRUE(weak_timer); | 1092 ASSERT_TRUE(weak_timer); |
1161 EXPECT_FALSE(weak_timer->IsRunning()); | 1093 EXPECT_FALSE(weak_timer->IsRunning()); |
1162 } | 1094 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 stream_request_.reset(); | 1148 stream_request_.reset(); |
1217 RunUntilIdle(); | 1149 RunUntilIdle(); |
1218 EXPECT_FALSE(has_failed()); | 1150 EXPECT_FALSE(has_failed()); |
1219 EXPECT_FALSE(stream_); | 1151 EXPECT_FALSE(stream_); |
1220 EXPECT_TRUE(request_info_); | 1152 EXPECT_TRUE(request_info_); |
1221 EXPECT_FALSE(response_info_); | 1153 EXPECT_FALSE(response_info_); |
1222 } | 1154 } |
1223 | 1155 |
1224 // Cancellation during read of the response headers works. | 1156 // Cancellation during read of the response headers works. |
1225 TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { | 1157 TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { |
1226 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); | 1158 std::string request = |
| 1159 WebSocketStandardRequest("/", "localhost", "http://localhost", ""); |
1227 MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; | 1160 MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; |
1228 MockRead reads[] = { | 1161 MockRead reads[] = { |
1229 MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), | 1162 MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), |
1230 }; | 1163 }; |
1231 scoped_ptr<DeterministicSocketData> socket_data( | 1164 scoped_ptr<DeterministicSocketData> socket_data( |
1232 BuildSocketData(reads, writes)); | 1165 BuildSocketData(reads, writes)); |
1233 socket_data->SetStop(1); | 1166 socket_data->SetStop(1); |
1234 DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); | 1167 DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); |
1235 CreateAndConnectRawExpectations("ws://localhost/", | 1168 CreateAndConnectRawExpectations("ws://localhost/", |
1236 NoSubProtocols(), | 1169 NoSubProtocols(), |
(...skipping 11 matching lines...) Expand all Loading... |
1248 // Over-size response headers (> 256KB) should not cause a crash. This is a | 1181 // Over-size response headers (> 256KB) should not cause a crash. This is a |
1249 // regression test for crbug.com/339456. It is based on the layout test | 1182 // regression test for crbug.com/339456. It is based on the layout test |
1250 // "cookie-flood.html". | 1183 // "cookie-flood.html". |
1251 TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { | 1184 TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { |
1252 std::string set_cookie_headers; | 1185 std::string set_cookie_headers; |
1253 set_cookie_headers.reserve(45 * 10000); | 1186 set_cookie_headers.reserve(45 * 10000); |
1254 for (int i = 0; i < 10000; ++i) { | 1187 for (int i = 0; i < 10000; ++i) { |
1255 set_cookie_headers += | 1188 set_cookie_headers += |
1256 base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); | 1189 base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); |
1257 } | 1190 } |
1258 CreateAndConnectStandard("ws://localhost/", "/", NoSubProtocols(), | 1191 CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
1259 "http://localhost", "", set_cookie_headers); | 1192 NoSubProtocols(), "http://localhost", "", |
| 1193 set_cookie_headers); |
1260 RunUntilIdle(); | 1194 RunUntilIdle(); |
1261 EXPECT_TRUE(has_failed()); | 1195 EXPECT_TRUE(has_failed()); |
1262 EXPECT_FALSE(response_info_); | 1196 EXPECT_FALSE(response_info_); |
1263 } | 1197 } |
1264 | 1198 |
1265 // If the remote host closes the connection without sending headers, we should | 1199 // If the remote host closes the connection without sending headers, we should |
1266 // log the console message "Connection closed before receiving a handshake | 1200 // log the console message "Connection closed before receiving a handshake |
1267 // response". | 1201 // response". |
1268 TEST_F(WebSocketStreamCreateTest, NoResponse) { | 1202 TEST_F(WebSocketStreamCreateTest, NoResponse) { |
1269 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); | 1203 std::string request = |
| 1204 WebSocketStandardRequest("/", "localhost", "http://localhost", ""); |
1270 MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; | 1205 MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; |
1271 MockRead reads[] = {MockRead(ASYNC, 0, 1)}; | 1206 MockRead reads[] = {MockRead(ASYNC, 0, 1)}; |
1272 scoped_ptr<DeterministicSocketData> socket_data( | 1207 scoped_ptr<DeterministicSocketData> socket_data( |
1273 BuildSocketData(reads, writes)); | 1208 BuildSocketData(reads, writes)); |
1274 DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); | 1209 DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); |
1275 CreateAndConnectRawExpectations("ws://localhost/", | 1210 CreateAndConnectRawExpectations("ws://localhost/", |
1276 NoSubProtocols(), | 1211 NoSubProtocols(), |
1277 "http://localhost", | 1212 "http://localhost", |
1278 socket_data.Pass()); | 1213 socket_data.Pass()); |
1279 socket_data_raw_ptr->RunFor(2); | 1214 socket_data_raw_ptr->RunFor(2); |
(...skipping 27 matching lines...) Expand all Loading... |
1307 TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateSuccess) { | 1242 TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateSuccess) { |
1308 scoped_ptr<SSLSocketDataProvider> ssl_data( | 1243 scoped_ptr<SSLSocketDataProvider> ssl_data( |
1309 new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); | 1244 new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); |
1310 ssl_data->cert = | 1245 ssl_data->cert = |
1311 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); | 1246 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); |
1312 ASSERT_TRUE(ssl_data->cert.get()); | 1247 ASSERT_TRUE(ssl_data->cert.get()); |
1313 ssl_data_.push_back(ssl_data.release()); | 1248 ssl_data_.push_back(ssl_data.release()); |
1314 ssl_data.reset(new SSLSocketDataProvider(ASYNC, OK)); | 1249 ssl_data.reset(new SSLSocketDataProvider(ASYNC, OK)); |
1315 ssl_data_.push_back(ssl_data.release()); | 1250 ssl_data_.push_back(ssl_data.release()); |
1316 url_request_context_host_.AddRawExpectations(BuildNullSocketData()); | 1251 url_request_context_host_.AddRawExpectations(BuildNullSocketData()); |
1317 CreateAndConnectStandard( | 1252 CreateAndConnectStandard("wss://localhost/", "localhost", "/", |
1318 "wss://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); | 1253 NoSubProtocols(), "http://localhost", "", ""); |
1319 RunUntilIdle(); | 1254 RunUntilIdle(); |
1320 ASSERT_TRUE(ssl_error_callbacks_); | 1255 ASSERT_TRUE(ssl_error_callbacks_); |
1321 ssl_error_callbacks_->ContinueSSLRequest(); | 1256 ssl_error_callbacks_->ContinueSSLRequest(); |
1322 RunUntilIdle(); | 1257 RunUntilIdle(); |
1323 EXPECT_FALSE(has_failed()); | 1258 EXPECT_FALSE(has_failed()); |
1324 EXPECT_TRUE(stream_); | 1259 EXPECT_TRUE(stream_); |
1325 } | 1260 } |
1326 | 1261 |
1327 // If the server requests authorisation, but we have no credentials, the | 1262 // If the server requests authorisation, but we have no credentials, the |
1328 // connection should fail cleanly. | 1263 // connection should fail cleanly. |
1329 TEST_F(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) { | 1264 TEST_F(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) { |
1330 CreateAndConnectCustomResponse("ws://localhost/", | 1265 CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", |
1331 "/", | 1266 NoSubProtocols(), "http://localhost", "", |
1332 NoSubProtocols(), | |
1333 "http://localhost", | |
1334 "", | |
1335 kUnauthorizedResponse); | 1267 kUnauthorizedResponse); |
1336 RunUntilIdle(); | 1268 RunUntilIdle(); |
1337 EXPECT_TRUE(has_failed()); | 1269 EXPECT_TRUE(has_failed()); |
1338 EXPECT_EQ("HTTP Authentication failed; no valid credentials available", | 1270 EXPECT_EQ("HTTP Authentication failed; no valid credentials available", |
1339 failure_message()); | 1271 failure_message()); |
1340 EXPECT_TRUE(response_info_); | 1272 EXPECT_TRUE(response_info_); |
1341 } | 1273 } |
1342 | 1274 |
1343 TEST_F(WebSocketStreamCreateBasicAuthTest, SuccessPasswordInUrl) { | 1275 TEST_F(WebSocketStreamCreateBasicAuthTest, SuccessPasswordInUrl) { |
1344 CreateAndConnectAuthHandshake("ws://foo:bar@localhost/", | 1276 CreateAndConnectAuthHandshake("ws://foo:bar@localhost/", |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1377 ASSERT_TRUE(response_info_); | 1309 ASSERT_TRUE(response_info_); |
1378 EXPECT_EQ(101, response_info_->status_code); | 1310 EXPECT_EQ(101, response_info_->status_code); |
1379 } | 1311 } |
1380 | 1312 |
1381 TEST_F(WebSocketStreamCreateUMATest, Incomplete) { | 1313 TEST_F(WebSocketStreamCreateUMATest, Incomplete) { |
1382 const std::string name("Net.WebSocket.HandshakeResult"); | 1314 const std::string name("Net.WebSocket.HandshakeResult"); |
1383 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); | 1315 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); |
1384 | 1316 |
1385 { | 1317 { |
1386 StreamCreation creation; | 1318 StreamCreation creation; |
1387 creation.CreateAndConnectStandard("ws://localhost/", | 1319 creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
1388 "/", | |
1389 creation.NoSubProtocols(), | 1320 creation.NoSubProtocols(), |
1390 "http://localhost", | 1321 "http://localhost", "", ""); |
1391 "", | |
1392 ""); | |
1393 } | 1322 } |
1394 | 1323 |
1395 scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); | 1324 scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); |
1396 ASSERT_TRUE(samples); | 1325 ASSERT_TRUE(samples); |
1397 if (original) { | 1326 if (original) { |
1398 samples->Subtract(*original); // Cancel the original values. | 1327 samples->Subtract(*original); // Cancel the original values. |
1399 } | 1328 } |
1400 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); | 1329 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); |
1401 EXPECT_EQ(0, samples->GetCount(CONNECTED)); | 1330 EXPECT_EQ(0, samples->GetCount(CONNECTED)); |
1402 EXPECT_EQ(0, samples->GetCount(FAILED)); | 1331 EXPECT_EQ(0, samples->GetCount(FAILED)); |
1403 } | 1332 } |
1404 | 1333 |
1405 TEST_F(WebSocketStreamCreateUMATest, Connected) { | 1334 TEST_F(WebSocketStreamCreateUMATest, Connected) { |
1406 const std::string name("Net.WebSocket.HandshakeResult"); | 1335 const std::string name("Net.WebSocket.HandshakeResult"); |
1407 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); | 1336 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); |
1408 | 1337 |
1409 { | 1338 { |
1410 StreamCreation creation; | 1339 StreamCreation creation; |
1411 creation.CreateAndConnectStandard("ws://localhost/", | 1340 creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/", |
1412 "/", | |
1413 creation.NoSubProtocols(), | 1341 creation.NoSubProtocols(), |
1414 "http://localhost", | 1342 "http://localhost", "", ""); |
1415 "", | |
1416 ""); | |
1417 creation.RunUntilIdle(); | 1343 creation.RunUntilIdle(); |
1418 } | 1344 } |
1419 | 1345 |
1420 scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); | 1346 scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); |
1421 ASSERT_TRUE(samples); | 1347 ASSERT_TRUE(samples); |
1422 if (original) { | 1348 if (original) { |
1423 samples->Subtract(*original); // Cancel the original values. | 1349 samples->Subtract(*original); // Cancel the original values. |
1424 } | 1350 } |
1425 EXPECT_EQ(0, samples->GetCount(INCOMPLETE)); | 1351 EXPECT_EQ(0, samples->GetCount(INCOMPLETE)); |
1426 EXPECT_EQ(1, samples->GetCount(CONNECTED)); | 1352 EXPECT_EQ(1, samples->GetCount(CONNECTED)); |
1427 EXPECT_EQ(0, samples->GetCount(FAILED)); | 1353 EXPECT_EQ(0, samples->GetCount(FAILED)); |
1428 } | 1354 } |
1429 | 1355 |
1430 TEST_F(WebSocketStreamCreateUMATest, Failed) { | 1356 TEST_F(WebSocketStreamCreateUMATest, Failed) { |
1431 const std::string name("Net.WebSocket.HandshakeResult"); | 1357 const std::string name("Net.WebSocket.HandshakeResult"); |
1432 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); | 1358 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); |
1433 | 1359 |
1434 { | 1360 { |
1435 StreamCreation creation; | 1361 StreamCreation creation; |
1436 static const char kInvalidStatusCodeResponse[] = | 1362 static const char kInvalidStatusCodeResponse[] = |
1437 "HTTP/1.1 200 OK\r\n" | 1363 "HTTP/1.1 200 OK\r\n" |
1438 "Upgrade: websocket\r\n" | 1364 "Upgrade: websocket\r\n" |
1439 "Connection: Upgrade\r\n" | 1365 "Connection: Upgrade\r\n" |
1440 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 1366 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
1441 "\r\n"; | 1367 "\r\n"; |
1442 creation.CreateAndConnectCustomResponse("ws://localhost/", | 1368 creation.CreateAndConnectCustomResponse( |
1443 "/", | 1369 "ws://localhost/", "localhost", "/", creation.NoSubProtocols(), |
1444 creation.NoSubProtocols(), | 1370 "http://localhost", "", kInvalidStatusCodeResponse); |
1445 "http://localhost", | |
1446 "", | |
1447 kInvalidStatusCodeResponse); | |
1448 creation.RunUntilIdle(); | 1371 creation.RunUntilIdle(); |
1449 } | 1372 } |
1450 | 1373 |
1451 scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); | 1374 scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); |
1452 ASSERT_TRUE(samples); | 1375 ASSERT_TRUE(samples); |
1453 if (original) { | 1376 if (original) { |
1454 samples->Subtract(*original); // Cancel the original values. | 1377 samples->Subtract(*original); // Cancel the original values. |
1455 } | 1378 } |
1456 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); | 1379 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); |
1457 EXPECT_EQ(0, samples->GetCount(CONNECTED)); | 1380 EXPECT_EQ(0, samples->GetCount(CONNECTED)); |
1458 EXPECT_EQ(0, samples->GetCount(FAILED)); | 1381 EXPECT_EQ(0, samples->GetCount(FAILED)); |
1459 } | 1382 } |
1460 | 1383 |
1461 } // namespace | 1384 } // namespace |
1462 } // namespace net | 1385 } // namespace net |
OLD | NEW |