Skip to content

Commit

Permalink
Direct Sockets: Detect when render frame is deleted
Browse files Browse the repository at this point in the history
DirectSocketsServiceImpl is now a WebContentsObserver.

OpenTcpSocket() and OpenUdpSocket() now fail safely if they are called
after the RenderFrameHost is destroyed.


Bug: 1122917
Change-Id: I4a880c9aee73271cd5895818e0da3d85e32a8e5b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2383531
Auto-Submit: Eric Willigers <ericwilligers@chromium.org>
Commit-Queue: Glen Robertson <glenrob@chromium.org>
Reviewed-by: Glen Robertson <glenrob@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803005}
  • Loading branch information
ericwilligers authored and Commit Bot committed Aug 31, 2020
1 parent 0eb482f commit fe9666e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 3 deletions.
17 changes: 16 additions & 1 deletion content/browser/direct_sockets/direct_sockets_service_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "base/optional.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"

Expand All @@ -28,7 +29,8 @@ GetPermissionCallbackForTesting() {
} // namespace

DirectSocketsServiceImpl::DirectSocketsServiceImpl(RenderFrameHost& frame_host)
: frame_host_(&frame_host) {}
: WebContentsObserver(WebContents::FromRenderFrameHost(&frame_host)),
frame_host_(&frame_host) {}

// static
void DirectSocketsServiceImpl::CreateForFrame(
Expand Down Expand Up @@ -86,10 +88,23 @@ void DirectSocketsServiceImpl::SetPermissionCallbackForTesting(
GetPermissionCallbackForTesting() = std::move(callback);
}

void DirectSocketsServiceImpl::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
if (render_frame_host == frame_host_)
frame_host_ = nullptr;
}

void DirectSocketsServiceImpl::WebContentsDestroyed() {
frame_host_ = nullptr;
}

net::Error DirectSocketsServiceImpl::EnsurePermission(
const blink::mojom::DirectSocketOptions& options) {
DCHECK(base::FeatureList::IsEnabled(features::kDirectSockets));

if (!frame_host_)
return net::ERR_CONTEXT_SHUT_DOWN;

if (GetPermissionCallbackForTesting())
return GetPermissionCallbackForTesting().Run(options);

Expand Down
12 changes: 10 additions & 2 deletions content/browser/direct_sockets/direct_sockets_service_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/callback.h"
#include "content/common/content_export.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"
Expand All @@ -24,7 +25,8 @@ namespace content {

// Implementation of the DirectSocketsService Mojo service.
class CONTENT_EXPORT DirectSocketsServiceImpl
: public blink::mojom::DirectSocketsService {
: public blink::mojom::DirectSocketsService,
public WebContentsObserver {
public:
using PermissionCallback = base::RepeatingCallback<net::Error(
const blink::mojom::DirectSocketOptions&)>;
Expand All @@ -45,14 +47,20 @@ class CONTENT_EXPORT DirectSocketsServiceImpl
void OpenUdpSocket(blink::mojom::DirectSocketOptionsPtr options,
OpenUdpSocketCallback callback) override;

// WebContentsObserver override:
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
void WebContentsDestroyed() override;

static void SetPermissionCallbackForTesting(PermissionCallback callback);

private:
friend class DirectSocketsUnitTest;

net::Error EnsurePermission(const blink::mojom::DirectSocketOptions& options);

network::mojom::NetworkContext* GetNetworkContext();

RenderFrameHost* const frame_host_;
RenderFrameHost* frame_host_;
};

} // namespace content
Expand Down
57 changes: 57 additions & 0 deletions content/browser/direct_sockets/direct_sockets_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>

#include "base/test/scoped_feature_list.h"
#include "content/browser/direct_sockets/direct_sockets_service_impl.h"
#include "content/public/common/content_features.h"
#include "content/public/test/test_renderer_host.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"

namespace content {

class DirectSocketsUnitTest : public RenderViewHostTestHarness {
public:
DirectSocketsUnitTest() {
feature_list_.InitAndEnableFeature(features::kDirectSockets);
}
~DirectSocketsUnitTest() override = default;

void SetUp() override {
RenderViewHostTestHarness::SetUp();
direct_sockets_service_ =
std::make_unique<DirectSocketsServiceImpl>(*main_rfh());
}

DirectSocketsServiceImpl& direct_sockets_service() {
return *direct_sockets_service_;
}

net::Error EnsurePermission(
const blink::mojom::DirectSocketOptions& options) {
return direct_sockets_service().EnsurePermission(options);
}

private:
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<DirectSocketsServiceImpl> direct_sockets_service_;
};

TEST_F(DirectSocketsUnitTest, RenderFrameDeleted) {
direct_sockets_service().RenderFrameDeleted(main_rfh());

blink::mojom::DirectSocketOptions options;
EXPECT_EQ(EnsurePermission(options), net::ERR_CONTEXT_SHUT_DOWN);
}

TEST_F(DirectSocketsUnitTest, WebContentsDestroyed) {
direct_sockets_service().WebContentsDestroyed();

blink::mojom::DirectSocketOptions options;
EXPECT_EQ(EnsurePermission(options), net::ERR_CONTEXT_SHUT_DOWN);
}

} // namespace content
1 change: 1 addition & 0 deletions content/test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2372,6 +2372,7 @@ test("content_unittests") {
# Non-Android.
sources += [
"../browser/devtools/protocol/webauthn_handler_unittest.cc",
"../browser/direct_sockets/direct_sockets_unittest.cc",
"../browser/host_zoom_map_impl_unittest.cc",
"../browser/serial/serial_unittest.cc",
"../browser/speech/chunked_byte_buffer_unittest.cc",
Expand Down

0 comments on commit fe9666e

Please sign in to comment.