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