|  | // Copyright 2015 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/websockets/websocket_stream_create_test_base.h" | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/callback.h" | 
|  | #include "base/macros.h" | 
|  | #include "net/http/http_request_headers.h" | 
|  | #include "net/http/http_response_headers.h" | 
|  | #include "net/log/net_log_with_source.h" | 
|  | #include "net/websockets/websocket_basic_handshake_stream.h" | 
|  | #include "net/websockets/websocket_handshake_request_info.h" | 
|  | #include "net/websockets/websocket_handshake_response_info.h" | 
|  | #include "net/websockets/websocket_handshake_stream_create_helper.h" | 
|  | #include "net/websockets/websocket_stream.h" | 
|  | #include "url/gurl.h" | 
|  | #include "url/origin.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | using HeaderKeyValuePair = WebSocketStreamCreateTestBase::HeaderKeyValuePair; | 
|  |  | 
|  | // A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a | 
|  | // deterministic key to use in the WebSocket handshake. | 
|  | class DeterministicKeyWebSocketHandshakeStreamCreateHelper | 
|  | : public WebSocketHandshakeStreamCreateHelper { | 
|  | public: | 
|  | DeterministicKeyWebSocketHandshakeStreamCreateHelper( | 
|  | WebSocketStream::ConnectDelegate* connect_delegate, | 
|  | const std::vector<std::string>& requested_subprotocols) | 
|  | : WebSocketHandshakeStreamCreateHelper(connect_delegate, | 
|  | requested_subprotocols) {} | 
|  |  | 
|  | void OnBasicStreamCreated(WebSocketBasicHandshakeStream* stream) override { | 
|  | stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); | 
|  | } | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN( | 
|  | DeterministicKeyWebSocketHandshakeStreamCreateHelper); | 
|  | }; | 
|  |  | 
|  | class WebSocketStreamCreateTestBase::TestConnectDelegate | 
|  | : public WebSocketStream::ConnectDelegate { | 
|  | public: | 
|  | TestConnectDelegate(WebSocketStreamCreateTestBase* owner, | 
|  | const base::Closure& done_callback) | 
|  | : owner_(owner), done_callback_(done_callback) {} | 
|  |  | 
|  | void OnCreateRequest(URLRequest* request) override { | 
|  | owner_->url_request_ = request; | 
|  | } | 
|  |  | 
|  | void OnSuccess(std::unique_ptr<WebSocketStream> stream) override { | 
|  | stream.swap(owner_->stream_); | 
|  | done_callback_.Run(); | 
|  | } | 
|  |  | 
|  | void OnFailure(const std::string& message) override { | 
|  | owner_->has_failed_ = true; | 
|  | owner_->failure_message_ = message; | 
|  | done_callback_.Run(); | 
|  | } | 
|  |  | 
|  | void OnStartOpeningHandshake( | 
|  | std::unique_ptr<WebSocketHandshakeRequestInfo> request) override { | 
|  | // Can be called multiple times (in the case of HTTP auth). Last call | 
|  | // wins. | 
|  | owner_->request_info_ = std::move(request); | 
|  | } | 
|  |  | 
|  | void OnFinishOpeningHandshake( | 
|  | std::unique_ptr<WebSocketHandshakeResponseInfo> response) override { | 
|  | if (owner_->response_info_) | 
|  | ADD_FAILURE(); | 
|  | owner_->response_info_ = std::move(response); | 
|  | } | 
|  |  | 
|  | void OnSSLCertificateError( | 
|  | std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> | 
|  | ssl_error_callbacks, | 
|  | const SSLInfo& ssl_info, | 
|  | bool fatal) override { | 
|  | owner_->ssl_error_callbacks_ = std::move(ssl_error_callbacks); | 
|  | owner_->ssl_info_ = ssl_info; | 
|  | owner_->ssl_fatal_ = fatal; | 
|  | } | 
|  |  | 
|  | private: | 
|  | WebSocketStreamCreateTestBase* owner_; | 
|  | base::Closure done_callback_; | 
|  | DISALLOW_COPY_AND_ASSIGN(TestConnectDelegate); | 
|  | }; | 
|  |  | 
|  | WebSocketStreamCreateTestBase::WebSocketStreamCreateTestBase() | 
|  | : has_failed_(false), ssl_fatal_(false), url_request_(nullptr) {} | 
|  |  | 
|  | WebSocketStreamCreateTestBase::~WebSocketStreamCreateTestBase() { | 
|  | } | 
|  |  | 
|  | void WebSocketStreamCreateTestBase::CreateAndConnectStream( | 
|  | const GURL& socket_url, | 
|  | const std::vector<std::string>& sub_protocols, | 
|  | const url::Origin& origin, | 
|  | const GURL& first_party_for_cookies, | 
|  | const std::string& additional_headers, | 
|  | std::unique_ptr<base::Timer> timer) { | 
|  | for (size_t i = 0; i < ssl_data_.size(); ++i) { | 
|  | url_request_context_host_.AddSSLSocketDataProvider(std::move(ssl_data_[i])); | 
|  | } | 
|  | ssl_data_.clear(); | 
|  | std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate( | 
|  | new TestConnectDelegate(this, connect_run_loop_.QuitClosure())); | 
|  | WebSocketStream::ConnectDelegate* delegate = connect_delegate.get(); | 
|  | std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper( | 
|  | new DeterministicKeyWebSocketHandshakeStreamCreateHelper(delegate, | 
|  | sub_protocols)); | 
|  | stream_request_ = WebSocketStream::CreateAndConnectStreamForTesting( | 
|  | socket_url, std::move(create_helper), origin, first_party_for_cookies, | 
|  | additional_headers, url_request_context_host_.GetURLRequestContext(), | 
|  | NetLogWithSource(), std::move(connect_delegate), | 
|  | timer ? std::move(timer) | 
|  | : std::unique_ptr<base::Timer>(new base::Timer(false, false))); | 
|  | } | 
|  |  | 
|  | std::vector<HeaderKeyValuePair> | 
|  | WebSocketStreamCreateTestBase::RequestHeadersToVector( | 
|  | const HttpRequestHeaders& headers) { | 
|  | HttpRequestHeaders::Iterator it(headers); | 
|  | std::vector<HeaderKeyValuePair> result; | 
|  | while (it.GetNext()) | 
|  | result.push_back(HeaderKeyValuePair(it.name(), it.value())); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | std::vector<HeaderKeyValuePair> | 
|  | WebSocketStreamCreateTestBase::ResponseHeadersToVector( | 
|  | const HttpResponseHeaders& headers) { | 
|  | size_t iter = 0; | 
|  | std::string name, value; | 
|  | std::vector<HeaderKeyValuePair> result; | 
|  | while (headers.EnumerateHeaderLines(&iter, &name, &value)) | 
|  | result.push_back(HeaderKeyValuePair(name, value)); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void WebSocketStreamCreateTestBase::WaitUntilConnectDone() { | 
|  | connect_run_loop_.Run(); | 
|  | } | 
|  |  | 
|  | std::vector<std::string> WebSocketStreamCreateTestBase::NoSubProtocols() { | 
|  | return std::vector<std::string>(); | 
|  | } | 
|  |  | 
|  | }  // namespace net |