• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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