#include "services/network/websocket.h"
#include <inttypes.h>
#include <string.h>
#include <memory>
#include <tuple>
#include <utility>
#include "base/check.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "net/base/auth.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/cookies/static_cookie_policy.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/ssl/ssl_info.h"
#include "net/storage_access_api/status.h"
#include "net/url_request/url_request_context.h"
#include "net/websockets/websocket_basic_stream.h"
#include "net/websockets/websocket_channel.h"
#include "net/websockets/websocket_errors.h"
#include "net/websockets/websocket_frame.h"
#include "net/websockets/websocket_handshake_request_info.h"
#include "net/websockets/websocket_handshake_response_info.h"
#include "services/network/public/cpp/ip_address_space_util.h"
#include "services/network/throttling/throttling_controller.h"
#include "services/network/throttling/throttling_network_interceptor.h"
#include "services/network/websocket_factory.h"
#include "services/network/websocket_interceptor.h"
namespace network {
namespace {
constexpr uint64_t kSmallMessageThreshhold = …;
constexpr uint32_t kReceiveDataPipeCapacity = …;
net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
mojom::WebSocketMessageType type) { … }
mojom::WebSocketMessageType OpCodeToMessageType(
net::WebSocketFrameHeader::OpCode opCode) { … }
mojom::WebSocketHandshakeResponsePtr ToMojo(
std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
bool has_raw_headers_access) { … }
}
class WebSocket::WebSocketEventHandler final
: public net::WebSocketEventInterface { … };
WebSocket::WebSocketEventHandler::WebSocketEventHandler(WebSocket* impl)
: … { … }
WebSocket::WebSocketEventHandler::~WebSocketEventHandler() { … }
void WebSocket::WebSocketEventHandler::OnCreateURLRequest(
net::URLRequest* url_request) { … }
void WebSocket::WebSocketEventHandler::OnURLRequestConnected(
net::URLRequest* request,
const net::TransportInfo& info) { … }
void WebSocket::WebSocketEventHandler::OnAddChannelResponse(
std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
const std::string& selected_protocol,
const std::string& extensions) { … }
void WebSocket::WebSocketEventHandler::OnDataFrame(
bool fin,
net::WebSocketFrameHeader::OpCode type,
base::span<const char> payload) { … }
void WebSocket::WebSocketEventHandler::OnSendDataFrameDone() { … }
bool WebSocket::WebSocketEventHandler::HasPendingDataFrames() { … }
void WebSocket::WebSocketEventHandler::OnClosingHandshake() { … }
void WebSocket::WebSocketEventHandler::OnDropChannel(
bool was_clean,
uint16_t code,
const std::string& reason) { … }
void WebSocket::WebSocketEventHandler::OnFailChannel(
const std::string& message,
int net_error,
std::optional<int> response_code) { … }
void WebSocket::WebSocketEventHandler::OnStartOpeningHandshake(
std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) { … }
void WebSocket::WebSocketEventHandler::OnSSLCertificateError(
std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
const GURL& url,
int net_error,
const net::SSLInfo& ssl_info,
bool fatal) { … }
int WebSocket::WebSocketEventHandler::OnAuthRequired(
const net::AuthChallengeInfo& auth_info,
scoped_refptr<net::HttpResponseHeaders> response_headers,
const net::IPEndPoint& remote_endpoint,
base::OnceCallback<void(const net::AuthCredentials*)> callback,
std::optional<net::AuthCredentials>* credentials) { … }
struct WebSocket::CloseInfo { … };
WebSocket::WebSocket(
WebSocketFactory* factory,
const GURL& url,
const std::vector<std::string>& requested_protocols,
const net::SiteForCookies& site_for_cookies,
net::StorageAccessApiStatus storage_access_api_status,
const net::IsolationInfo& isolation_info,
std::vector<mojom::HttpHeaderPtr> additional_headers,
const url::Origin& origin,
uint32_t options,
net::NetworkTrafficAnnotationTag traffic_annotation,
HasRawHeadersAccess has_raw_headers_access,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
url_loader_network_observer,
mojo::PendingRemote<mojom::WebSocketAuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
std::optional<WebSocketThrottler::PendingConnection>
pending_connection_tracker,
base::TimeDelta delay,
const std::optional<base::UnguessableToken>& throttling_profile_id)
: … { … }
WebSocket::~WebSocket() { … }
const void* const WebSocket::kUserDataKey = …;
void WebSocket::SendMessage(mojom::WebSocketMessageType type,
uint64_t data_length) { … }
void WebSocket::StartReceiving() { … }
void WebSocket::StartClosingHandshake(uint16_t code,
const std::string& reason) { … }
bool WebSocket::AllowCookies(const GURL& url) const { … }
bool WebSocket::RevokeIfNonceMatches(const base::UnguessableToken& nonce) { … }
int WebSocket::OnBeforeStartTransaction(
const net::HttpRequestHeaders& headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback) { … }
int WebSocket::OnHeadersReceived(
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
std::optional<GURL>* preserve_fragment_on_redirect_url) { … }
WebSocket* WebSocket::ForRequest(const net::URLRequest& request) { … }
void WebSocket::OnConnectionError(const base::Location& set_from) { … }
void WebSocket::AddChannel(
const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const net::SiteForCookies& site_for_cookies,
net::StorageAccessApiStatus storage_access_api_status,
const net::IsolationInfo& isolation_info,
std::vector<mojom::HttpHeaderPtr> additional_headers) { … }
void WebSocket::OnWritable(MojoResult result,
const mojo::HandleSignalsState& state) { … }
void WebSocket::SendPendingDataFrames(InterruptionReason resume_reason) { … }
void WebSocket::SendDataFrame(base::span<const char>* payload) { … }
void WebSocket::OnReadable(MojoResult result,
const mojo::HandleSignalsState& state) { … }
void WebSocket::ReadAndSendFromDataPipe(InterruptionReason resume_reason) { … }
bool WebSocket::ReadAndSendFrameFromDataPipe(DataFrame* data_frame) { … }
void WebSocket::ResumeDataPipeReading() { … }
void WebSocket::OnSSLCertificateErrorResponse(
std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
const net::SSLInfo& ssl_info,
int net_error) { … }
void WebSocket::OnAuthRequiredComplete(
base::OnceCallback<void(const net::AuthCredentials*)> callback,
const std::optional<net::AuthCredentials>& credentials) { … }
void WebSocket::OnBeforeSendHeadersComplete(
net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const std::optional<net::HttpRequestHeaders>& headers) { … }
void WebSocket::OnHeadersReceivedComplete(
net::CompletionOnceCallback callback,
scoped_refptr<net::HttpResponseHeaders>* out_headers,
std::optional<GURL>* out_preserve_fragment_on_redirect_url,
int result,
const std::optional<std::string>& headers,
const std::optional<GURL>& preserve_fragment_on_redirect_url) { … }
void WebSocket::Reset() { … }
}