1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_ 6 #define NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/macros.h" 16 #include "net/http/http_basic_state.h" 17 #include "net/http/http_request_headers.h" 18 #include "net/http/http_stream_parser.h" 19 #include "net/socket/client_socket_handle.h" 20 #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" 21 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" 22 #include "net/url_request/url_request_test_util.h" 23 #include "net/websockets/websocket_handshake_stream_create_helper.h" 24 #include "net/websockets/websocket_stream.h" 25 26 namespace url { 27 class Origin; 28 } // namespace url 29 30 namespace net { 31 32 using WebSocketExtraHeaders = std::vector<std::pair<std::string, std::string>>; 33 34 class MockClientSocketFactory; 35 class WebSocketBasicHandshakeStream; 36 class ProxyResolutionService; 37 class SequencedSocketData; 38 class IPEndPoint; 39 struct SSLSocketDataProvider; 40 41 class LinearCongruentialGenerator { 42 public: 43 explicit LinearCongruentialGenerator(uint32_t seed); 44 uint32_t Generate(); 45 46 private: 47 uint64_t current_; 48 }; 49 50 // Converts a vector of header key-value pairs into a single string. 51 std::string WebSocketExtraHeadersToString(const WebSocketExtraHeaders& headers); 52 53 // Converts a vector of header key-value pairs into an HttpRequestHeaders 54 HttpRequestHeaders WebSocketExtraHeadersToHttpRequestHeaders( 55 const WebSocketExtraHeaders& headers); 56 57 // Generates a standard WebSocket handshake request. The challenge key used is 58 // "dGhlIHNhbXBsZSBub25jZQ==". Each header in |extra_headers| must be terminated 59 // with "\r\n". 60 std::string WebSocketStandardRequest( 61 const std::string& path, 62 const std::string& host, 63 const url::Origin& origin, 64 const std::string& send_additional_request_headers, 65 const std::string& extra_headers); 66 67 // Generates a standard WebSocket handshake request. The challenge key used is 68 // "dGhlIHNhbXBsZSBub25jZQ==". |cookies| must be empty or terminated with 69 // "\r\n". Each header in |extra_headers| must be terminated with "\r\n". 70 std::string WebSocketStandardRequestWithCookies( 71 const std::string& path, 72 const std::string& host, 73 const url::Origin& origin, 74 const std::string& cookies, 75 const std::string& send_additional_request_headers, 76 const std::string& extra_headers); 77 78 // A response with the appropriate accept header to match the above 79 // challenge key. Each header in |extra_headers| must be terminated with 80 // "\r\n". 81 std::string WebSocketStandardResponse(const std::string& extra_headers); 82 83 // WebSocketCommonTestHeaders() generates a common set of request headers 84 // corresponding to WebSocketStandardRequest("/", "www.example.org", 85 // url::Origin::Create(GURL("http://origin.example.org")), "", "") 86 HttpRequestHeaders WebSocketCommonTestHeaders(); 87 88 // Generates a handshake request header block when using WebSockets over HTTP/2. 89 spdy::SpdyHeaderBlock WebSocketHttp2Request( 90 const std::string& path, 91 const std::string& authority, 92 const std::string& origin, 93 const WebSocketExtraHeaders& extra_headers); 94 95 // Generates a handshake response header block when using WebSockets over 96 // HTTP/2. 97 spdy::SpdyHeaderBlock WebSocketHttp2Response( 98 const WebSocketExtraHeaders& extra_headers); 99 100 // This class provides a convenient way to construct a MockClientSocketFactory 101 // for WebSocket tests. 102 class WebSocketMockClientSocketFactoryMaker { 103 public: 104 WebSocketMockClientSocketFactoryMaker(); 105 ~WebSocketMockClientSocketFactoryMaker(); 106 107 // Tell the factory to create a socket which expects |expect_written| to be 108 // written, and responds with |return_to_read|. The test will fail if the 109 // expected text is not written, or all the bytes are not read. This adds data 110 // for a new mock-socket using AddRawExpections(), and so can be called 111 // multiple times to queue up multiple mock sockets, but usually in those 112 // cases the lower-level AddRawExpections() interface is more appropriate. 113 void SetExpectations(const std::string& expect_written, 114 const std::string& return_to_read); 115 116 // A low-level interface to permit arbitrary expectations to be added. The 117 // mock sockets will be created in the same order that they were added. 118 void AddRawExpectations(std::unique_ptr<SequencedSocketData> socket_data); 119 120 // Allow an SSL socket data provider to be added. You must also supply a mock 121 // transport socket for it to use. If the mock SSL handshake fails then the 122 // mock transport socket will connect but have nothing read or written. If the 123 // mock handshake succeeds then the data from the underlying transport socket 124 // will be passed through unchanged (without encryption). 125 void AddSSLSocketDataProvider( 126 std::unique_ptr<SSLSocketDataProvider> ssl_socket_data); 127 128 // Call to get a pointer to the factory, which remains owned by this object. 129 MockClientSocketFactory* factory(); 130 131 private: 132 struct Detail; 133 std::unique_ptr<Detail> detail_; 134 135 DISALLOW_COPY_AND_ASSIGN(WebSocketMockClientSocketFactoryMaker); 136 }; 137 138 // This class encapsulates the details of creating a 139 // TestURLRequestContext that returns mock ClientSocketHandles that do what is 140 // required by the tests. 141 struct WebSocketTestURLRequestContextHost { 142 public: 143 WebSocketTestURLRequestContextHost(); 144 ~WebSocketTestURLRequestContextHost(); 145 SetExpectationsWebSocketTestURLRequestContextHost146 void SetExpectations(const std::string& expect_written, 147 const std::string& return_to_read) { 148 maker_.SetExpectations(expect_written, return_to_read); 149 } 150 151 void AddRawExpectations(std::unique_ptr<SequencedSocketData> socket_data); 152 153 // Allow an SSL socket data provider to be added. 154 void AddSSLSocketDataProvider( 155 std::unique_ptr<SSLSocketDataProvider> ssl_socket_data); 156 157 // Allow a proxy to be set. Usage: 158 // SetProxyConfig("proxy1:8000"); 159 // Any syntax accepted by net::ProxyConfig::ParseFromString() will work. 160 // Do not call after GetURLRequestContext() has been called. 161 void SetProxyConfig(const std::string& proxy_rules); 162 163 // Call after calling one of SetExpections() or AddRawExpectations(). The 164 // returned pointer remains owned by this object. 165 TestURLRequestContext* GetURLRequestContext(); 166 network_delegateWebSocketTestURLRequestContextHost167 const TestNetworkDelegate& network_delegate() const { 168 return network_delegate_; 169 } 170 171 private: 172 WebSocketMockClientSocketFactoryMaker maker_; 173 TestURLRequestContext url_request_context_; 174 TestNetworkDelegate network_delegate_; 175 std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; 176 bool url_request_context_initialized_; 177 178 DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost); 179 }; 180 181 // WebSocketStream::ConnectDelegate implementation that does nothing. 182 class DummyConnectDelegate : public WebSocketStream::ConnectDelegate { 183 public: 184 DummyConnectDelegate() = default; 185 ~DummyConnectDelegate() override = default; OnCreateRequest(URLRequest * url_request)186 void OnCreateRequest(URLRequest* url_request) override {} OnSuccess(std::unique_ptr<WebSocketStream> stream,std::unique_ptr<WebSocketHandshakeResponseInfo> response)187 void OnSuccess( 188 std::unique_ptr<WebSocketStream> stream, 189 std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {} OnFailure(const std::string & message)190 void OnFailure(const std::string& message) override {} OnStartOpeningHandshake(std::unique_ptr<WebSocketHandshakeRequestInfo> request)191 void OnStartOpeningHandshake( 192 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {} OnSSLCertificateError(std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> ssl_error_callbacks,int net_error,const SSLInfo & ssl_info,bool fatal)193 void OnSSLCertificateError( 194 std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> 195 ssl_error_callbacks, 196 int net_error, 197 const SSLInfo& ssl_info, 198 bool fatal) override {} 199 int OnAuthRequired(const AuthChallengeInfo& auth_info, 200 scoped_refptr<HttpResponseHeaders> response_headers, 201 const IPEndPoint& remote_endpoint, 202 base::OnceCallback<void(const AuthCredentials*)> callback, 203 base::Optional<AuthCredentials>* credentials) override; 204 }; 205 206 // WebSocketStreamRequestAPI implementation that sets the value of 207 // Sec-WebSocket-Key to the deterministic key that is used by tests. 208 class TestWebSocketStreamRequestAPI : public WebSocketStreamRequestAPI { 209 public: 210 TestWebSocketStreamRequestAPI() = default; 211 ~TestWebSocketStreamRequestAPI() override = default; 212 void OnBasicHandshakeStreamCreated( 213 WebSocketBasicHandshakeStream* handshake_stream) override; 214 void OnHttp2HandshakeStreamCreated( 215 WebSocketHttp2HandshakeStream* handshake_stream) override; OnFailure(const std::string & message)216 void OnFailure(const std::string& message) override {} 217 }; 218 219 // A sub-class of WebSocketHandshakeStreamCreateHelper which sets a 220 // deterministic key to use in the WebSocket handshake, and uses a dummy 221 // ConnectDelegate and WebSocketStreamRequestAPI. 222 class TestWebSocketHandshakeStreamCreateHelper 223 : public WebSocketHandshakeStreamCreateHelper { 224 public: 225 // Constructor for using dummy ConnectDelegate and WebSocketStreamRequestAPI. TestWebSocketHandshakeStreamCreateHelper()226 TestWebSocketHandshakeStreamCreateHelper() 227 : WebSocketHandshakeStreamCreateHelper(&connect_delegate_, 228 /* requested_subprotocols = */ {}, 229 &request_) {} 230 231 ~TestWebSocketHandshakeStreamCreateHelper() override = default; 232 233 private: 234 DummyConnectDelegate connect_delegate_; 235 TestWebSocketStreamRequestAPI request_; 236 237 DISALLOW_COPY_AND_ASSIGN(TestWebSocketHandshakeStreamCreateHelper); 238 }; 239 240 } // namespace net 241 242 #endif // NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_ 243