Commit 7a387c65 authored by Yutaka Hirano's avatar Yutaka Hirano Committed by Commit Bot

[WebSocket] Bind WebSocketClient when connection is established

In order to deal with mojo message ordering uncertainty between
WebSocketHandshakeClient and WebSocketClient, this CL has
WebSocketHandleImpl::binding_as_client_ binds when
OnConnectionEstablished is called.

mojom.WebSocketClient.OnFailChannel is replaced with
InterfacePtr::ResetWithReason because |client_| may not be available
when network::WebSocket::WebSocketEventHandler::OnFailChannel is called.

Bug: 989406, 967524
Change-Id: Ic14357133a85317a07271a3615a21ff3e61fe37d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1728917Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarAdam Rice <ricea@chromium.org>
Reviewed-by: default avatarYoichi Osato <yoichio@chromium.org>
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683477}
parent b07ed514
...@@ -378,9 +378,9 @@ void WebRequestProxyingWebSocket::ContinueToStartRequest(int error_code) { ...@@ -378,9 +378,9 @@ void WebRequestProxyingWebSocket::ContinueToStartRequest(int error_code) {
// best. // best.
network::mojom::WebSocketHandshakeClientPtr handshake_client; network::mojom::WebSocketHandshakeClientPtr handshake_client;
binding_as_handshake_client_.Bind(mojo::MakeRequest(&handshake_client)); binding_as_handshake_client_.Bind(mojo::MakeRequest(&handshake_client));
binding_as_handshake_client_.set_connection_error_handler( binding_as_handshake_client_.set_connection_error_with_reason_handler(
base::BindOnce(&WebRequestProxyingWebSocket::OnError, base::BindOnce(&WebRequestProxyingWebSocket::OnMojoConnectionError,
base::Unretained(this), net::ERR_FAILED)); base::Unretained(this)));
network::mojom::AuthenticationHandlerPtr auth_handler; network::mojom::AuthenticationHandlerPtr auth_handler;
binding_as_auth_handler_.Bind(mojo::MakeRequest(&auth_handler)); binding_as_auth_handler_.Bind(mojo::MakeRequest(&auth_handler));
network::mojom::TrustedHeaderClientPtr trusted_header_client; network::mojom::TrustedHeaderClientPtr trusted_header_client;
...@@ -484,4 +484,12 @@ void WebRequestProxyingWebSocket::OnError(int error_code) { ...@@ -484,4 +484,12 @@ void WebRequestProxyingWebSocket::OnError(int error_code) {
proxies_->RemoveProxy(this); proxies_->RemoveProxy(this);
} }
void WebRequestProxyingWebSocket::OnMojoConnectionError(
uint32_t custom_reason,
const std::string& description) {
forwarding_handshake_client_.ResetWithReason(custom_reason, description);
OnError(net::ERR_FAILED);
// Deletes |this|.
}
} // namespace extensions } // namespace extensions
...@@ -107,6 +107,8 @@ class WebRequestProxyingWebSocket ...@@ -107,6 +107,8 @@ class WebRequestProxyingWebSocket
void PauseIncomingMethodCallProcessing(); void PauseIncomingMethodCallProcessing();
void ResumeIncomingMethodCallProcessing(); void ResumeIncomingMethodCallProcessing();
void OnError(int result); void OnError(int result);
void OnMojoConnectionError(uint32_t custom_reason,
const std::string& description);
WebSocketFactory factory_; WebSocketFactory factory_;
content::BrowserContext* const browser_context_; content::BrowserContext* const browser_context_;
......
...@@ -112,14 +112,13 @@ interface WebSocketClient { ...@@ -112,14 +112,13 @@ interface WebSocketClient {
// Notify the renderer that a closing handshake has been initiated by the // Notify the renderer that a closing handshake has been initiated by the
// server, so that it can set the Javascript readyState to CLOSING. // server, so that it can set the Javascript readyState to CLOSING.
OnClosingHandshake(); OnClosingHandshake();
OnFailChannel(string reason);
}; };
interface WebSocket { interface WebSocket {
// The client side may observe the following disconnection reason from the // The client side may observe the following disconnection reason from the
// service side: // service side:
const uint32 kInsufficientResources = 1; const uint32 kInsufficientResources = 1;
const uint32 kInternalFailure = 2;
// Send a non-control frame to the remote server. // Send a non-control frame to the remote server.
// - |fin| indicates that this frame is the last in the current message. // - |fin| indicates that this frame is the last in the current message.
......
...@@ -222,7 +222,9 @@ void WebSocket::WebSocketEventHandler::OnFailChannel( ...@@ -222,7 +222,9 @@ void WebSocket::WebSocketEventHandler::OnFailChannel(
DVLOG(3) << "WebSocketEventHandler::OnFailChannel @" DVLOG(3) << "WebSocketEventHandler::OnFailChannel @"
<< reinterpret_cast<void*>(this) << " message=\"" << message << "\""; << reinterpret_cast<void*>(this) << " message=\"" << message << "\"";
impl_->client_->OnFailChannel(message); impl_->handshake_client_.ResetWithReason(mojom::WebSocket::kInternalFailure,
message);
impl_->client_.ResetWithReason(mojom::WebSocket::kInternalFailure, message);
impl_->Reset(); impl_->Reset();
} }
......
...@@ -179,7 +179,8 @@ WebSocketChannelImpl* WebSocketChannelImpl::Create( ...@@ -179,7 +179,8 @@ WebSocketChannelImpl* WebSocketChannelImpl::Create(
std::unique_ptr<SourceLocation> location) { std::unique_ptr<SourceLocation> location) {
auto* channel = MakeGarbageCollected<WebSocketChannelImpl>( auto* channel = MakeGarbageCollected<WebSocketChannelImpl>(
execution_context, client, std::move(location), execution_context, client, std::move(location),
std::make_unique<WebSocketHandleImpl>()); std::make_unique<WebSocketHandleImpl>(
execution_context->GetTaskRunner(TaskType::kNetworking)));
channel->handshake_throttle_ = channel->handshake_throttle_ =
channel->GetBaseFetchContext()->CreateWebSocketHandshakeThrottle(); channel->GetBaseFetchContext()->CreateWebSocketHandshakeThrottle();
return channel; return channel;
...@@ -260,11 +261,9 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) { ...@@ -260,11 +261,9 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) {
// a mojo connection error. // a mojo connection error.
mojo::MakeRequest(&connector); mojo::MakeRequest(&connector);
} }
handle_->Connect( handle_->Connect(std::move(connector), url, protocols,
std::move(connector), url, protocols, GetBaseFetchContext()->GetSiteForCookies(),
GetBaseFetchContext()->GetSiteForCookies(), execution_context_->UserAgent(), this);
execution_context_->UserAgent(), this,
execution_context_->GetTaskRunner(TaskType::kNetworking).get());
if (handshake_throttle_) { if (handshake_throttle_) {
// The use of WrapWeakPersistent is safe and motivated by the fact that if // The use of WrapWeakPersistent is safe and motivated by the fact that if
......
...@@ -92,8 +92,7 @@ class MockWebSocketHandle : public WebSocketHandle { ...@@ -92,8 +92,7 @@ class MockWebSocketHandle : public WebSocketHandle {
const Vector<String>& protocols, const Vector<String>& protocols,
const KURL& site_for_cookies, const KURL& site_for_cookies,
const String& user_agent_override, const String& user_agent_override,
WebSocketChannelImpl* channel, WebSocketChannelImpl* channel) override {
base::SingleThreadTaskRunner*) override {
Connect(url, protocols, site_for_cookies, user_agent_override, channel); Connect(url, protocols, site_for_cookies, user_agent_override, channel);
} }
MOCK_METHOD5(Connect, MOCK_METHOD5(Connect,
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WEBSOCKET_HANDLE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WEBSOCKET_HANDLE_H_
#include <stdint.h> #include <stdint.h>
#include "base/single_thread_task_runner.h"
#include "services/network/public/mojom/websocket.mojom-blink.h" #include "services/network/public/mojom/websocket.mojom-blink.h"
#include "third_party/blink/public/mojom/websockets/websocket_connector.mojom-blink.h" #include "third_party/blink/public/mojom/websockets/websocket_connector.mojom-blink.h"
#include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
...@@ -66,8 +65,7 @@ class WebSocketHandle { ...@@ -66,8 +65,7 @@ class WebSocketHandle {
const Vector<String>& protocols, const Vector<String>& protocols,
const KURL& site_for_cookies, const KURL& site_for_cookies,
const String& user_agent_override, const String& user_agent_override,
WebSocketChannelImpl*, WebSocketChannelImpl*) = 0;
base::SingleThreadTaskRunner*) = 0;
virtual void Send(bool fin, MessageType, const char* data, wtf_size_t) = 0; virtual void Send(bool fin, MessageType, const char* data, wtf_size_t) = 0;
virtual void AddReceiveFlowControlQuota(int64_t quota) = 0; virtual void AddReceiveFlowControlQuota(int64_t quota) = 0;
virtual void Close(uint16_t code, const String& reason) = 0; virtual void Close(uint16_t code, const String& reason) = 0;
......
...@@ -21,8 +21,10 @@ const uint16_t kAbnormalShutdownOpCode = 1006; ...@@ -21,8 +21,10 @@ const uint16_t kAbnormalShutdownOpCode = 1006;
} // namespace } // namespace
WebSocketHandleImpl::WebSocketHandleImpl() WebSocketHandleImpl::WebSocketHandleImpl(
: channel_(nullptr), scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(std::move(task_runner)),
channel_(nullptr),
handshake_client_binding_(this), handshake_client_binding_(this),
client_binding_(this) { client_binding_(this) {
NETWORK_DVLOG(1) << this << " created"; NETWORK_DVLOG(1) << this << " created";
...@@ -40,25 +42,21 @@ void WebSocketHandleImpl::Connect(mojom::blink::WebSocketConnectorPtr connector, ...@@ -40,25 +42,21 @@ void WebSocketHandleImpl::Connect(mojom::blink::WebSocketConnectorPtr connector,
const Vector<String>& protocols, const Vector<String>& protocols,
const KURL& site_for_cookies, const KURL& site_for_cookies,
const String& user_agent_override, const String& user_agent_override,
WebSocketChannelImpl* channel, WebSocketChannelImpl* channel) {
base::SingleThreadTaskRunner* task_runner) {
NETWORK_DVLOG(1) << this << " connect(" << url.GetString() << ")"; NETWORK_DVLOG(1) << this << " connect(" << url.GetString() << ")";
DCHECK(!channel_); DCHECK(!channel_);
DCHECK(channel); DCHECK(channel);
channel_ = channel; channel_ = channel;
// Here we detect mojo connection errors on |client_binding_|. See also
// CreateWebSocket in //network/services/public/mojom/network_context.mojom.
network::mojom::blink::WebSocketHandshakeClientPtr handshake_client_proxy;
Vector<network::mojom::blink::HttpHeaderPtr> additional_headers; Vector<network::mojom::blink::HttpHeaderPtr> additional_headers;
network::mojom::blink::WebSocketHandshakeClientPtr handshake_client_proxy;
handshake_client_binding_.Bind( handshake_client_binding_.Bind(
mojo::MakeRequest(&handshake_client_proxy, task_runner), task_runner); mojo::MakeRequest(&handshake_client_proxy, task_runner_), task_runner_);
network::mojom::blink::WebSocketClientPtr client_proxy; handshake_client_binding_.set_connection_error_with_reason_handler(WTF::Bind(
client_binding_.Bind(mojo::MakeRequest(&client_proxy, task_runner),
task_runner);
client_binding_.set_connection_error_with_reason_handler(WTF::Bind(
&WebSocketHandleImpl::OnConnectionError, WTF::Unretained(this))); &WebSocketHandleImpl::OnConnectionError, WTF::Unretained(this)));
network::mojom::blink::WebSocketClientPtr client_proxy;
pending_client_receiver_ = mojo::MakeRequest(&client_proxy);
connector->Connect(url, protocols, site_for_cookies, user_agent_override, connector->Connect(url, protocols, site_for_cookies, user_agent_override,
std::move(handshake_client_proxy), std::move(handshake_client_proxy),
...@@ -121,19 +119,12 @@ void WebSocketHandleImpl::Disconnect() { ...@@ -121,19 +119,12 @@ void WebSocketHandleImpl::Disconnect() {
void WebSocketHandleImpl::OnConnectionError(uint32_t custom_reason, void WebSocketHandleImpl::OnConnectionError(uint32_t custom_reason,
const std::string& description) { const std::string& description) {
// Our connection to the WebSocket was dropped. This could be due to
// exceeding the maximum number of concurrent websockets from this process.
// This handler is sufficient to detect all mojo connection errors, as
// any error will result in the data connection being dropped.
// By detecting the errors on this channel, we ensure that any FailChannel
// messages from the network service will be processed first.
NETWORK_DVLOG(1) << " OnConnectionError( reason: " << custom_reason NETWORK_DVLOG(1) << " OnConnectionError( reason: " << custom_reason
<< ", description:" << description; << ", description:" << description;
OnFailChannel("Unknown reason"); String message = "Unknown reason";
} if (custom_reason == network::mojom::blink::WebSocket::kInternalFailure) {
message = String::FromUTF8(description.c_str(), description.size());
void WebSocketHandleImpl::OnFailChannel(const String& message) { }
NETWORK_DVLOG(1) << this << " OnFailChannel(" << message << ")";
WebSocketChannelImpl* channel = channel_; WebSocketChannelImpl* channel = channel_;
Disconnect(); Disconnect();
...@@ -169,6 +160,12 @@ void WebSocketHandleImpl::OnConnectionEstablished( ...@@ -169,6 +160,12 @@ void WebSocketHandleImpl::OnConnectionEstablished(
if (!channel_) if (!channel_)
return; return;
// From now on, we will detect mojo errors via |client_binding_|.
handshake_client_binding_.Close();
client_binding_.Bind(std::move(pending_client_receiver_), task_runner_);
client_binding_.set_connection_error_with_reason_handler(WTF::Bind(
&WebSocketHandleImpl::OnConnectionError, WTF::Unretained(this)));
DCHECK(!websocket_); DCHECK(!websocket_);
websocket_ = std::move(websocket); websocket_ = std::move(websocket);
channel_->DidConnect(this, protocol, extensions, receive_quota_threshold); channel_->DidConnect(this, protocol, extensions, receive_quota_threshold);
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace blink { namespace blink {
class WebSocketHandleImpl class WebSocketHandleImpl
...@@ -45,7 +49,7 @@ class WebSocketHandleImpl ...@@ -45,7 +49,7 @@ class WebSocketHandleImpl
public network::mojom::blink::WebSocketHandshakeClient, public network::mojom::blink::WebSocketHandshakeClient,
public network::mojom::blink::WebSocketClient { public network::mojom::blink::WebSocketClient {
public: public:
WebSocketHandleImpl(); explicit WebSocketHandleImpl(scoped_refptr<base::SingleThreadTaskRunner>);
~WebSocketHandleImpl() override; ~WebSocketHandleImpl() override;
void Connect(mojom::blink::WebSocketConnectorPtr, void Connect(mojom::blink::WebSocketConnectorPtr,
...@@ -53,8 +57,7 @@ class WebSocketHandleImpl ...@@ -53,8 +57,7 @@ class WebSocketHandleImpl
const Vector<String>& protocols, const Vector<String>& protocols,
const KURL& site_for_cookies, const KURL& site_for_cookies,
const String& user_agent_override, const String& user_agent_override,
WebSocketChannelImpl*, WebSocketChannelImpl*) override;
base::SingleThreadTaskRunner*) override;
void Send(bool fin, MessageType, const char* data, wtf_size_t) override; void Send(bool fin, MessageType, const char* data, wtf_size_t) override;
void AddReceiveFlowControlQuota(int64_t quota) override; void AddReceiveFlowControlQuota(int64_t quota) override;
void Close(uint16_t code, const String& reason) override; void Close(uint16_t code, const String& reason) override;
...@@ -82,11 +85,12 @@ class WebSocketHandleImpl ...@@ -82,11 +85,12 @@ class WebSocketHandleImpl
uint16_t code, uint16_t code,
const String& reason) override; const String& reason) override;
void OnClosingHandshake() override; void OnClosingHandshake() override;
void OnFailChannel(const String& reason) override;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
WeakPersistent<WebSocketChannelImpl> channel_; WeakPersistent<WebSocketChannelImpl> channel_;
network::mojom::blink::WebSocketPtr websocket_; network::mojom::blink::WebSocketPtr websocket_;
network::mojom::blink::WebSocketClientRequest pending_client_receiver_;
mojo::Binding<network::mojom::blink::WebSocketHandshakeClient> mojo::Binding<network::mojom::blink::WebSocketHandshakeClient>
handshake_client_binding_; handshake_client_binding_;
mojo::Binding<network::mojom::blink::WebSocketClient> client_binding_; mojo::Binding<network::mojom::blink::WebSocketClient> client_binding_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment