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