| Index: content/browser/websocket/websocket_impl.cc
|
| diff --git a/content/browser/renderer_host/websocket_host.cc b/content/browser/websocket/websocket_impl.cc
|
| similarity index 52%
|
| rename from content/browser/renderer_host/websocket_host.cc
|
| rename to content/browser/websocket/websocket_impl.cc
|
| index cce4485b3d4d67801e5037ee042d88fd5aaaaa41..6b8dd77753aa3e6bf6fcb1228f9a48721c7e47b5 100644
|
| --- a/content/browser/renderer_host/websocket_host.cc
|
| +++ b/content/browser/websocket/websocket_impl.cc
|
| @@ -2,7 +2,7 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "content/browser/renderer_host/websocket_host.h"
|
| +#include "content/browser/websocket/websocket_impl.h"
|
|
|
| #include <inttypes.h>
|
|
|
| @@ -19,20 +19,19 @@
|
| #include "base/strings/stringprintf.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "content/browser/bad_message.h"
|
| -#include "content/browser/renderer_host/websocket_blob_sender.h"
|
| -#include "content/browser/renderer_host/websocket_dispatcher_host.h"
|
| +#include "content/browser/child_process_security_policy_impl.h"
|
| #include "content/browser/ssl/ssl_error_handler.h"
|
| #include "content/browser/ssl/ssl_manager.h"
|
| -#include "content/common/websocket_messages.h"
|
| +#include "content/browser/websocket/websocket_blob_sender.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/storage_partition.h"
|
| -#include "ipc/ipc_message_macros.h"
|
| #include "net/base/net_errors.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/url_request/url_request_context_getter.h"
|
| #include "net/websockets/websocket_channel.h"
|
| #include "net/websockets/websocket_errors.h"
|
| #include "net/websockets/websocket_event_interface.h"
|
| @@ -42,7 +41,6 @@
|
| #include "url/origin.h"
|
|
|
| namespace content {
|
| -
|
| namespace {
|
|
|
| typedef net::WebSocketEventInterface::ChannelState ChannelState;
|
| @@ -50,54 +48,37 @@ typedef net::WebSocketEventInterface::ChannelState ChannelState;
|
| // Convert a content::WebSocketMessageType to a
|
| // net::WebSocketFrameHeader::OpCode
|
| net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
|
| - WebSocketMessageType type) {
|
| - DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION ||
|
| - type == WEB_SOCKET_MESSAGE_TYPE_TEXT ||
|
| - type == WEB_SOCKET_MESSAGE_TYPE_BINARY);
|
| + mojom::WebSocketMessageType type) {
|
| + DCHECK(type == mojom::WebSocketMessageType::CONTINUATION ||
|
| + type == mojom::WebSocketMessageType::TEXT ||
|
| + type == mojom::WebSocketMessageType::BINARY);
|
| typedef net::WebSocketFrameHeader::OpCode OpCode;
|
| // These compile asserts verify that the same underlying values are used for
|
| // both types, so we can simply cast between them.
|
| - static_assert(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) ==
|
| - net::WebSocketFrameHeader::kOpCodeContinuation,
|
| - "enum values must match for opcode continuation");
|
| - static_assert(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) ==
|
| - net::WebSocketFrameHeader::kOpCodeText,
|
| - "enum values must match for opcode text");
|
| - static_assert(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) ==
|
| - net::WebSocketFrameHeader::kOpCodeBinary,
|
| - "enum values must match for opcode binary");
|
| + static_assert(
|
| + static_cast<OpCode>(mojom::WebSocketMessageType::CONTINUATION) ==
|
| + net::WebSocketFrameHeader::kOpCodeContinuation,
|
| + "enum values must match for opcode continuation");
|
| + static_assert(
|
| + static_cast<OpCode>(mojom::WebSocketMessageType::TEXT) ==
|
| + net::WebSocketFrameHeader::kOpCodeText,
|
| + "enum values must match for opcode text");
|
| + static_assert(
|
| + static_cast<OpCode>(mojom::WebSocketMessageType::BINARY) ==
|
| + net::WebSocketFrameHeader::kOpCodeBinary,
|
| + "enum values must match for opcode binary");
|
| return static_cast<OpCode>(type);
|
| }
|
|
|
| -WebSocketMessageType OpCodeToMessageType(
|
| +mojom::WebSocketMessageType OpCodeToMessageType(
|
| net::WebSocketFrameHeader::OpCode opCode) {
|
| DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
|
| opCode == net::WebSocketFrameHeader::kOpCodeText ||
|
| opCode == net::WebSocketFrameHeader::kOpCodeBinary);
|
| // This cast is guaranteed valid by the static_assert() statements above.
|
| - return static_cast<WebSocketMessageType>(opCode);
|
| -}
|
| -
|
| -ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
|
| - const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_ALIVE =
|
| - WebSocketDispatcherHost::WEBSOCKET_HOST_ALIVE;
|
| - const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_DELETED =
|
| - WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED;
|
| -
|
| - DCHECK(host_state == WEBSOCKET_HOST_ALIVE ||
|
| - host_state == WEBSOCKET_HOST_DELETED);
|
| - // These compile asserts verify that we can get away with using static_cast<>
|
| - // for the conversion.
|
| - static_assert(static_cast<ChannelState>(WEBSOCKET_HOST_ALIVE) ==
|
| - net::WebSocketEventInterface::CHANNEL_ALIVE,
|
| - "enum values must match for state_alive");
|
| - static_assert(static_cast<ChannelState>(WEBSOCKET_HOST_DELETED) ==
|
| - net::WebSocketEventInterface::CHANNEL_DELETED,
|
| - "enum values must match for state_deleted");
|
| - return static_cast<ChannelState>(host_state);
|
| + return static_cast<mojom::WebSocketMessageType>(opCode);
|
| }
|
|
|
| -// Implementation of WebSocketBlobSender::Channel
|
| class SendChannelImpl final : public WebSocketBlobSender::Channel {
|
| public:
|
| explicit SendChannelImpl(net::WebSocketChannel* channel)
|
| @@ -127,13 +108,10 @@ class SendChannelImpl final : public WebSocketBlobSender::Channel {
|
| // Implementation of net::WebSocketEventInterface. Receives events from our
|
| // WebSocketChannel object. Each event is translated to an IPC and sent to the
|
| // renderer or child process via WebSocketDispatcherHost.
|
| -class WebSocketHost::WebSocketEventHandler final
|
| +class WebSocketImpl::WebSocketEventHandler final
|
| : public net::WebSocketEventInterface {
|
| public:
|
| - WebSocketEventHandler(WebSocketDispatcherHost* dispatcher,
|
| - WebSocketHost* host,
|
| - int routing_id,
|
| - int render_frame_id);
|
| + explicit WebSocketEventHandler(WebSocketImpl* impl);
|
| ~WebSocketEventHandler() override;
|
|
|
| // net::WebSocketEventInterface implementation
|
| @@ -181,172 +159,206 @@ class WebSocketHost::WebSocketEventHandler final
|
| DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
|
| };
|
|
|
| - WebSocketDispatcherHost* const dispatcher_;
|
| - WebSocketHost* const host_;
|
| - const int routing_id_;
|
| - const int render_frame_id_;
|
| + WebSocketImpl* const impl_;
|
| std::unique_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
|
| };
|
|
|
| -WebSocketHost::WebSocketEventHandler::WebSocketEventHandler(
|
| - WebSocketDispatcherHost* dispatcher,
|
| - WebSocketHost* host,
|
| - int routing_id,
|
| - int render_frame_id)
|
| - : dispatcher_(dispatcher),
|
| - host_(host),
|
| - routing_id_(routing_id),
|
| - render_frame_id_(render_frame_id) {}
|
| -
|
| -WebSocketHost::WebSocketEventHandler::~WebSocketEventHandler() {
|
| - DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
|
| +WebSocketImpl::WebSocketEventHandler::WebSocketEventHandler(WebSocketImpl* impl)
|
| + : impl_(impl) {
|
| + DVLOG(1) << "WebSocketEventHandler created @"
|
| + << reinterpret_cast<void*>(this);
|
| +}
|
| +
|
| +WebSocketImpl::WebSocketEventHandler::~WebSocketEventHandler() {
|
| + DVLOG(1) << "WebSocketEventHandler destroyed @"
|
| + << reinterpret_cast<void*>(this);
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnAddChannelResponse(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnAddChannelResponse(
|
| const std::string& selected_protocol,
|
| const std::string& extensions) {
|
| - DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
|
| - << " routing_id=" << routing_id_
|
| + DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse @"
|
| + << reinterpret_cast<void*>(this)
|
| << " selected_protocol=\"" << selected_protocol << "\""
|
| << " extensions=\"" << extensions << "\"";
|
|
|
| - return StateCast(dispatcher_->SendAddChannelResponse(
|
| - routing_id_, selected_protocol, extensions));
|
| + impl_->delegate_->OnReceivedResponseFromServer(impl_);
|
| +
|
| + impl_->client_->OnAddChannelResponse(selected_protocol, extensions);
|
| +
|
| + return net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnDataFrame(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnDataFrame(
|
| bool fin,
|
| net::WebSocketFrameHeader::OpCode type,
|
| const std::vector<char>& data) {
|
| - DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
|
| - << " routing_id=" << routing_id_ << " fin=" << fin
|
| + DVLOG(3) << "WebSocketEventHandler::OnDataFrame @"
|
| + << reinterpret_cast<void*>(this)
|
| + << " fin=" << fin
|
| << " type=" << type << " data is " << data.size() << " bytes";
|
|
|
| - return StateCast(dispatcher_->SendFrame(routing_id_, fin,
|
| - OpCodeToMessageType(type), data));
|
| + // TODO(darin): Avoid this copy.
|
| + mojo::Array<uint8_t> data_to_pass(data.size());
|
| + memcpy(&data_to_pass[0], &data[0], data.size());
|
| +
|
| + impl_->client_->OnDataFrame(fin, OpCodeToMessageType(type),
|
| + std::move(data_to_pass));
|
| +
|
| + return net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnClosingHandshake() {
|
| - DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
|
| - << " routing_id=" << routing_id_;
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnClosingHandshake() {
|
| + DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake @"
|
| + << reinterpret_cast<void*>(this);
|
| +
|
| + impl_->client_->OnClosingHandshake();
|
|
|
| - return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_));
|
| + return net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnFlowControl(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnFlowControl(
|
| int64_t quota) {
|
| - DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
|
| - << " routing_id=" << routing_id_ << " quota=" << quota;
|
| + DVLOG(3) << "WebSocketEventHandler::OnFlowControl @"
|
| + << reinterpret_cast<void*>(this)
|
| + << " quota=" << quota;
|
|
|
| - if (host_->blob_sender_)
|
| - host_->blob_sender_->OnNewSendQuota();
|
| - return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
|
| + if (impl_->blob_sender_)
|
| + impl_->blob_sender_->OnNewSendQuota();
|
| +
|
| + impl_->client_->OnFlowControl(quota);
|
| +
|
| + return net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnDropChannel(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnDropChannel(
|
| bool was_clean,
|
| uint16_t code,
|
| const std::string& reason) {
|
| - DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
|
| - << " routing_id=" << routing_id_ << " was_clean=" << was_clean
|
| - << " code=" << code << " reason=\"" << reason << "\"";
|
| + DVLOG(3) << "WebSocketEventHandler::OnDropChannel @"
|
| + << reinterpret_cast<void*>(this)
|
| + << " was_clean=" << was_clean << " code=" << code
|
| + << " reason=\"" << reason << "\"";
|
|
|
| - return StateCast(
|
| - dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason));
|
| + impl_->client_->OnDropChannel(was_clean, code, reason);
|
| +
|
| + return net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnFailChannel(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnFailChannel(
|
| const std::string& message) {
|
| - DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
|
| - << " routing_id=" << routing_id_ << " message=\"" << message << "\"";
|
| + DVLOG(3) << "WebSocketEventHandler::OnFailChannel @"
|
| + << reinterpret_cast<void*>(this) << " message=\"" << message << "\"";
|
| +
|
| + impl_->client_->OnFailChannel(message);
|
|
|
| - return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
|
| + return net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnStartOpeningHandshake(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnStartOpeningHandshake(
|
| std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) {
|
| - bool should_send = dispatcher_->CanReadRawCookies();
|
| - DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
|
| - << "should_send=" << should_send;
|
| + bool should_send =
|
| + ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
|
| + impl_->delegate_->GetClientProcessId());
|
| +
|
| + DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake @"
|
| + << reinterpret_cast<void*>(this) << " should_send=" << should_send;
|
|
|
| if (!should_send)
|
| return WebSocketEventInterface::CHANNEL_ALIVE;
|
|
|
| - WebSocketHandshakeRequest request_to_pass;
|
| - request_to_pass.url.Swap(&request->url);
|
| + mojom::WebSocketHandshakeRequestPtr request_to_pass(
|
| + mojom::WebSocketHandshakeRequest::New());
|
| + request_to_pass->url.Swap(&request->url);
|
| net::HttpRequestHeaders::Iterator it(request->headers);
|
| - while (it.GetNext())
|
| - request_to_pass.headers.push_back(std::make_pair(it.name(), it.value()));
|
| - request_to_pass.headers_text =
|
| + while (it.GetNext()) {
|
| + mojom::HttpHeaderPtr header(mojom::HttpHeader::New());
|
| + header->name = it.name();
|
| + header->value = it.value();
|
| + request_to_pass->headers.push_back(std::move(header));
|
| + }
|
| + request_to_pass->headers_text =
|
| base::StringPrintf("GET %s HTTP/1.1\r\n",
|
| - request_to_pass.url.spec().c_str()) +
|
| + request_to_pass->url.spec().c_str()) +
|
| request->headers.ToString();
|
| - request_to_pass.request_time = request->request_time;
|
|
|
| - return StateCast(
|
| - dispatcher_->NotifyStartOpeningHandshake(routing_id_, request_to_pass));
|
| + impl_->client_->OnStartOpeningHandshake(std::move(request_to_pass));
|
| +
|
| + return WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnFinishOpeningHandshake(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnFinishOpeningHandshake(
|
| std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) {
|
| - bool should_send = dispatcher_->CanReadRawCookies();
|
| + bool should_send =
|
| + ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
|
| + impl_->delegate_->GetClientProcessId());
|
| +
|
| DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
|
| - << "should_send=" << should_send;
|
| + << reinterpret_cast<void*>(this) << " should_send=" << should_send;
|
|
|
| if (!should_send)
|
| return WebSocketEventInterface::CHANNEL_ALIVE;
|
|
|
| - WebSocketHandshakeResponse response_to_pass;
|
| - response_to_pass.url.Swap(&response->url);
|
| - response_to_pass.status_code = response->status_code;
|
| - response_to_pass.status_text.swap(response->status_text);
|
| + mojom::WebSocketHandshakeResponsePtr response_to_pass(
|
| + mojom::WebSocketHandshakeResponse::New());
|
| + response_to_pass->url.Swap(&response->url);
|
| + response_to_pass->status_code = response->status_code;
|
| + response_to_pass->status_text = response->status_text;
|
| size_t iter = 0;
|
| std::string name, value;
|
| - while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
|
| - response_to_pass.headers.push_back(std::make_pair(name, value));
|
| - response_to_pass.headers_text =
|
| + while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
|
| + mojom::HttpHeaderPtr header(mojom::HttpHeader::New());
|
| + header->name = name;
|
| + header->value = value;
|
| + response_to_pass->headers.push_back(std::move(header));
|
| + }
|
| + response_to_pass->headers_text =
|
| net::HttpUtil::ConvertHeadersBackToHTTPResponse(
|
| response->headers->raw_headers());
|
| - response_to_pass.response_time = response->response_time;
|
|
|
| - return StateCast(
|
| - dispatcher_->NotifyFinishOpeningHandshake(routing_id_, response_to_pass));
|
| + impl_->client_->OnFinishOpeningHandshake(std::move(response_to_pass));
|
| +
|
| + return WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -ChannelState WebSocketHost::WebSocketEventHandler::OnSSLCertificateError(
|
| +ChannelState WebSocketImpl::WebSocketEventHandler::OnSSLCertificateError(
|
| std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
|
| const GURL& url,
|
| const net::SSLInfo& ssl_info,
|
| bool fatal) {
|
| DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
|
| - << " routing_id=" << routing_id_ << " url=" << url.spec()
|
| + << reinterpret_cast<void*>(this) << " url=" << url.spec()
|
| << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
|
| ssl_error_handler_delegate_.reset(
|
| new SSLErrorHandlerDelegate(std::move(callbacks)));
|
| SSLManager::OnSSLCertificateSubresourceError(
|
| - ssl_error_handler_delegate_->GetWeakPtr(), url,
|
| - dispatcher_->render_process_id(), render_frame_id_, ssl_info, fatal);
|
| + ssl_error_handler_delegate_->GetWeakPtr(),
|
| + url,
|
| + impl_->delegate_->GetClientProcessId(),
|
| + impl_->render_frame_id_,
|
| + ssl_info,
|
| + fatal);
|
| // The above method is always asynchronous.
|
| return WebSocketEventInterface::CHANNEL_ALIVE;
|
| }
|
|
|
| -WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| +WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| SSLErrorHandlerDelegate(
|
| std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
|
| callbacks)
|
| : callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {}
|
|
|
| -WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| +WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| ~SSLErrorHandlerDelegate() {}
|
|
|
| base::WeakPtr<SSLErrorHandler::Delegate>
|
| -WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
|
| +WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
|
| return weak_ptr_factory_.GetWeakPtr();
|
| }
|
|
|
| -void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| +void WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| CancelSSLRequest(int error, const net::SSLInfo* ssl_info) {
|
| DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
|
| << " error=" << error
|
| @@ -355,54 +367,51 @@ void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| callbacks_->CancelSSLRequest(error, ssl_info);
|
| }
|
|
|
| -void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| +void WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
|
| ContinueSSLRequest() {
|
| DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
|
| callbacks_->ContinueSSLRequest();
|
| }
|
|
|
| -WebSocketHost::WebSocketHost(int routing_id,
|
| - WebSocketDispatcherHost* dispatcher,
|
| - net::URLRequestContext* url_request_context,
|
| - base::TimeDelta delay)
|
| - : dispatcher_(dispatcher),
|
| - url_request_context_(url_request_context),
|
| - routing_id_(routing_id),
|
| +WebSocketImpl::WebSocketImpl(
|
| + Delegate* delegate,
|
| + mojom::WebSocketRequest request,
|
| + int render_frame_id,
|
| + base::TimeDelta delay)
|
| + : delegate_(delegate),
|
| + binding_(this, std::move(request)),
|
| + render_frame_id_(render_frame_id),
|
| delay_(delay),
|
| pending_flow_control_quota_(0),
|
| handshake_succeeded_(false),
|
| weak_ptr_factory_(this) {
|
| - DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
|
| + binding_.set_connection_error_handler(
|
| + base::Bind(&WebSocketImpl::OnConnectionError, base::Unretained(this)));
|
| }
|
|
|
| -WebSocketHost::~WebSocketHost() {}
|
| +WebSocketImpl::~WebSocketImpl() {}
|
|
|
| -void WebSocketHost::GoAway() {
|
| - OnDropChannel(false, static_cast<uint16_t>(net::kWebSocketErrorGoingAway),
|
| - "");
|
| +void WebSocketImpl::GoAway() {
|
| + StartClosingHandshake(static_cast<uint16_t>(net::kWebSocketErrorGoingAway),
|
| + "");
|
| }
|
|
|
| -bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
|
| - bool handled = true;
|
| - IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
|
| - IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
|
| - IPC_MESSAGE_HANDLER(WebSocketHostMsg_SendBlob, OnSendBlob)
|
| - IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
|
| - IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
|
| - IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| - return handled;
|
| +void WebSocketImpl::Initialize(mojom::WebSocketClientPtr client) {
|
| + client_ = std::move(client);
|
| }
|
|
|
| -void WebSocketHost::OnAddChannelRequest(
|
| +void WebSocketImpl::AddChannelRequest(
|
| const GURL& socket_url,
|
| - const std::vector<std::string>& requested_protocols,
|
| - const url::Origin& origin,
|
| - int render_frame_id) {
|
| - DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
|
| - << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
|
| - << "\" requested_protocols=\""
|
| + mojo::Array<mojo::String> requested_protocols_mojo,
|
| + const url::Origin& origin) {
|
| + // Convert to STL types.
|
| + std::vector<std::string> requested_protocols(
|
| + requested_protocols_mojo.begin(),
|
| + requested_protocols_mojo.end());
|
| +
|
| + DVLOG(3) << "WebSocketImpl::AddChannelRequest @"
|
| + << reinterpret_cast<void*>(this)
|
| + << " socket_url=\"" << socket_url << "\" requested_protocols=\""
|
| << base::JoinString(requested_protocols, ", ") << "\" origin=\""
|
| << origin << "\"";
|
|
|
| @@ -410,68 +419,33 @@ void WebSocketHost::OnAddChannelRequest(
|
| if (delay_ > base::TimeDelta()) {
|
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| FROM_HERE,
|
| - base::Bind(&WebSocketHost::AddChannel, weak_ptr_factory_.GetWeakPtr(),
|
| - socket_url, requested_protocols, origin, render_frame_id),
|
| + base::Bind(&WebSocketImpl::AddChannel,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + socket_url,
|
| + requested_protocols,
|
| + origin),
|
| delay_);
|
| } else {
|
| - AddChannel(socket_url, requested_protocols, origin, render_frame_id);
|
| - }
|
| - // |this| may have been deleted here.
|
| -}
|
| -
|
| -void WebSocketHost::AddChannel(
|
| - const GURL& socket_url,
|
| - const std::vector<std::string>& requested_protocols,
|
| - const url::Origin& origin,
|
| - int render_frame_id) {
|
| - DVLOG(3) << "WebSocketHost::AddChannel"
|
| - << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
|
| - << "\" requested_protocols=\""
|
| - << base::JoinString(requested_protocols, ", ") << "\" origin=\""
|
| - << origin << "\"";
|
| -
|
| - DCHECK(!channel_);
|
| -
|
| - std::unique_ptr<net::WebSocketEventInterface> event_interface(
|
| - new WebSocketEventHandler(dispatcher_, this, routing_id_,
|
| - render_frame_id));
|
| - channel_.reset(new net::WebSocketChannel(std::move(event_interface),
|
| - url_request_context_));
|
| -
|
| - if (pending_flow_control_quota_ > 0) {
|
| - // channel_->SendFlowControl(pending_flow_control_quota_) must be called
|
| - // after channel_->SendAddChannelRequest() below.
|
| - // We post OnFlowControl() here using |weak_ptr_factory_| instead of
|
| - // calling SendFlowControl directly, because |this| may have been deleted
|
| - // after channel_->SendAddChannelRequest().
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE, base::Bind(&WebSocketHost::OnFlowControl,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - pending_flow_control_quota_));
|
| - pending_flow_control_quota_ = 0;
|
| + AddChannel(socket_url, requested_protocols, origin);
|
| }
|
| -
|
| - channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
|
| - // |this| may have been deleted here.
|
| }
|
|
|
| -void WebSocketHost::OnSendBlob(const std::string& uuid,
|
| - uint64_t expected_size) {
|
| - DVLOG(3) << "WebSocketHost::OnSendBlob"
|
| - << " routing_id=" << routing_id_ << " uuid=" << uuid
|
| +void WebSocketImpl::SendBlob(const mojo::String& uuid, uint64_t expected_size) {
|
| + DVLOG(3) << "WebSocketImpl::OnSendBlob @"
|
| + << reinterpret_cast<void*>(this) << " uuid=" << uuid
|
| << " expected_size=" << expected_size;
|
|
|
| DCHECK(channel_);
|
| if (blob_sender_) {
|
| bad_message::ReceivedBadMessage(
|
| - dispatcher_, bad_message::WSH_SEND_BLOB_DURING_BLOB_SEND);
|
| + delegate_->GetClientProcessId(),
|
| + bad_message::WSI_SEND_BLOB_DURING_BLOB_SEND);
|
| return;
|
| }
|
| blob_sender_.reset(new WebSocketBlobSender(
|
| base::WrapUnique(new SendChannelImpl(channel_.get()))));
|
| - StoragePartition* partition = dispatcher_->storage_partition();
|
| storage::FileSystemContext* file_system_context =
|
| - partition->GetFileSystemContext();
|
| + delegate_->GetStoragePartition()->GetFileSystemContext();
|
|
|
| net::WebSocketEventInterface::ChannelState channel_state =
|
| net::WebSocketEventInterface::CHANNEL_ALIVE;
|
| @@ -479,36 +453,42 @@ void WebSocketHost::OnSendBlob(const std::string& uuid,
|
| // This use of base::Unretained is safe because the WebSocketBlobSender object
|
| // is owned by this object and will not call it back after destruction.
|
| int rv = blob_sender_->Start(
|
| - uuid, expected_size, dispatcher_->blob_storage_context(),
|
| + uuid,
|
| + expected_size,
|
| + delegate_->GetBlobStorageContext(),
|
| file_system_context,
|
| BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
|
| &channel_state,
|
| - base::Bind(&WebSocketHost::BlobSendComplete, base::Unretained(this)));
|
| + base::Bind(&WebSocketImpl::BlobSendComplete, base::Unretained(this)));
|
| if (channel_state == net::WebSocketEventInterface::CHANNEL_ALIVE &&
|
| rv != net::ERR_IO_PENDING)
|
| BlobSendComplete(rv);
|
| - // |this| may be destroyed here.
|
| }
|
|
|
| -void WebSocketHost::OnSendFrame(bool fin,
|
| - WebSocketMessageType type,
|
| - const std::vector<char>& data) {
|
| - DVLOG(3) << "WebSocketHost::OnSendFrame"
|
| - << " routing_id=" << routing_id_ << " fin=" << fin
|
| +void WebSocketImpl::SendFrame(bool fin, mojom::WebSocketMessageType type,
|
| + mojo::Array<uint8_t> data) {
|
| + DVLOG(3) << "WebSocketImpl::OnSendFrame @"
|
| + << reinterpret_cast<void*>(this) << " fin=" << fin
|
| << " type=" << type << " data is " << data.size() << " bytes";
|
|
|
| DCHECK(channel_);
|
| if (blob_sender_) {
|
| bad_message::ReceivedBadMessage(
|
| - dispatcher_, bad_message::WSH_SEND_FRAME_DURING_BLOB_SEND);
|
| + delegate_->GetClientProcessId(),
|
| + bad_message::WSI_SEND_FRAME_DURING_BLOB_SEND);
|
| return;
|
| }
|
| - channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
|
| +
|
| + // TODO(darin): Avoid this copy.
|
| + std::vector<char> data_to_pass(data.size());
|
| + memcpy(&data_to_pass[0], &data[0], data.size());
|
| +
|
| + channel_->SendFrame(fin, MessageTypeToOpCode(type), data_to_pass);
|
| }
|
|
|
| -void WebSocketHost::OnFlowControl(int64_t quota) {
|
| - DVLOG(3) << "WebSocketHost::OnFlowControl"
|
| - << " routing_id=" << routing_id_ << " quota=" << quota;
|
| +void WebSocketImpl::SendFlowControl(int64_t quota) {
|
| + DVLOG(3) << "WebSocketImpl::OnFlowControl @"
|
| + << reinterpret_cast<void*>(this) << " quota=" << quota;
|
|
|
| if (!channel_) {
|
| // WebSocketChannel is not yet created due to the delay introduced by
|
| @@ -521,20 +501,26 @@ void WebSocketHost::OnFlowControl(int64_t quota) {
|
| ignore_result(channel_->SendFlowControl(quota));
|
| }
|
|
|
| -void WebSocketHost::OnDropChannel(bool was_clean,
|
| - uint16_t code,
|
| - const std::string& reason) {
|
| - DVLOG(3) << "WebSocketHost::OnDropChannel"
|
| - << " routing_id=" << routing_id_ << " was_clean=" << was_clean
|
| +void WebSocketImpl::StartClosingHandshake(uint16_t code,
|
| + const mojo::String& reason) {
|
| + DVLOG(3) << "WebSocketImpl::StartClosingHandshake @"
|
| + << reinterpret_cast<void*>(this)
|
| << " code=" << code << " reason=\"" << reason << "\"";
|
|
|
| if (!channel_) {
|
| // WebSocketChannel is not yet created due to the delay introduced by
|
| // per-renderer WebSocket throttling.
|
| +#if 0
|
| WebSocketDispatcherHost::WebSocketHostState result =
|
| dispatcher_->DoDropChannel(routing_id_, false,
|
| net::kWebSocketErrorAbnormalClosure, "");
|
| DCHECK_EQ(WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED, result);
|
| +#endif
|
| + client_->OnDropChannel(false, net::kWebSocketErrorAbnormalClosure, "");
|
| +
|
| + // XXX need to break connection
|
| + // XXX -- No, we will observe the client dropping the connection
|
| +
|
| return;
|
| }
|
|
|
| @@ -543,9 +529,53 @@ void WebSocketHost::OnDropChannel(bool was_clean,
|
| ignore_result(channel_->StartClosingHandshake(code, reason));
|
| }
|
|
|
| -void WebSocketHost::BlobSendComplete(int result) {
|
| - DVLOG(3) << "WebSocketHost::BlobSendComplete"
|
| - << " routing_id=" << routing_id_
|
| +void WebSocketImpl::OnConnectionError() {
|
| + delegate_->OnLostConnectionToClient(this);
|
| +}
|
| +
|
| +void WebSocketImpl::AddChannel(
|
| + const GURL& socket_url,
|
| + const std::vector<std::string>& requested_protocols,
|
| + const url::Origin& origin) {
|
| + DVLOG(3) << "WebSocketImpl::AddChannel @"
|
| + << reinterpret_cast<void*>(this)
|
| + << " socket_url=\"" << socket_url
|
| + << "\" requested_protocols=\""
|
| + << base::JoinString(requested_protocols, ", ") << "\" origin=\""
|
| + << origin << "\"";
|
| +
|
| + DCHECK(!channel_);
|
| +
|
| + StoragePartition* partition = delegate_->GetStoragePartition();
|
| +
|
| + std::unique_ptr<net::WebSocketEventInterface> event_interface(
|
| + new WebSocketEventHandler(this));
|
| + channel_.reset(
|
| + new net::WebSocketChannel(
|
| + std::move(event_interface),
|
| + partition->GetURLRequestContext()->GetURLRequestContext()));
|
| +
|
| + if (pending_flow_control_quota_ > 0) {
|
| + // channel_->SendFlowControl(pending_flow_control_quota_) must be called
|
| + // after channel_->SendAddChannelRequest() below.
|
| + // We post SendFlowControl() here using |weak_ptr_factory_| instead of
|
| + // calling SendFlowControl directly, because |this| may have been deleted
|
| + // after channel_->SendAddChannelRequest().
|
| + // XXX we should be able to call this after SendAddChannelRequest now
|
| + // as connection errors are observed asynchronously.
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE, base::Bind(&WebSocketImpl::SendFlowControl,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + pending_flow_control_quota_));
|
| + pending_flow_control_quota_ = 0;
|
| + }
|
| +
|
| + channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
|
| +}
|
| +
|
| +void WebSocketImpl::BlobSendComplete(int result) {
|
| + DVLOG(3) << "WebSocketImpl::BlobSendComplete @"
|
| + << reinterpret_cast<void*>(this)
|
| << " result=" << net::ErrorToString(result);
|
|
|
| // All paths through this method must reset blob_sender_, so take ownership
|
| @@ -553,29 +583,30 @@ void WebSocketHost::BlobSendComplete(int result) {
|
| std::unique_ptr<WebSocketBlobSender> blob_sender(std::move(blob_sender_));
|
| switch (result) {
|
| case net::OK:
|
| - ignore_result(dispatcher_->BlobSendComplete(routing_id_));
|
| - // |this| may be destroyed here.
|
| + client_->OnBlobSent();
|
| return;
|
|
|
| case net::ERR_UPLOAD_FILE_CHANGED: {
|
| uint64_t expected_size = blob_sender->expected_size();
|
| uint64_t actual_size = blob_sender->ActualSize();
|
| if (expected_size != actual_size) {
|
| - ignore_result(dispatcher_->NotifyFailure(
|
| - routing_id_,
|
| + // XXX ignore_result(dispatcher_->NotifyFailure(
|
| + // XXX routing_id_,
|
| + client_->OnFailChannel(
|
| base::StringPrintf("Blob size mismatch; renderer size = %" PRIu64
|
| ", browser size = %" PRIu64,
|
| - expected_size, actual_size)));
|
| - // |this| is destroyed here.
|
| + expected_size, actual_size));
|
| + // XXX |this| is destroyed here.
|
| return;
|
| } // else fallthrough
|
| }
|
|
|
| default:
|
| - ignore_result(dispatcher_->NotifyFailure(
|
| - routing_id_,
|
| - "Failed to load Blob: error code = " + net::ErrorToString(result)));
|
| - // |this| is destroyed here.
|
| + // XXX ignore_result(dispatcher_->NotifyFailure(
|
| + // XXX routing_id_,
|
| + client_->OnFailChannel(
|
| + "Failed to load Blob: error code = " + net::ErrorToString(result));
|
| + // XXX |this| is destroyed here.
|
| return;
|
| }
|
| }
|
|
|