1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_stream.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm> 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utility> 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <vector> 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/compiler_specific.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_vector.h" 14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/histogram.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/histogram_samples.h" 16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/statistics_recorder.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/timer/mock_timer.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/timer/timer.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/net_errors.h" 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/base/test_data_directory.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_request_headers.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_response_headers.h" 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/socket_test_util.h" 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/test/cert_test_util.h" 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_request_test_util.h" 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_basic_handshake_stream.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_frame.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_request_info.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_response_info.h" 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_handshake_stream_create_helper.h" 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_test_util.h" 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h" 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/origin.h" 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace net { 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef std::pair<std::string, std::string> HeaderKeyValuePair; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<HeaderKeyValuePair> ToVector(const HttpRequestHeaders& headers) { 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HttpRequestHeaders::Iterator it(headers); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> result; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (it.GetNext()) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.push_back(HeaderKeyValuePair(it.name(), it.value())); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<HeaderKeyValuePair> ToVector(const HttpResponseHeaders& headers) { 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* iter = NULL; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string name, value; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> result; 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (headers.EnumerateHeaderLines(&iter, &name, &value)) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.push_back(HeaderKeyValuePair(name, value)); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simple builder for a DeterministicSocketData object to save repetitive code. 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// It always sets the connect data to MockConnect(SYNCHRONOUS, OK), so it cannot 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// be used in tests where the connect fails. In practice, those tests never have 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// any read/write data and so can't benefit from it anyway. The arrays are not 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// copied. It is up to the caller to ensure they stay in scope until the test 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// ends. 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <size_t reads_count, size_t writes_count> 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<DeterministicSocketData> BuildSocketData( 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockRead (&reads)[reads_count], 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockWrite (&writes)[writes_count]) { 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new DeterministicSocketData(reads, reads_count, writes, writes_count)); 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_data->SetStop(reads_count + writes_count); 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return socket_data.Pass(); 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Builder for a DeterministicSocketData that expects nothing. This does not 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// set the connect data, so the calling code must do that explicitly. 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<DeterministicSocketData> BuildNullSocketData() { 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return make_scoped_ptr(new DeterministicSocketData(NULL, 0, NULL, 0)); 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MockWeakTimer : public base::MockTimer, 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public base::SupportsWeakPtr<MockWeakTimer> { 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MockWeakTimer(bool retain_user_task, bool is_repeating) 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : MockTimer(retain_user_task, is_repeating) {} 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// deterministic key to use in the WebSocket handshake. 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class DeterministicKeyWebSocketHandshakeStreamCreateHelper 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : public WebSocketHandshakeStreamCreateHelper { 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicKeyWebSocketHandshakeStreamCreateHelper( 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* connect_delegate, 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& requested_subprotocols) 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : WebSocketHandshakeStreamCreateHelper(connect_delegate, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requested_subprotocols) {} 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnStreamCreated(WebSocketBasicHandshakeStream* stream) OVERRIDE { 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class WebSocketStreamCreateTest : public ::testing::Test { 108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public: 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {} 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectCustomResponse( 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& response_body, 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.SetExpectations( 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardRequest(socket_path, origin, extra_request_headers), 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) response_body); 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass()); 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // errors like "Unable to perform synchronous IO while stopped" will occur. 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectStandard(const std::string& socket_url, 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extra_response_headers, 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<base::Timer> timer = 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<base::Timer>()) { 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse( 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_url, 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_path, 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) origin, 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) extra_request_headers, 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WebSocketStandardResponse(extra_response_headers), 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timer.Pass()); 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectRawExpectations( 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<DeterministicSocketData> socket_data, 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) { 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRawExpectations(socket_data.Pass()); 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass()); 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Add additional raw expectations for sockets created before the final one. 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data) { 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_request_context_host_.AddRawExpectations(socket_data.Pass()); 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A wrapper for CreateAndConnectStreamForTesting that knows about our default 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // parameters. 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectStream(const std::string& socket_url, 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& origin, 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<base::Timer> timer) { 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (size_t i = 0; i < ssl_data_.size(); ++i) { 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]); 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data_[i] = NULL; 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_request_context_host_.AddSSLSocketDataProvider(ssl_data.Pass()); 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data_.clear(); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate( 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new TestConnectDelegate(this)); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* delegate = connect_delegate.get(); 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper( 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new DeterministicKeyWebSocketHandshakeStreamCreateHelper( 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch delegate, sub_protocols)); 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_ = ::net::CreateAndConnectStreamForTesting( 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GURL(socket_url), 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch create_helper.Pass(), 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url::Origin(origin), 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.GetURLRequestContext(), 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BoundNetLog(), 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connect_delegate.Pass(), 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timer ? timer.Pass() : scoped_ptr<base::Timer>( 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new base::Timer(false, false))); 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A simple function to make the tests more readable. Creates an empty vector. 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static std::vector<std::string> NoSubProtocols() { 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return std::vector<std::string>(); 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& failure_message() const { return failure_message_; } 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_failed() const { return has_failed_; } 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) class TestConnectDelegate : public WebSocketStream::ConnectDelegate { 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit TestConnectDelegate(WebSocketStreamCreateTest* owner) 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : owner_(owner) {} 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void OnSuccess(scoped_ptr<WebSocketStream> stream) OVERRIDE { 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream.swap(owner_->stream_); 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnFailure(const std::string& message) OVERRIDE { 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->has_failed_ = true; 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->failure_message_ = message; 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnStartOpeningHandshake( 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Can be called multiple times (in the case of HTTP auth). Last call 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // wins. 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->request_info_ = request.Pass(); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnFinishOpeningHandshake( 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (owner_->response_info_) 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ADD_FAILURE(); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->response_info_ = response.Pass(); 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual void OnSSLCertificateError( 22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> 22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_error_callbacks, 22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const SSLInfo& ssl_info, 22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool fatal) OVERRIDE { 23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) owner_->ssl_error_callbacks_ = ssl_error_callbacks.Pass(); 23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) owner_->ssl_info_ = ssl_info; 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) owner_->ssl_fatal_ = fatal; 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStreamCreateTest* owner_; 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketTestURLRequestContextHost url_request_context_host_; 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStreamRequest> stream_request_; 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only set if the connection succeeded. 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStream> stream_; 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only set if the connection failed. 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string failure_message_; 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_failed_; 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request_info_; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response_info_; 24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> ssl_error_callbacks_; 24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SSLInfo ssl_info_; 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool ssl_fatal_; 25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ScopedVector<SSLSocketDataProvider> ssl_data_; 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// There are enough tests of the Sec-WebSocket-Extensions header that they 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// deserve their own test fixture. 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class WebSocketStreamCreateExtensionTest : public WebSocketStreamCreateTest { 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Performs a standard connect, with the value of the Sec-WebSocket-Extensions 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // header in the response set to |extensions_header_value|. Runs the event 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // loop to allow the connect to complete. 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void CreateAndConnectWithExtensions( 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extensions_header_value) { 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectStandard( 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/testing_path", 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/testing_path", 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Common code to construct expectations for authentication tests that receive 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the auth challenge on one connection and then create a second connection to 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// send the authenticated request on. 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CommonAuthTestHelper { 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CommonAuthTestHelper() : reads1_(), writes1_(), reads2_(), writes2_() {} 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> BuildSocketData1( 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& response) { 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) request1_ = WebSocketStandardRequest("/", "http://localhost", ""); 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) writes1_[0] = MockWrite(SYNCHRONOUS, 0, request1_.c_str()); 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) response1_ = response; 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reads1_[0] = MockRead(SYNCHRONOUS, 1, response1_.c_str()); 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reads1_[1] = MockRead(SYNCHRONOUS, OK, 2); // Close connection 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BuildSocketData(reads1_, writes1_); 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> BuildSocketData2( 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& request, 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& response) { 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) request2_ = request; 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) response2_ = response; 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) writes2_[0] = MockWrite(SYNCHRONOUS, 0, request2_.c_str()); 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reads2_[0] = MockRead(SYNCHRONOUS, 1, response2_.c_str()); 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BuildSocketData(reads2_, writes2_); 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // These need to be object-scoped since they have to remain valid until all 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // socket operations in the test are complete. 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string request1_; 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string request2_; 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string response1_; 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string response2_; 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockRead reads1_[2]; 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockWrite writes1_[1]; 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockRead reads2_[1]; 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockWrite writes2_[1]; 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CommonAuthTestHelper); 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Data and methods for BasicAuth tests. 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WebSocketStreamCreateBasicAuthTest : public WebSocketStreamCreateTest { 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected: 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void CreateAndConnectAuthHandshake(const std::string& url, 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& base64_user_pass, 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& response2) { 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRawExpectations(helper_.BuildSocketData1(kUnauthorizedResponse)); 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static const char request2format[] = 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "GET / HTTP/1.1\r\n" 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Host: localhost\r\n" 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Connection: Upgrade\r\n" 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Pragma: no-cache\r\n" 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Cache-Control: no-cache\r\n" 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Authorization: Basic %s\r\n" 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Upgrade: websocket\r\n" 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Origin: http://localhost\r\n" 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Sec-WebSocket-Version: 13\r\n" 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "User-Agent:\r\n" 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Accept-Encoding: gzip, deflate\r\n" 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Accept-Language: en-us,fr\r\n" 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Sec-WebSocket-Extensions: permessage-deflate; " 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "client_max_window_bits\r\n" 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "\r\n"; 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string request = 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::StringPrintf(request2format, base64_user_pass.c_str()); 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateAndConnectRawExpectations( 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url, 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NoSubProtocols(), 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "http://localhost", 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) helper_.BuildSocketData2(request, response2)); 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static const char kUnauthorizedResponse[]; 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CommonAuthTestHelper helper_; 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WebSocketStreamCreateDigestAuthTest : public WebSocketStreamCreateTest { 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected: 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static const char kUnauthorizedResponse[]; 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static const char kAuthorizedRequest[]; 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CommonAuthTestHelper helper_; 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char WebSocketStreamCreateBasicAuthTest::kUnauthorizedResponse[] = 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "HTTP/1.1 401 Unauthorized\r\n" 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Content-Length: 0\r\n" 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "WWW-Authenticate: Basic realm=\"camelot\"\r\n" 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "\r\n"; 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// These negotiation values are borrowed from 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// http_auth_handler_digest_unittest.cc. Feel free to come up with new ones if 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// you are bored. Only the weakest (no qop) variants of Digest authentication 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// can be tested by this method, because the others involve random input. 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char WebSocketStreamCreateDigestAuthTest::kUnauthorizedResponse[] = 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "HTTP/1.1 401 Unauthorized\r\n" 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Content-Length: 0\r\n" 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "WWW-Authenticate: Digest realm=\"Oblivion\", nonce=\"nonce-value\"\r\n" 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "\r\n"; 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char WebSocketStreamCreateDigestAuthTest::kAuthorizedRequest[] = 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "GET / HTTP/1.1\r\n" 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Host: localhost\r\n" 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Connection: Upgrade\r\n" 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Pragma: no-cache\r\n" 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Cache-Control: no-cache\r\n" 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Authorization: Digest username=\"FooBar\", realm=\"Oblivion\", " 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "nonce=\"nonce-value\", uri=\"/\", " 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "response=\"f72ff54ebde2f928860f806ec04acd1b\"\r\n" 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Upgrade: websocket\r\n" 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Origin: http://localhost\r\n" 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Sec-WebSocket-Version: 13\r\n" 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "User-Agent:\r\n" 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Accept-Encoding: gzip, deflate\r\n" 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Accept-Language: en-us,fr\r\n" 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Sec-WebSocket-Extensions: permessage-deflate; " 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "client_max_window_bits\r\n" 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "\r\n"; 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass WebSocketStreamCreateUMATest : public ::testing::Test { 401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public: 402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // This enum should match with the enum in Delegate in websocket_stream.cc. 403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch enum HandshakeResult { 404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch INCOMPLETE, 405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CONNECTED, 406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FAILED, 407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NUM_HANDSHAKE_RESULT_TYPES, 408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch class StreamCreation : public WebSocketStreamCreateTest { 411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch virtual void TestBody() OVERRIDE {} 412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 414c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> GetSamples(const std::string& name) { 415c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::HistogramBase* histogram = 416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::StatisticsRecorder::FindHistogram(name); 417c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return histogram ? histogram->SnapshotSamples() 418c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : scoped_ptr<base::HistogramSamples>(); 419c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}; 421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the basic case works as expected. 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(response_info_); 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kResponse[] = 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: websocket\r\n" 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: Upgrade\r\n" 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "foo: bar, baz\r\n" 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "hoge: fuga\r\n" 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "hoge: piyo\r\n" 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse( 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/", 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kResponse); 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(request_info_); 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(response_info_); 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> request_headers = 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ToVector(request_info_->headers); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We examine the contents of request_info_ and response_info_ 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // mainly only in this test case. 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(GURL("ws://localhost/"), request_info_->url); 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(GURL("ws://localhost/"), response_info_->url); 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(101, response_info_->status_code); 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Switching Protocols", response_info_->status_text); 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(12u, request_headers.size()); 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]); 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]); 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Pragma", "no-cache"), request_headers[2]); 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Cache-Control", "no-cache"), 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[3]); 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[4]); 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost"), 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[5]); 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"), 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[6]); 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[7]); 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip, deflate"), 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[8]); 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"), 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[9]); 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Sec-WebSocket-Key", request_headers[10].first); 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions", 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits"), 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[11]); 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> response_headers = 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ToVector(*response_info_->headers.get()); 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(6u, response_headers.size()); 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sort the headers for ease of verification. 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::sort(response_headers.begin(), response_headers.end()); 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]); 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); 500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the stream isn't established until the message loop runs. 503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { 504a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check the path is used. 511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, PathIsUsed) { 512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check that the origin is used. 524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check that sub-protocols are sent and parsed. 537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { 538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n", 547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); 548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); 552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Unsolicited sub-protocols are rejected. 555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { 556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 557a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 558a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 561a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); 562a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Response must not include 'Sec-WebSocket-Protocol' header " 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "if not present in request: chatv20.chromium.org", 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 569a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 570a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 571a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Missing sub-protocol response is rejected. 572a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> sub_protocols; 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chat.example.com"); 575a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 576a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols, 578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 579a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chat.example.com\r\n", 580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 581a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 582a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sent non-empty 'Sec-WebSocket-Protocol' header " 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "but no response was received", 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 588a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 589a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Only one sub-protocol can be accepted. 591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { 592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 598a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n", 601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n"); 603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Protocol' header must not appear " 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "more than once in a response", 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 610a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 611a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Unmatched sub-protocol should be rejected. 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> sub_protocols; 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 617a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols, 620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "chatv20.chromium.org\r\n", 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "in response does not match any of sent values", 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate extension basic success case. 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateSuccess) { 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("permessage-deflate"); 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate extensions success with all parameters. 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateParamsSuccess) { 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover; " 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "server_max_window_bits=11; client_max_window_bits=13; " 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "server_no_context_takeover"); 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify that incoming messages are actually decompressed with 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate enabled. 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse( 6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/testing_path", 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/testing_path", 6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStandardResponse( 6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Extensions: permessage-deflate\r\n") + 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string( 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed 6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9)); 665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(stream_); 6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<WebSocketFrame> frames; 6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CompletionCallback callback; 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(OK, stream_->ReadFrames(&frames, callback)); 6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(1U, frames.size()); 6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(5U, frames[0]->header.payload_length); 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Hello", std::string(frames[0]->data->data(), 5)); 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Unknown extension in the response is rejected 6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, UnknownExtension) { 6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("x-unknown-extension"); 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Found an unsupported extension 'x-unknown-extension' " 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "in 'Sec-WebSocket-Extensions' header", 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Malformed extensions are rejected (this file does not cover all possible 6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// parse failures, as the parser is covered thoroughly by its own unit tests). 6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MalformedExtension) { 6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions(";"); 6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Error during WebSocket handshake: 'Sec-WebSocket-Extensions' header " 6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "value is rejected by the parser: ;", 6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The permessage-deflate extension may only be specified once. 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, OnlyOnePerMessageDeflateAllowed) { 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate, permessage-deflate; client_max_window_bits=10"); 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 706a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: " 707a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received duplicate permessage-deflate response", 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters may not be duplicated. 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, NoDuplicateParameters) { 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover; " 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "client_no_context_takeover"); 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 719a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received duplicate permessage-deflate extension parameter " 721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "client_no_context_takeover", 7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters must start with "client_" or "server_" 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterPrefix) { 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; absurd_no_context_takeover"); 729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 732a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 733a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received an unexpected permessage-deflate extension parameter", 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters must be either *_no_context_takeover or 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterSuffix) { 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_content_bits=5"); 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 745a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 746a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received an unexpected permessage-deflate extension parameter", 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_no_context_takeover parameters must not have an argument 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterValue) { 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover=true"); 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 757a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 758a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_no_context_takeover parameter", 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must have an argument 7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, NoMaxWindowBitsArgument) { 7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("permessage-deflate; client_max_window_bits"); 7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "client_max_window_bits must have value", 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be an integer 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueInteger) { 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=banana"); 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be >= 8 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooSmall) { 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=7"); 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 792a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 793a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be <= 15 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooBig) { 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits=16"); 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 804a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 805a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_max_window_bits parameter", 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must not start with 0 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithZero) { 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits=08"); 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_max_window_bits parameter", 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must not start with + 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithPlus) { 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=+9"); 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 828a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 829a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(ricea): Check that WebSocketDeflateStream is initialised with the 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// arguments from the server. This is difficult because the data written to the 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// socket is randomly masked. 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Additional Sec-WebSocket-Accept headers should be rejected. 838a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, DoubleAccept) { 839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 840a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "ws://localhost/", 841a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 842a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); 846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 847a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Accept' header must not appear " 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "more than once in a response", 8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Response code 200 must be rejected. 856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { 857a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kInvalidStatusCodeResponse[] = 858a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 200 OK\r\n" 859a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 861a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 862a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 863a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 864a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 865a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 866a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 867a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 868a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidStatusCodeResponse); 869a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", 8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 873a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Redirects are not followed (according to the WHATWG WebSocket API, which 876a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// overrides RFC6455 for browser applications). 877a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { 878a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kRedirectResponse[] = 879a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 302 Moved Temporarily\r\n" 880a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Content-Type: text/html\r\n" 881a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Content-Length: 34\r\n" 882a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: keep-alive\r\n" 883a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Location: ws://localhost/other\r\n" 884a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n" 885a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "<title>Moved</title><h1>Moved</h1>"; 886a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 888a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 889a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 890a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 891a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kRedirectResponse); 892a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", 8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 896a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 897a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 898a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Malformed responses should be rejected. HttpStreamParser will accept just 899a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// about any garbage in the middle of the headers. To make it give up, the junk 900a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// has to be at the start of the response. Even then, it just gets treated as an 901a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// HTTP/0.9 response. 902a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MalformedResponse) { 903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMalformedResponse[] = 904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "220 mx.google.com ESMTP\r\n" 905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 OK\r\n" 906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 910a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 911a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 912a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 914a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMalformedResponse); 916a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 918a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Invalid status line", 9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 920a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 921a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 922a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Upgrade header must be present. 923a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { 924a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingUpgradeResponse[] = 925a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 926a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 927a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 928a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 929a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 930a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 931a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 932a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 933a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 934a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingUpgradeResponse); 935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 939a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 940a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 941a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// There must only be one upgrade header. 942a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { 943a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 944a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "ws://localhost/", 945a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 946a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 947a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", "Upgrade: HTTP/2.0\r\n"); 949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Upgrade' header must not appear more than once in a response", 9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 9545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// There must only be one correct upgrade header. 9575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { 9585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kMissingUpgradeResponse[] = 9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 9605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: Upgrade\r\n" 9615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: hogefuga\r\n" 9635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 967a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMissingUpgradeResponse); 9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 9715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Upgrade' header value is not 'WebSocket': hogefuga", 9745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 975a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 976a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 977a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connection header must be present. 978a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { 979a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingConnectionResponse[] = 980a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 981a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 982a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 984a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 985a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 986a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 987a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 988a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 989a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingConnectionResponse); 990a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Connection' header is missing", 9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Connection header must contain "Upgrade". 9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { 9995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kMissingConnectionResponse[] = 10005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: websocket\r\n" 10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: hogefuga\r\n" 10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 1008a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMissingConnectionResponse); 10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Connection' header value must contain 'Upgrade'", 10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1017a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1018a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connection header is permitted to contain other tokens. 1019a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { 1020a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kAdditionalConnectionTokenResponse[] = 1021a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 1022a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 1023a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade, Keep-Alive\r\n" 1024a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 1025a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 1026a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 1027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 1029a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kAdditionalConnectionTokenResponse); 1032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 10335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 1035a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1037a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sec-WebSocket-Accept header must be present. 1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { 1039a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingAcceptResponse[] = 1040a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 1041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 1044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 1045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 1046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 1047a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 1049a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingAcceptResponse); 1050a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 10515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 10525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 10535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Accept' header is missing", 10545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1055a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1056a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1057a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sec-WebSocket-Accept header must match the key that was sent. 1058a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { 1059a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kIncorrectAcceptResponse[] = 1060a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 1061a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 1062a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 1063a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" 1064a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 1065a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 1066a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 1067a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 1068a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 1069a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 1070a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kIncorrectAcceptResponse); 1071a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 10725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 10735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 10745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Incorrect 'Sec-WebSocket-Accept' header value", 10755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1076a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1077a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1078a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation works. 1079a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, Cancellation) { 1080a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 1081a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 1082a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 1083a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 10845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 1085a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 10865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 10875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 1088a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1089a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1090a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connect failure must look just like negotiation failure. 1091a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { 10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); 1093a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data( 1094a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); 1095a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 1096a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", socket_data.Pass()); 1097a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 10985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 10995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", 11005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 11015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 11025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connect timeout must look just like any other failure. 1106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { 11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); 1108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data( 1109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); 1110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 1111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", socket_data.Pass()); 1112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 11135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 11145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", 11155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 11181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The server doesn't respond to the opening handshake. 11191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(WebSocketStreamCreateTest, HandshakeTimeout) { 11201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); 11211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); 11221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); 11231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); 11241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 11251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "http://localhost", socket_data.Pass(), 11261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timer.PassAs<base::Timer>()); 11271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(has_failed()); 11281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(weak_timer.get()); 11291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(weak_timer->IsRunning()); 11301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_timer->Fire(); 11321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RunUntilIdle(); 11331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(has_failed()); 11351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ("WebSocket opening handshake timed out", failure_message()); 11361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(weak_timer.get()); 11371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(weak_timer->IsRunning()); 11381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 11391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// When the connection establishes the timer should be stopped. 11411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(WebSocketStreamCreateTest, HandshakeTimerOnSuccess) { 11421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); 11431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); 11441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateAndConnectStandard( 11461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", "", 11471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timer.PassAs<base::Timer>()); 11481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(weak_timer); 11491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(weak_timer->IsRunning()); 11501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RunUntilIdle(); 11521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(has_failed()); 11531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(stream_); 11541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(weak_timer); 11551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(weak_timer->IsRunning()); 11561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 11571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// When the connection fails the timer should be stopped. 11591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(WebSocketStreamCreateTest, HandshakeTimerOnFailure) { 11601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); 11611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_data->set_connect_data( 11621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); 11631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); 11641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); 11651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 11661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "http://localhost", socket_data.Pass(), 11671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timer.PassAs<base::Timer>()); 11681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(weak_timer.get()); 11691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(weak_timer->IsRunning()); 11701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RunUntilIdle(); 11721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(has_failed()); 11731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", 11741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci failure_message()); 11751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(weak_timer.get()); 11761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(weak_timer->IsRunning()); 11771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 11781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during connect works. 1180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { 11815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); 1182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); 1183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 1184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 1185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 1186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data.Pass()); 1187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 1188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 1190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 1191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during write of the request headers works. 1194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringWrite) { 1195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We seem to need at least two operations in order to use SetStop(). 1196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, 0, "GET / HTTP/"), 1197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite(ASYNC, 1, "1.1\r\n")}; 1198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We keep a copy of the pointer so that we can call RunFor() on it later. 1199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicSocketData* socket_data( 1200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, writes, arraysize(writes))); 1201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 1202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->SetStop(1); 1203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 1204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 1205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 1206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) make_scoped_ptr(socket_data)); 1207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->Run(); 1208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 1209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 1211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 12135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 1214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during read of the response headers works. 1217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { 1218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string request = WebSocketStandardRequest("/", "http://localhost", ""); 1219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; 1220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockRead reads[] = { 1221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), 1222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 12235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 12245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BuildSocketData(reads, writes)); 1225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->SetStop(1); 12265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); 1227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 1228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 1229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 12305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_data.Pass()); 12315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_data_raw_ptr->Run(); 1232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 1233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 12345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 12355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Over-size response headers (> 256KB) should not cause a crash. This is a 12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// regression test for crbug.com/339456. It is based on the layout test 12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// "cookie-flood.html". 12435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { 12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string set_cookie_headers; 12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_cookie_headers.reserve(45 * 10000); 12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < 10000; ++i) { 12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_cookie_headers += 12485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); 12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 12505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/", "/", NoSubProtocols(), 1251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", "", set_cookie_headers); 12525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If the remote host closes the connection without sending headers, we should 12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// log the console message "Connection closed before receiving a handshake 12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// response". 12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, NoResponse) { 1261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string request = WebSocketStandardRequest("/", "http://localhost", ""); 12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; 12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockRead reads[] = {MockRead(ASYNC, 0, 1)}; 12645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 12655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BuildSocketData(reads, writes)); 12665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); 12675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 12685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 1269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 12705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_data.Pass()); 12715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_data_raw_ptr->RunFor(2); 12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 1273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 12745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 12755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Connection closed before receiving a handshake response", 12765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 127946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateFailure) { 128046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data_.push_back( 128146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); 128246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data_[0]->cert = 128346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); 12841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(ssl_data_[0]->cert.get()); 12855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<DeterministicSocketData> raw_socket_data(BuildNullSocketData()); 128646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateAndConnectRawExpectations("wss://localhost/", 128746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NoSubProtocols(), 128846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "http://localhost", 128946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) raw_socket_data.Pass()); 129046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RunUntilIdle(); 129146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_FALSE(has_failed()); 129246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_TRUE(ssl_error_callbacks_); 129346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_error_callbacks_->CancelSSLRequest(ERR_CERT_AUTHORITY_INVALID, 129446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &ssl_info_); 129546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RunUntilIdle(); 129646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(has_failed()); 129746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 129846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 129946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateSuccess) { 130046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SSLSocketDataProvider> ssl_data( 130146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); 130246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data->cert = 130346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); 13041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(ssl_data->cert.get()); 130546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data_.push_back(ssl_data.release()); 130646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data.reset(new SSLSocketDataProvider(ASYNC, OK)); 130746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_data_.push_back(ssl_data.release()); 13085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_request_context_host_.AddRawExpectations(BuildNullSocketData()); 130946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateAndConnectStandard( 131046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "wss://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 131146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RunUntilIdle(); 131246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_TRUE(ssl_error_callbacks_); 131346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_error_callbacks_->ContinueSSLRequest(); 131446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RunUntilIdle(); 131546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_FALSE(has_failed()); 131646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(stream_); 131746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 131846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 13195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// If the server requests authorisation, but we have no credentials, the 13205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// connection should fail cleanly. 13215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) { 13225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 13235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "/", 13245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NoSubProtocols(), 13255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "http://localhost", 13265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "", 13275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kUnauthorizedResponse); 13285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RunUntilIdle(); 13295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(has_failed()); 13305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ("HTTP Authentication failed; no valid credentials available", 13315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) failure_message()); 13325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(response_info_); 13335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 13345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(WebSocketStreamCreateBasicAuthTest, SuccessPasswordInUrl) { 13365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateAndConnectAuthHandshake("ws://foo:bar@localhost/", 13375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Zm9vOmJhcg==", 13385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebSocketStandardResponse(std::string())); 13395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RunUntilIdle(); 13405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_FALSE(has_failed()); 13415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(stream_); 13425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_TRUE(response_info_); 13435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(101, response_info_->status_code); 13445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 13455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(WebSocketStreamCreateBasicAuthTest, FailureIncorrectPasswordInUrl) { 13475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateAndConnectAuthHandshake( 13485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "ws://foo:baz@localhost/", "Zm9vOmJheg==", kUnauthorizedResponse); 13495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RunUntilIdle(); 13505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(has_failed()); 13515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(response_info_); 13525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 13535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Digest auth has the same connection semantics as Basic auth, so we can 13555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// generally assume that whatever works for Basic auth will also work for 13565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Digest. There's just one test here, to confirm that it works at all. 13575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(WebSocketStreamCreateDigestAuthTest, DigestPasswordInUrl) { 13585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRawExpectations(helper_.BuildSocketData1(kUnauthorizedResponse)); 13595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateAndConnectRawExpectations( 13615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "ws://FooBar:pass@localhost/", 13625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NoSubProtocols(), 13635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "http://localhost", 13645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) helper_.BuildSocketData2(kAuthorizedRequest, 13655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebSocketStandardResponse(std::string()))); 13665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RunUntilIdle(); 13675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_FALSE(has_failed()); 13685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(stream_); 13695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_TRUE(response_info_); 13705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(101, response_info_->status_code); 13715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 13725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketStreamCreateUMATest, Incomplete) { 1374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string name("Net.WebSocket.HandshakeResult"); 1375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> original(GetSamples(name)); 1376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 1378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StreamCreation creation; 1379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.CreateAndConnectStandard("ws://localhost/", 1380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "/", 1381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.NoSubProtocols(), 1382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "http://localhost", 1383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "", 1384c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ""); 1385c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1386c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1387c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); 1388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_TRUE(samples); 1389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (original) { 1390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch samples->Subtract(*original); // Cancel the original values. 1391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); 1393c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(CONNECTED)); 1394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(FAILED)); 1395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 1396c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketStreamCreateUMATest, Connected) { 1398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string name("Net.WebSocket.HandshakeResult"); 1399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> original(GetSamples(name)); 1400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 1402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StreamCreation creation; 1403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.CreateAndConnectStandard("ws://localhost/", 1404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "/", 1405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.NoSubProtocols(), 1406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "http://localhost", 1407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "", 1408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ""); 1409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.RunUntilIdle(); 1410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); 1413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_TRUE(samples); 1414c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (original) { 1415c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch samples->Subtract(*original); // Cancel the original values. 1416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1417c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(INCOMPLETE)); 1418c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(1, samples->GetCount(CONNECTED)); 1419c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(FAILED)); 1420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 1421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1422c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketStreamCreateUMATest, Failed) { 1423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string name("Net.WebSocket.HandshakeResult"); 1424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> original(GetSamples(name)); 1425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1426c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 1427c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StreamCreation creation; 1428c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch static const char kInvalidStatusCodeResponse[] = 1429c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "HTTP/1.1 200 OK\r\n" 1430c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Upgrade: websocket\r\n" 1431c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Connection: Upgrade\r\n" 1432c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 1433c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "\r\n"; 1434c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.CreateAndConnectCustomResponse("ws://localhost/", 1435c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "/", 1436c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.NoSubProtocols(), 1437c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "http://localhost", 1438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "", 1439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kInvalidStatusCodeResponse); 1440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.RunUntilIdle(); 1441c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1442c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); 1444c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_TRUE(samples); 1445c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (original) { 1446c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch samples->Subtract(*original); // Cancel the original values. 1447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 144846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); 1449c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(CONNECTED)); 145046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(0, samples->GetCount(FAILED)); 1451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 1452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 1454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace net 1455