websocket.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. #ifndef SERVICES_NETWORK_WEBSOCKET_H_
  5. #define SERVICES_NETWORK_WEBSOCKET_H_
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "base/component_export.h"
  11. #include "base/containers/queue.h"
  12. #include "base/containers/span.h"
  13. #include "base/memory/raw_ptr.h"
  14. #include "base/memory/scoped_refptr.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/time/time.h"
  17. #include "base/types/strong_alias.h"
  18. #include "mojo/public/cpp/bindings/receiver.h"
  19. #include "mojo/public/cpp/bindings/remote.h"
  20. #include "net/base/network_delegate.h"
  21. #include "net/traffic_annotation/network_traffic_annotation.h"
  22. #include "net/websockets/websocket_event_interface.h"
  23. #include "services/network/network_service.h"
  24. #include "services/network/public/mojom/network_context.mojom.h"
  25. #include "services/network/public/mojom/websocket.mojom.h"
  26. #include "services/network/websocket_interceptor.h"
  27. #include "services/network/websocket_throttler.h"
  28. #include "third_party/abseil-cpp/absl/types/optional.h"
  29. #include "url/origin.h"
  30. class GURL;
  31. namespace base {
  32. class Location;
  33. } // namespace base
  34. namespace net {
  35. class IOBuffer;
  36. class IsolationInfo;
  37. class SSLInfo;
  38. class SiteForCookies;
  39. class WebSocketChannel;
  40. } // namespace net
  41. namespace network {
  42. class WebSocketFactory;
  43. // Host of net::WebSocketChannel.
  44. class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
  45. public:
  46. using HasRawHeadersAccess =
  47. base::StrongAlias<class HasRawHeadersAccessTag, bool>;
  48. WebSocket(
  49. WebSocketFactory* factory,
  50. const GURL& url,
  51. const std::vector<std::string>& requested_protocols,
  52. const net::SiteForCookies& site_for_cookies,
  53. const net::IsolationInfo& isolation_info,
  54. std::vector<mojom::HttpHeaderPtr> additional_headers,
  55. const url::Origin& origin,
  56. uint32_t options,
  57. net::NetworkTrafficAnnotationTag traffic_annotation,
  58. HasRawHeadersAccess has_raw_cookie_access,
  59. mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
  60. mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
  61. url_loader_network_observer,
  62. mojo::PendingRemote<mojom::WebSocketAuthenticationHandler> auth_handler,
  63. mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
  64. absl::optional<WebSocketThrottler::PendingConnection>
  65. pending_connection_tracker,
  66. base::TimeDelta delay,
  67. const absl::optional<base::UnguessableToken>& throttling_profile_id);
  68. WebSocket(const WebSocket&) = delete;
  69. WebSocket& operator=(const WebSocket&) = delete;
  70. ~WebSocket() override;
  71. // mojom::WebSocket methods:
  72. void SendMessage(mojom::WebSocketMessageType type,
  73. uint64_t data_length) override;
  74. void StartReceiving() override;
  75. void StartClosingHandshake(uint16_t code, const std::string& reason) override;
  76. // Whether to allow sending/setting cookies during WebSocket handshakes for
  77. // |url|. This decision is based on the |options_| and |origin_| this
  78. // WebSocket was created with.
  79. bool AllowCookies(const GURL& url) const;
  80. // These methods are called by the network delegate to forward these events to
  81. // the |header_client_|.
  82. int OnBeforeStartTransaction(
  83. const net::HttpRequestHeaders& headers,
  84. net::NetworkDelegate::OnBeforeStartTransactionCallback callback);
  85. int OnHeadersReceived(
  86. net::CompletionOnceCallback callback,
  87. const net::HttpResponseHeaders* original_response_headers,
  88. scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
  89. absl::optional<GURL>* preserve_fragment_on_redirect_url);
  90. // Gets the WebSocket associated with this request.
  91. static WebSocket* ForRequest(const net::URLRequest& request);
  92. static const void* const kUserDataKey;
  93. private:
  94. class WebSocketEventHandler;
  95. struct CloseInfo;
  96. // This class is used to set the WebSocket as user data on a URLRequest. This
  97. // is used instead of WebSocket directly because SetUserData requires a
  98. // std::unique_ptr. This is safe because WebSocket owns the URLRequest, so is
  99. // guaranteed to outlive it.
  100. class UnownedPointer : public base::SupportsUserData::Data {
  101. public:
  102. explicit UnownedPointer(WebSocket* pointer) : pointer_(pointer) {}
  103. UnownedPointer(const UnownedPointer&) = delete;
  104. UnownedPointer& operator=(const UnownedPointer&) = delete;
  105. WebSocket* get() const { return pointer_; }
  106. private:
  107. const raw_ptr<WebSocket> pointer_;
  108. };
  109. struct DataFrame final {
  110. DataFrame(mojom::WebSocketMessageType type,
  111. uint64_t data_length,
  112. bool do_not_fragment)
  113. : type(type),
  114. data_length(data_length),
  115. do_not_fragment(do_not_fragment) {}
  116. mojom::WebSocketMessageType type;
  117. uint64_t data_length;
  118. const bool do_not_fragment;
  119. };
  120. void OnConnectionError(const base::Location& set_from);
  121. void AddChannel(const GURL& socket_url,
  122. const std::vector<std::string>& requested_protocols,
  123. const net::SiteForCookies& site_for_cookies,
  124. const net::IsolationInfo& isolation_info,
  125. std::vector<mojom::HttpHeaderPtr> additional_headers);
  126. void OnSSLCertificateErrorResponse(
  127. std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
  128. callbacks,
  129. const net::SSLInfo& ssl_info,
  130. int net_error);
  131. void OnAuthRequiredComplete(
  132. base::OnceCallback<void(const net::AuthCredentials*)> callback,
  133. const absl::optional<net::AuthCredentials>& credential);
  134. void OnBeforeSendHeadersComplete(
  135. net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
  136. int result,
  137. const absl::optional<net::HttpRequestHeaders>& headers);
  138. void OnHeadersReceivedComplete(
  139. net::CompletionOnceCallback callback,
  140. scoped_refptr<net::HttpResponseHeaders>* out_headers,
  141. absl::optional<GURL>* out_preserve_fragment_on_redirect_url,
  142. int result,
  143. const absl::optional<std::string>& headers,
  144. const absl::optional<GURL>& preserve_fragment_on_redirect_url);
  145. void Reset();
  146. enum class InterruptionReason {
  147. // Not interrupted or not resuming after interruptions (but processing a
  148. // brand new frame)
  149. kNone,
  150. // Interrupted by empty Mojo pipe or resuming afterwards
  151. kMojoPipe,
  152. // Interrupted by the interceptor or resuming afterwards
  153. kInterceptor,
  154. };
  155. // Datapipe functions to receive.
  156. void OnWritable(MojoResult result, const mojo::HandleSignalsState& state);
  157. void SendPendingDataFrames(InterruptionReason resume_reason);
  158. void SendDataFrame(base::span<const char>* data_span);
  159. // Datapipe functions to send.
  160. void OnReadable(MojoResult result, const mojo::HandleSignalsState& state);
  161. void ReadAndSendFromDataPipe(InterruptionReason resume_reason);
  162. // This helper method only called from ReadAndSendFromDataPipe.
  163. // Note that it may indirectly delete |this|.
  164. // Returns true if the frame has been sent completely.
  165. bool ReadAndSendFrameFromDataPipe(DataFrame* data_frame);
  166. void ResumeDataPipeReading();
  167. // |factory_| owns |this|.
  168. const raw_ptr<WebSocketFactory> factory_;
  169. mojo::Receiver<mojom::WebSocket> receiver_{this};
  170. mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
  171. url_loader_network_observer_;
  172. mojo::Remote<mojom::WebSocketHandshakeClient> handshake_client_;
  173. mojo::Remote<mojom::WebSocketClient> client_;
  174. mojo::Remote<mojom::WebSocketAuthenticationHandler> auth_handler_;
  175. mojo::Remote<mojom::TrustedHeaderClient> header_client_;
  176. absl::optional<WebSocketThrottler::PendingConnection>
  177. pending_connection_tracker_;
  178. // The channel we use to send events to the network.
  179. std::unique_ptr<net::WebSocketChannel> channel_;
  180. // Delay used for per-renderer WebSocket throttling.
  181. const base::TimeDelta delay_;
  182. const uint32_t options_;
  183. const net::NetworkTrafficAnnotationTag traffic_annotation_;
  184. // The web origin to use for the WebSocket.
  185. const url::Origin origin_;
  186. // For 3rd-party cookie permission checking.
  187. net::SiteForCookies site_for_cookies_;
  188. bool handshake_succeeded_ = false;
  189. const HasRawHeadersAccess has_raw_headers_access_;
  190. InterruptionReason incoming_frames_interrupted_ = InterruptionReason::kNone;
  191. InterruptionReason outgoing_frames_interrupted_ = InterruptionReason::kNone;
  192. // Datapipe fields to receive.
  193. mojo::ScopedDataPipeProducerHandle writable_;
  194. mojo::SimpleWatcher writable_watcher_;
  195. base::queue<base::span<const char>> pending_data_frames_;
  196. // Datapipe fields to send.
  197. mojo::ScopedDataPipeConsumerHandle readable_;
  198. mojo::SimpleWatcher readable_watcher_;
  199. base::queue<DataFrame> pending_send_data_frames_;
  200. bool blocked_on_websocket_channel_ = false;
  201. // True if we should preserve the old behaviour where <=64KB messages were
  202. // never fragmented.
  203. // TODO(ricea): Remove the flag once we know whether we really need this or
  204. // not. See https://crbug.com/1086273.
  205. const bool reassemble_short_messages_;
  206. // Temporary buffer for storage of short messages that have been fragmented by
  207. // the data pipe. Only messages that are actually fragmented are copied into
  208. // here.
  209. scoped_refptr<net::IOBuffer> message_under_reassembly_;
  210. // Number of bytes that have been written to |message_under_reassembly_| so
  211. // far.
  212. size_t bytes_reassembled_ = 0;
  213. // Set when StartClosingHandshake() is called while
  214. // |pending_send_data_frames_| is non-empty. This can happen due to a race
  215. // condition between the readable signal on the data pipe and the channel on
  216. // which StartClosingHandshake() is called.
  217. std::unique_ptr<CloseInfo> pending_start_closing_handshake_;
  218. const absl::optional<base::UnguessableToken> throttling_profile_id_;
  219. uint32_t net_log_source_id_ = net::NetLogSource::kInvalidId;
  220. std::unique_ptr<WebSocketInterceptor> frame_interceptor_;
  221. base::WeakPtrFactory<WebSocket> weak_ptr_factory_{this};
  222. };
  223. } // namespace network
  224. #endif // SERVICES_NETWORK_WEBSOCKET_H_