Commit 5a3788ee authored by Minoru Chikamune's avatar Minoru Chikamune Committed by Commit Bot

Add a mode which doesn't reset the mojo connection when the associated...

Add a mode which doesn't reset the mojo connection when the associated ExecutionContext is detached.

If the original code doesn't have `ContextDestroyed()`, then HeapMojoWrapperMode::kWithoutContextObserver should be used.

Bug: 1058076
Change-Id: I6ea02f1b663b968d70e7b3b475ce40f183592f57
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2114020Reviewed-by: default avatarKeishi Hattori <keishi@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Commit-Queue: Minoru Chikamune <chikamune@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753122}
parent 772d2084
...@@ -1230,6 +1230,7 @@ jumbo_component("platform") { ...@@ -1230,6 +1230,7 @@ jumbo_component("platform") {
"mojo/heap_mojo_receiver_set.h", "mojo/heap_mojo_receiver_set.h",
"mojo/heap_mojo_remote.h", "mojo/heap_mojo_remote.h",
"mojo/heap_mojo_unique_receiver_set.h", "mojo/heap_mojo_unique_receiver_set.h",
"mojo/heap_mojo_wrapper_mode.h",
"mojo/kurl_mojom_traits.h", "mojo/kurl_mojom_traits.h",
"mojo/mojo_helper.h", "mojo/mojo_helper.h",
"mojo/security_origin_mojom_traits.h", "mojo/security_origin_mojom_traits.h",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/renderer/platform/context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
...@@ -17,7 +18,11 @@ namespace blink { ...@@ -17,7 +18,11 @@ namespace blink {
// HeapMojoReceiver's constructor takes context as a mandatory parameter. // HeapMojoReceiver's constructor takes context as a mandatory parameter.
// HeapMojoReceiver resets the mojo connection when 1) the owner object is // HeapMojoReceiver resets the mojo connection when 1) the owner object is
// garbage-collected and 2) the associated ExecutionContext is detached. // garbage-collected and 2) the associated ExecutionContext is detached.
template <typename Interface>
// TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
// that the interface is not used after ContextDestroyed().
template <typename Interface,
HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
class HeapMojoReceiver { class HeapMojoReceiver {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -72,7 +77,10 @@ class HeapMojoReceiver { ...@@ -72,7 +77,10 @@ class HeapMojoReceiver {
mojo::Receiver<Interface>& receiver() { return receiver_; } mojo::Receiver<Interface>& receiver() { return receiver_; }
// ContextLifecycleObserver methods // ContextLifecycleObserver methods
void ContextDestroyed() override { receiver_.reset(); } void ContextDestroyed() override {
if (Mode == HeapMojoWrapperMode::kWithContextObserver)
receiver_.reset();
}
private: private:
mojo::Receiver<Interface> receiver_; mojo::Receiver<Interface> receiver_;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/receiver_set.h"
#include "third_party/blink/renderer/platform/context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
...@@ -18,7 +19,11 @@ namespace blink { ...@@ -18,7 +19,11 @@ namespace blink {
// HeapMojoReceiverSet's constructor takes context as a mandatory parameter. // HeapMojoReceiverSet's constructor takes context as a mandatory parameter.
// HeapMojoReceiverSet resets the mojo connection when 1) the owner object is // HeapMojoReceiverSet resets the mojo connection when 1) the owner object is
// garbage-collected or 2) the associated ExecutionContext is detached. // garbage-collected or 2) the associated ExecutionContext is detached.
template <typename Interface>
// TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
// that the interface is not used after ContextDestroyed().
template <typename Interface,
HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
class HeapMojoReceiverSet { class HeapMojoReceiverSet {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -72,10 +77,13 @@ class HeapMojoReceiverSet { ...@@ -72,10 +77,13 @@ class HeapMojoReceiverSet {
mojo::ReceiverSet<Interface>& receiver_set() { return receiver_set_; } mojo::ReceiverSet<Interface>& receiver_set() { return receiver_set_; }
// ContextLifecycleObserver methods // ContextLifecycleObserver methods
void ContextDestroyed() override { receiver_set_.Clear(); } void ContextDestroyed() override {
if (Mode == HeapMojoWrapperMode::kWithContextObserver)
receiver_set_.Clear();
}
private: private:
::mojo::ReceiverSet<Interface> receiver_set_; mojo::ReceiverSet<Interface> receiver_set_;
}; };
Member<Wrapper> wrapper_; Member<Wrapper> wrapper_;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap_observer_list.h" #include "third_party/blink/renderer/platform/heap_observer_list.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
...@@ -60,47 +61,56 @@ class MockService : public sample::blink::Service { ...@@ -60,47 +61,56 @@ class MockService : public sample::blink::Service {
void GetPort(mojo::PendingReceiver<sample::blink::Port> receiver) override {} void GetPort(mojo::PendingReceiver<sample::blink::Port> receiver) override {}
}; };
class GCOwner : public GarbageCollected<GCOwner> { template <HeapMojoWrapperMode Mode>
class GCOwner : public GarbageCollected<GCOwner<Mode>> {
public: public:
explicit GCOwner(FakeContextNotifier* context) : receiver_set_(context) {} explicit GCOwner(FakeContextNotifier* context) : receiver_set_(context) {}
void Trace(Visitor* visitor) { visitor->Trace(receiver_set_); } void Trace(Visitor* visitor) { visitor->Trace(receiver_set_); }
HeapMojoReceiverSet<sample::blink::Service>& receiver_set() { HeapMojoReceiverSet<sample::blink::Service, Mode>& receiver_set() {
return receiver_set_; return receiver_set_;
} }
private: private:
HeapMojoReceiverSet<sample::blink::Service> receiver_set_; HeapMojoReceiverSet<sample::blink::Service, Mode> receiver_set_;
}; };
} // namespace template <HeapMojoWrapperMode Mode>
class HeapMojoReceiverSetGCBaseTest : public TestSupportingGC {
class HeapMojoReceiverSetTest : public TestSupportingGC {
public: public:
FakeContextNotifier* context() { return context_; } FakeContextNotifier* context() { return context_; }
scoped_refptr<base::NullTaskRunner> task_runner() { scoped_refptr<base::NullTaskRunner> task_runner() {
return null_task_runner_; return null_task_runner_;
} }
GCOwner* owner() { return owner_; } GCOwner<Mode>* owner() { return owner_; }
void ClearOwner() { owner_ = nullptr; } void ClearOwner() { owner_ = nullptr; }
protected: protected:
void SetUp() override { void SetUp() override {
context_ = MakeGarbageCollected<FakeContextNotifier>(); context_ = MakeGarbageCollected<FakeContextNotifier>();
owner_ = MakeGarbageCollected<GCOwner>(context()); owner_ = MakeGarbageCollected<GCOwner<Mode>>(context());
} }
void TearDown() override {} void TearDown() override {}
Persistent<FakeContextNotifier> context_; Persistent<FakeContextNotifier> context_;
Persistent<GCOwner> owner_; Persistent<GCOwner<Mode>> owner_;
scoped_refptr<base::NullTaskRunner> null_task_runner_ = scoped_refptr<base::NullTaskRunner> null_task_runner_ =
base::MakeRefCounted<base::NullTaskRunner>(); base::MakeRefCounted<base::NullTaskRunner>();
}; };
// GC the HeapMojoReceiverSet and verify that the receiver is no longer } // namespace
// part of the set, and that the service was deleted.
TEST_F(HeapMojoReceiverSetTest, RemovesReceiver) { class HeapMojoReceiverSetGCWithContextObserverTest
: public HeapMojoReceiverSetGCBaseTest<
HeapMojoWrapperMode::kWithContextObserver> {};
class HeapMojoReceiverSetGCWithoutContextObserverTest
: public HeapMojoReceiverSetGCBaseTest<
HeapMojoWrapperMode::kWithoutContextObserver> {};
// GC the HeapMojoReceiverSet with context observer and verify that the receiver
// is no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoReceiverSetGCWithContextObserverTest, RemovesReceiver) {
auto receiver_set = owner()->receiver_set(); auto receiver_set = owner()->receiver_set();
MockService service; MockService service;
auto receiver = mojo::PendingReceiver<sample::blink::Service>( auto receiver = mojo::PendingReceiver<sample::blink::Service>(
...@@ -115,7 +125,43 @@ TEST_F(HeapMojoReceiverSetTest, RemovesReceiver) { ...@@ -115,7 +125,43 @@ TEST_F(HeapMojoReceiverSetTest, RemovesReceiver) {
EXPECT_FALSE(receiver_set.HasReceiver(rid)); EXPECT_FALSE(receiver_set.HasReceiver(rid));
} }
TEST_F(HeapMojoReceiverSetTest, ClearLeavesSetEmpty) { // GC the HeapMojoReceiverSet without context observer and verify that the
// receiver is no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoReceiverSetGCWithoutContextObserverTest, RemovesReceiver) {
auto receiver_set = owner()->receiver_set();
MockService service;
auto receiver = mojo::PendingReceiver<sample::blink::Service>(
mojo::MessagePipe().handle0);
mojo::ReceiverId rid =
receiver_set.Add(&service, std::move(receiver), task_runner());
EXPECT_TRUE(receiver_set.HasReceiver(rid));
receiver_set.Remove(rid);
EXPECT_FALSE(receiver_set.HasReceiver(rid));
}
// GC the HeapMojoReceiverSet with context observer and verify that the receiver
// is no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoReceiverSetGCWithContextObserverTest, ClearLeavesSetEmpty) {
auto receiver_set = owner()->receiver_set();
MockService service;
auto receiver = mojo::PendingReceiver<sample::blink::Service>(
mojo::MessagePipe().handle0);
mojo::ReceiverId rid =
receiver_set.Add(&service, std::move(receiver), task_runner());
EXPECT_TRUE(receiver_set.HasReceiver(rid));
receiver_set.Clear();
EXPECT_FALSE(receiver_set.HasReceiver(rid));
}
// GC the HeapMojoReceiverSet without context observer and verify that the
// receiver is no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoReceiverSetGCWithoutContextObserverTest, ClearLeavesSetEmpty) {
auto receiver_set = owner()->receiver_set(); auto receiver_set = owner()->receiver_set();
MockService service; MockService service;
auto receiver = mojo::PendingReceiver<sample::blink::Service>( auto receiver = mojo::PendingReceiver<sample::blink::Service>(
......
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap_observer_list.h" #include "third_party/blink/renderer/platform/heap_observer_list.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
namespace {
class MockContext final : public GarbageCollected<MockContext>, class MockContext final : public GarbageCollected<MockContext>,
public ContextLifecycleNotifier { public ContextLifecycleNotifier {
USING_GARBAGE_COLLECTED_MIXIN(MockContext); USING_GARBAGE_COLLECTED_MIXIN(MockContext);
...@@ -42,12 +45,15 @@ class MockContext final : public GarbageCollected<MockContext>, ...@@ -42,12 +45,15 @@ class MockContext final : public GarbageCollected<MockContext>,
HeapObserverList<ContextLifecycleObserver> observers_; HeapObserverList<ContextLifecycleObserver> observers_;
}; };
class ReceiverOwner : public GarbageCollected<ReceiverOwner>, template <HeapMojoWrapperMode Mode>
class ReceiverOwner : public GarbageCollected<ReceiverOwner<Mode>>,
public sample::blink::Service { public sample::blink::Service {
public: public:
explicit ReceiverOwner(MockContext* context) : receiver_(this, context) {} explicit ReceiverOwner(MockContext* context) : receiver_(this, context) {}
HeapMojoReceiver<sample::blink::Service>& receiver() { return receiver_; } HeapMojoReceiver<sample::blink::Service, Mode>& receiver() {
return receiver_;
}
void Trace(Visitor* visitor) { visitor->Trace(receiver_); } void Trace(Visitor* visitor) { visitor->Trace(receiver_); }
...@@ -59,10 +65,11 @@ class ReceiverOwner : public GarbageCollected<ReceiverOwner>, ...@@ -59,10 +65,11 @@ class ReceiverOwner : public GarbageCollected<ReceiverOwner>,
sample::blink::Service::FrobinateCallback callback) override {} sample::blink::Service::FrobinateCallback callback) override {}
void GetPort(mojo::PendingReceiver<sample::blink::Port> port) override {} void GetPort(mojo::PendingReceiver<sample::blink::Port> port) override {}
HeapMojoReceiver<sample::blink::Service> receiver_; HeapMojoReceiver<sample::blink::Service, Mode> receiver_;
}; };
class HeapMojoReceiverTest : public TestSupportingGC { template <HeapMojoWrapperMode Mode>
class HeapMojoReceiverGCBaseTest : public TestSupportingGC {
public: public:
base::RunLoop& run_loop() { return run_loop_; } base::RunLoop& run_loop() { return run_loop_; }
bool& disconnected() { return disconnected_; } bool& disconnected() { return disconnected_; }
...@@ -73,13 +80,13 @@ class HeapMojoReceiverTest : public TestSupportingGC { ...@@ -73,13 +80,13 @@ class HeapMojoReceiverTest : public TestSupportingGC {
void SetUp() override { void SetUp() override {
CHECK(!disconnected_); CHECK(!disconnected_);
context_ = MakeGarbageCollected<MockContext>(); context_ = MakeGarbageCollected<MockContext>();
owner_ = MakeGarbageCollected<ReceiverOwner>(context_); owner_ = MakeGarbageCollected<ReceiverOwner<Mode>>(context_);
scoped_refptr<base::NullTaskRunner> null_task_runner = scoped_refptr<base::NullTaskRunner> null_task_runner =
base::MakeRefCounted<base::NullTaskRunner>(); base::MakeRefCounted<base::NullTaskRunner>();
remote_ = mojo::Remote<sample::blink::Service>( remote_ = mojo::Remote<sample::blink::Service>(
owner_->receiver().BindNewPipeAndPassRemote(null_task_runner)); owner_->receiver().BindNewPipeAndPassRemote(null_task_runner));
remote_.set_disconnect_handler(WTF::Bind( remote_.set_disconnect_handler(WTF::Bind(
[](HeapMojoReceiverTest* receiver_test) { [](HeapMojoReceiverGCBaseTest* receiver_test) {
receiver_test->run_loop().Quit(); receiver_test->run_loop().Quit();
receiver_test->disconnected() = true; receiver_test->disconnected() = true;
}, },
...@@ -88,29 +95,82 @@ class HeapMojoReceiverTest : public TestSupportingGC { ...@@ -88,29 +95,82 @@ class HeapMojoReceiverTest : public TestSupportingGC {
void TearDown() override { CHECK(disconnected_); } void TearDown() override { CHECK(disconnected_); }
Persistent<MockContext> context_; Persistent<MockContext> context_;
Persistent<ReceiverOwner> owner_; Persistent<ReceiverOwner<Mode>> owner_;
base::RunLoop run_loop_; base::RunLoop run_loop_;
mojo::Remote<sample::blink::Service> remote_; mojo::Remote<sample::blink::Service> remote_;
bool disconnected_ = false; bool disconnected_ = false;
}; };
// Make HeapMojoReceiver garbage collected and check that the connection is template <HeapMojoWrapperMode Mode>
// disconnected right after the marking phase. class HeapMojoReceiverDestroyContextBaseTest : public TestSupportingGC {
TEST_F(HeapMojoReceiverTest, ResetsOnGC) { protected:
void SetUp() override {
context_ = MakeGarbageCollected<MockContext>();
owner_ = MakeGarbageCollected<ReceiverOwner<Mode>>(context_);
scoped_refptr<base::NullTaskRunner> null_task_runner =
base::MakeRefCounted<base::NullTaskRunner>();
remote_ = mojo::Remote<sample::blink::Service>(
owner_->receiver().BindNewPipeAndPassRemote(null_task_runner));
}
Persistent<MockContext> context_;
Persistent<ReceiverOwner<Mode>> owner_;
mojo::Remote<sample::blink::Service> remote_;
};
} // namespace
class HeapMojoReceiverGCWithContextObserverTest
: public HeapMojoReceiverGCBaseTest<
HeapMojoWrapperMode::kWithContextObserver> {};
class HeapMojoReceiverGCWithoutContextObserverTest
: public HeapMojoReceiverGCBaseTest<
HeapMojoWrapperMode::kWithoutContextObserver> {};
class HeapMojoReceiverDestroyContextWithContextObserverTest
: public HeapMojoReceiverDestroyContextBaseTest<
HeapMojoWrapperMode::kWithContextObserver> {};
class HeapMojoReceiverDestroyContextWithoutContextObserverTest
: public HeapMojoReceiverDestroyContextBaseTest<
HeapMojoWrapperMode::kWithoutContextObserver> {};
// Make HeapMojoReceiver with context observer garbage collected and check that
// the connection is disconnected right after the marking phase.
TEST_F(HeapMojoReceiverGCWithContextObserverTest, ResetsOnGC) {
ClearOwner(); ClearOwner();
EXPECT_FALSE(disconnected()); EXPECT_FALSE(disconnected());
PreciselyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping); PreciselyCollectGarbage();
run_loop().Run(); run_loop().Run();
EXPECT_TRUE(disconnected()); EXPECT_TRUE(disconnected());
CompleteSweepingIfNeeded(); CompleteSweepingIfNeeded();
} }
// Destroy the context and check that the connection is disconnected. // Make HeapMojoReceiver without context observer garbage collected and check
TEST_F(HeapMojoReceiverTest, ResetsOnContextDestroyed) { // that the connection is disconnected right after the marking phase.
TEST_F(HeapMojoReceiverGCWithoutContextObserverTest, ResetsOnGC) {
ClearOwner();
EXPECT_FALSE(disconnected()); EXPECT_FALSE(disconnected());
context_->NotifyContextDestroyed(); PreciselyCollectGarbage();
run_loop().Run(); run_loop().Run();
EXPECT_TRUE(disconnected()); EXPECT_TRUE(disconnected());
CompleteSweepingIfNeeded();
}
// Destroy the context with context observer and check that the connection is
// disconnected.
TEST_F(HeapMojoReceiverDestroyContextWithContextObserverTest,
ResetsOnContextDestroyed) {
EXPECT_TRUE(owner_->receiver().is_bound());
context_->NotifyContextDestroyed();
EXPECT_FALSE(owner_->receiver().is_bound());
}
// Destroy the context without context observer and check that the connection is
// still connected.
TEST_F(HeapMojoReceiverDestroyContextWithoutContextObserverTest,
ResetsOnContextDestroyed) {
EXPECT_TRUE(owner_->receiver().is_bound());
context_->NotifyContextDestroyed();
EXPECT_TRUE(owner_->receiver().is_bound());
} }
} // namespace blink } // namespace blink
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/renderer/platform/context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
...@@ -19,7 +20,11 @@ namespace blink { ...@@ -19,7 +20,11 @@ namespace blink {
// HeapMojoRemote's constructor takes context as a mandatory parameter. // HeapMojoRemote's constructor takes context as a mandatory parameter.
// HeapMojoRemote resets the mojo connection when 1) the owner object is // HeapMojoRemote resets the mojo connection when 1) the owner object is
// garbage-collected and 2) the associated ExecutionContext is detached. // garbage-collected and 2) the associated ExecutionContext is detached.
template <typename Interface>
// TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
// that the interface is not used after ContextDestroyed().
template <typename Interface,
HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
class HeapMojoRemote { class HeapMojoRemote {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -72,7 +77,10 @@ class HeapMojoRemote { ...@@ -72,7 +77,10 @@ class HeapMojoRemote {
mojo::Remote<Interface>& remote() { return remote_; } mojo::Remote<Interface>& remote() { return remote_; }
// ContextLifecycleObserver methods // ContextLifecycleObserver methods
void ContextDestroyed() override { remote_.reset(); } void ContextDestroyed() override {
if (Mode == HeapMojoWrapperMode::kWithContextObserver)
remote_.reset();
}
private: private:
mojo::Remote<Interface> remote_; mojo::Remote<Interface> remote_;
......
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap_observer_list.h" #include "third_party/blink/renderer/platform/heap_observer_list.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
namespace {
class MockContext final : public GarbageCollected<MockContext>, class MockContext final : public GarbageCollected<MockContext>,
public ContextLifecycleNotifier { public ContextLifecycleNotifier {
USING_GARBAGE_COLLECTED_MIXIN(MockContext); USING_GARBAGE_COLLECTED_MIXIN(MockContext);
...@@ -59,18 +62,20 @@ class ServiceImpl : public sample::blink::Service { ...@@ -59,18 +62,20 @@ class ServiceImpl : public sample::blink::Service {
mojo::Receiver<sample::blink::Service> receiver_{this}; mojo::Receiver<sample::blink::Service> receiver_{this};
}; };
class RemoteOwner : public GarbageCollected<RemoteOwner> { template <HeapMojoWrapperMode Mode>
class RemoteOwner : public GarbageCollected<RemoteOwner<Mode>> {
public: public:
explicit RemoteOwner(MockContext* context) : remote_(context) {} explicit RemoteOwner(MockContext* context) : remote_(context) {}
HeapMojoRemote<sample::blink::Service>& remote() { return remote_; } HeapMojoRemote<sample::blink::Service, Mode>& remote() { return remote_; }
void Trace(Visitor* visitor) { visitor->Trace(remote_); } void Trace(Visitor* visitor) { visitor->Trace(remote_); }
HeapMojoRemote<sample::blink::Service> remote_; HeapMojoRemote<sample::blink::Service, Mode> remote_;
}; };
class HeapMojoRemoteTest : public TestSupportingGC { template <HeapMojoWrapperMode Mode>
class HeapMojoRemoteGCBaseTest : public TestSupportingGC {
public: public:
base::RunLoop& run_loop() { return run_loop_; } base::RunLoop& run_loop() { return run_loop_; }
bool& disconnected() { return disconnected_; } bool& disconnected() { return disconnected_; }
...@@ -81,46 +86,96 @@ class HeapMojoRemoteTest : public TestSupportingGC { ...@@ -81,46 +86,96 @@ class HeapMojoRemoteTest : public TestSupportingGC {
void SetUp() override { void SetUp() override {
CHECK(!disconnected_); CHECK(!disconnected_);
context_ = MakeGarbageCollected<MockContext>(); context_ = MakeGarbageCollected<MockContext>();
owner_ = MakeGarbageCollected<RemoteOwner>(context_); owner_ = MakeGarbageCollected<RemoteOwner<Mode>>(context_);
scoped_refptr<base::NullTaskRunner> null_task_runner = scoped_refptr<base::NullTaskRunner> null_task_runner =
base::MakeRefCounted<base::NullTaskRunner>(); base::MakeRefCounted<base::NullTaskRunner>();
impl_.receiver().Bind( impl_.receiver().Bind(
owner_->remote().BindNewPipeAndPassReceiver(null_task_runner)); owner_->remote().BindNewPipeAndPassReceiver(null_task_runner));
impl_.receiver().set_disconnect_handler(WTF::Bind( impl_.receiver().set_disconnect_handler(WTF::Bind(
[](HeapMojoRemoteTest* remote_test) { [](HeapMojoRemoteGCBaseTest* remote_test) {
remote_test->run_loop().Quit(); remote_test->run_loop().Quit();
remote_test->disconnected() = true; remote_test->disconnected() = true;
}, },
WTF::Unretained(this))); WTF::Unretained(this)));
} }
void TearDown() override {
// CHECK(disconnected_);
}
ServiceImpl impl_; ServiceImpl impl_;
Persistent<MockContext> context_; Persistent<MockContext> context_;
Persistent<RemoteOwner> owner_; Persistent<RemoteOwner<Mode>> owner_;
base::RunLoop run_loop_; base::RunLoop run_loop_;
bool disconnected_ = false; bool disconnected_ = false;
}; };
// Make HeapMojoRemote garbage collected and check that the connection is template <HeapMojoWrapperMode Mode>
// disconnected right after the marking phase. class HeapMojoRemoteDestroyContextBaseTest : public TestSupportingGC {
TEST_F(HeapMojoRemoteTest, ResetsOnGC) { protected:
void SetUp() override {
context_ = MakeGarbageCollected<MockContext>();
owner_ = MakeGarbageCollected<RemoteOwner<Mode>>(context_);
scoped_refptr<base::NullTaskRunner> null_task_runner =
base::MakeRefCounted<base::NullTaskRunner>();
impl_.receiver().Bind(
owner_->remote().BindNewPipeAndPassReceiver(null_task_runner));
}
ServiceImpl impl_;
Persistent<MockContext> context_;
Persistent<RemoteOwner<Mode>> owner_;
};
} // namespace
class HeapMojoRemoteGCWithContextObserverTest
: public HeapMojoRemoteGCBaseTest<
HeapMojoWrapperMode::kWithContextObserver> {};
class HeapMojoRemoteGCWithoutContextObserverTest
: public HeapMojoRemoteGCBaseTest<
HeapMojoWrapperMode::kWithoutContextObserver> {};
class HeapMojoRemoteDestroyContextWithContextObserverTest
: public HeapMojoRemoteDestroyContextBaseTest<
HeapMojoWrapperMode::kWithContextObserver> {};
class HeapMojoRemoteDestroyContextWithoutContextObserverTest
: public HeapMojoRemoteDestroyContextBaseTest<
HeapMojoWrapperMode::kWithoutContextObserver> {};
// Make HeapMojoRemote with context observer garbage collected and check that
// the connection is disconnected right after the marking phase.
TEST_F(HeapMojoRemoteGCWithContextObserverTest, ResetsOnGC) {
ClearOwner(); ClearOwner();
EXPECT_FALSE(disconnected()); EXPECT_FALSE(disconnected());
PreciselyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping); PreciselyCollectGarbage();
run_loop().Run(); run_loop().Run();
EXPECT_TRUE(disconnected()); EXPECT_TRUE(disconnected());
CompleteSweepingIfNeeded(); CompleteSweepingIfNeeded();
} }
// Destroy the context and check that the connection is disconnected. // Make HeapMojoRemote without context observer garbage collected and check that
TEST_F(HeapMojoRemoteTest, ResetsOnContextDestroyed) { // the connection is disconnected right after the marking phase.
TEST_F(HeapMojoRemoteGCWithoutContextObserverTest, ResetsOnGC) {
ClearOwner();
EXPECT_FALSE(disconnected()); EXPECT_FALSE(disconnected());
context_->NotifyContextDestroyed(); PreciselyCollectGarbage();
run_loop().Run(); run_loop().Run();
EXPECT_TRUE(disconnected()); EXPECT_TRUE(disconnected());
CompleteSweepingIfNeeded();
}
// Destroy the context with context observer and check that the connection is
// disconnected.
TEST_F(HeapMojoRemoteDestroyContextWithContextObserverTest,
ResetsOnContextDestroyed) {
EXPECT_TRUE(owner_->remote().is_bound());
context_->NotifyContextDestroyed();
EXPECT_FALSE(owner_->remote().is_bound());
}
// Destroy the context without context observer and check that the connection is
// still connected.
TEST_F(HeapMojoRemoteDestroyContextWithoutContextObserverTest,
ResetsOnContextDestroyed) {
EXPECT_TRUE(owner_->remote().is_bound());
context_->NotifyContextDestroyed();
EXPECT_TRUE(owner_->remote().is_bound());
} }
} // namespace blink } // namespace blink
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/unique_receiver_set.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "third_party/blink/renderer/platform/context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
...@@ -19,7 +20,9 @@ namespace blink { ...@@ -19,7 +20,9 @@ namespace blink {
// context as a mandatory parameter. HeapMojoUniqueReceiverSet resets the mojo // context as a mandatory parameter. HeapMojoUniqueReceiverSet resets the mojo
// connection when 1) the owner object is garbage-collected or 2) the associated // connection when 1) the owner object is garbage-collected or 2) the associated
// ExecutionContext is detached. // ExecutionContext is detached.
template <typename Interface, typename Deleter = std::default_delete<Interface>> template <typename Interface,
typename Deleter = std::default_delete<Interface>,
HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
class HeapMojoUniqueReceiverSet { class HeapMojoUniqueReceiverSet {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -76,7 +79,10 @@ class HeapMojoUniqueReceiverSet { ...@@ -76,7 +79,10 @@ class HeapMojoUniqueReceiverSet {
} }
// ContextLifecycleObserver methods // ContextLifecycleObserver methods
void ContextDestroyed() override { receiver_set_.Clear(); } void ContextDestroyed() override {
if (Mode == HeapMojoWrapperMode::kWithContextObserver)
receiver_set_.Clear();
}
private: private:
mojo::UniqueReceiverSet<Interface, void, Deleter> receiver_set_; mojo::UniqueReceiverSet<Interface, void, Deleter> receiver_set_;
......
...@@ -11,10 +11,12 @@ ...@@ -11,10 +11,12 @@
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap_observer_list.h" #include "third_party/blink/renderer/platform/heap_observer_list.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink { namespace blink {
namespace { namespace {
class FakeContextNotifier final : public GarbageCollected<FakeContextNotifier>, class FakeContextNotifier final : public GarbageCollected<FakeContextNotifier>,
public ContextLifecycleNotifier { public ContextLifecycleNotifier {
USING_GARBAGE_COLLECTED_MIXIN(FakeContextNotifier); USING_GARBAGE_COLLECTED_MIXIN(FakeContextNotifier);
...@@ -46,27 +48,34 @@ class FakeContextNotifier final : public GarbageCollected<FakeContextNotifier>, ...@@ -46,27 +48,34 @@ class FakeContextNotifier final : public GarbageCollected<FakeContextNotifier>,
HeapObserverList<ContextLifecycleObserver> observers_; HeapObserverList<ContextLifecycleObserver> observers_;
}; };
class GCOwner : public GarbageCollected<GCOwner> { template <HeapMojoWrapperMode Mode>
class GCOwner : public GarbageCollected<GCOwner<Mode>> {
public: public:
explicit GCOwner(FakeContextNotifier* context) : receiver_set_(context) {} explicit GCOwner(FakeContextNotifier* context) : receiver_set_(context) {}
void Trace(Visitor* visitor) { visitor->Trace(receiver_set_); } void Trace(Visitor* visitor) { visitor->Trace(receiver_set_); }
HeapMojoUniqueReceiverSet<sample::blink::Service>& receiver_set() { HeapMojoUniqueReceiverSet<sample::blink::Service,
std::default_delete<sample::blink::Service>,
Mode>&
receiver_set() {
return receiver_set_; return receiver_set_;
} }
private: private:
HeapMojoUniqueReceiverSet<sample::blink::Service> receiver_set_; HeapMojoUniqueReceiverSet<sample::blink::Service,
std::default_delete<sample::blink::Service>,
Mode>
receiver_set_;
}; };
} // namespace template <HeapMojoWrapperMode Mode>
class HeapMojoUniqueReceiverSetTest : public TestSupportingGC { class HeapMojoUniqueReceiverSetBaseTest : public TestSupportingGC {
public: public:
FakeContextNotifier* context() { return context_; } FakeContextNotifier* context() { return context_; }
scoped_refptr<base::NullTaskRunner> task_runner() { scoped_refptr<base::NullTaskRunner> task_runner() {
return null_task_runner_; return null_task_runner_;
} }
GCOwner* owner() { return owner_; } GCOwner<Mode>* owner() { return owner_; }
void ClearOwner() { owner_ = nullptr; } void ClearOwner() { owner_ = nullptr; }
...@@ -75,22 +84,32 @@ class HeapMojoUniqueReceiverSetTest : public TestSupportingGC { ...@@ -75,22 +84,32 @@ class HeapMojoUniqueReceiverSetTest : public TestSupportingGC {
protected: protected:
void SetUp() override { void SetUp() override {
context_ = MakeGarbageCollected<FakeContextNotifier>(); context_ = MakeGarbageCollected<FakeContextNotifier>();
owner_ = MakeGarbageCollected<GCOwner>(context()); owner_ = MakeGarbageCollected<GCOwner<Mode>>(context());
} }
void TearDown() override {} void TearDown() override {}
Persistent<FakeContextNotifier> context_; Persistent<FakeContextNotifier> context_;
Persistent<GCOwner> owner_; Persistent<GCOwner<Mode>> owner_;
scoped_refptr<base::NullTaskRunner> null_task_runner_ = scoped_refptr<base::NullTaskRunner> null_task_runner_ =
base::MakeRefCounted<base::NullTaskRunner>(); base::MakeRefCounted<base::NullTaskRunner>();
bool service_deleted_ = false; bool service_deleted_ = false;
}; };
class HeapMojoUniqueReceiverSetWithContextObserverTest
: public HeapMojoUniqueReceiverSetBaseTest<
HeapMojoWrapperMode::kWithContextObserver> {};
class HeapMojoUniqueReceiverSetWithoutContextObserverTest
: public HeapMojoUniqueReceiverSetBaseTest<
HeapMojoWrapperMode::kWithoutContextObserver> {};
} // namespace
namespace { namespace {
template <typename T>
class MockService : public sample::blink::Service { class MockService : public sample::blink::Service {
public: public:
explicit MockService(HeapMojoUniqueReceiverSetTest* test) : test_(test) {} explicit MockService(T* test) : test_(test) {}
// Notify the test when the service is deleted by the UniqueReceiverSet. // Notify the test when the service is deleted by the UniqueReceiverSet.
~MockService() override { test_->MarkServiceDeleted(); } ~MockService() override { test_->MarkServiceDeleted(); }
...@@ -101,16 +120,39 @@ class MockService : public sample::blink::Service { ...@@ -101,16 +120,39 @@ class MockService : public sample::blink::Service {
void GetPort(mojo::PendingReceiver<sample::blink::Port> receiver) override {} void GetPort(mojo::PendingReceiver<sample::blink::Port> receiver) override {}
private: private:
HeapMojoUniqueReceiverSetTest* test_; T* test_;
}; };
} // namespace } // namespace
// GC the HeapMojoUniqueReceiverSet and verify that the receiver is no longer // GC the HeapMojoUniqueReceiverSet with context observer and verify that the
// part of the set, and that the service was deleted. // receiver is no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoUniqueReceiverSetTest, ResetsOnGC) { TEST_F(HeapMojoUniqueReceiverSetWithContextObserverTest, ResetsOnGC) {
auto receiver_set = owner()->receiver_set();
auto service = std::make_unique<
MockService<HeapMojoUniqueReceiverSetWithContextObserverTest>>(this);
auto receiver = mojo::PendingReceiver<sample::blink::Service>(
mojo::MessagePipe().handle0);
mojo::ReceiverId rid =
receiver_set.Add(std::move(service), std::move(receiver), task_runner());
EXPECT_TRUE(receiver_set.HasReceiver(rid));
EXPECT_FALSE(service_deleted_);
ClearOwner();
PreciselyCollectGarbage();
EXPECT_TRUE(service_deleted_);
CompleteSweepingIfNeeded();
}
// GC the HeapMojoUniqueReceiverSet without context observer and verify that the
// receiver is no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoUniqueReceiverSetWithoutContextObserverTest, ResetsOnGC) {
auto receiver_set = owner()->receiver_set(); auto receiver_set = owner()->receiver_set();
auto service = std::make_unique<MockService>(this); auto service = std::make_unique<
MockService<HeapMojoUniqueReceiverSetWithoutContextObserverTest>>(this);
auto receiver = mojo::PendingReceiver<sample::blink::Service>( auto receiver = mojo::PendingReceiver<sample::blink::Service>(
mojo::MessagePipe().handle0); mojo::MessagePipe().handle0);
...@@ -120,18 +162,41 @@ TEST_F(HeapMojoUniqueReceiverSetTest, ResetsOnGC) { ...@@ -120,18 +162,41 @@ TEST_F(HeapMojoUniqueReceiverSetTest, ResetsOnGC) {
EXPECT_FALSE(service_deleted_); EXPECT_FALSE(service_deleted_);
ClearOwner(); ClearOwner();
PreciselyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping); PreciselyCollectGarbage();
EXPECT_TRUE(service_deleted_); EXPECT_TRUE(service_deleted_);
CompleteSweepingIfNeeded(); CompleteSweepingIfNeeded();
} }
// Destroy the context and verify that the receiver is no longer // Destroy the context with context observer and verify that the receiver is no
// part of the set, and that the service was deleted. // longer part of the set, and that the service was deleted.
TEST_F(HeapMojoUniqueReceiverSetTest, ResetsOnContextDestroyed) { TEST_F(HeapMojoUniqueReceiverSetWithContextObserverTest,
ResetsOnContextDestroyed) {
HeapMojoUniqueReceiverSet<sample::blink::Service> receiver_set(context());
auto service = std::make_unique<
MockService<HeapMojoUniqueReceiverSetWithContextObserverTest>>(this);
auto receiver = mojo::PendingReceiver<sample::blink::Service>(
mojo::MessagePipe().handle0);
mojo::ReceiverId rid =
receiver_set.Add(std::move(service), std::move(receiver), task_runner());
EXPECT_TRUE(receiver_set.HasReceiver(rid));
EXPECT_FALSE(service_deleted_);
context_->NotifyContextDestroyed();
EXPECT_FALSE(receiver_set.HasReceiver(rid));
EXPECT_TRUE(service_deleted_);
}
// Destroy the context without context observer and verify that the receiver is
// no longer part of the set, and that the service was deleted.
TEST_F(HeapMojoUniqueReceiverSetWithoutContextObserverTest,
ResetsOnContextDestroyed) {
HeapMojoUniqueReceiverSet<sample::blink::Service> receiver_set(context()); HeapMojoUniqueReceiverSet<sample::blink::Service> receiver_set(context());
auto service = std::make_unique<MockService>(this); auto service = std::make_unique<
MockService<HeapMojoUniqueReceiverSetWithoutContextObserverTest>>(this);
auto receiver = mojo::PendingReceiver<sample::blink::Service>( auto receiver = mojo::PendingReceiver<sample::blink::Service>(
mojo::MessagePipe().handle0); mojo::MessagePipe().handle0);
......
// 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_WRAPPER_MODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_WRAPPER_MODE_H_
namespace blink {
// A list of modes for HeapMojo wrappers.
enum class HeapMojoWrapperMode {
// Resets the mojo connection when 1) the owner object is garbage-collected
// and 2) the associated ExecutionContext is detached.
kWithContextObserver,
// Resets the mojo connection when the owner object is garbage-collected.
// But, it will not reset the mojo connection when the associated
// ExecutionContext is detached.
kWithoutContextObserver,
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_WRAPPER_MODE_H_
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