1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_ASSOCIATED_RECEIVER_H_
6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_ASSOCIATED_RECEIVER_H_
7 
8 #include <utility>
9 
10 #include "mojo/public/cpp/bindings/associated_receiver.h"
11 #include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
12 #include "third_party/blink/renderer/platform/heap/heap.h"
13 #include "third_party/blink/renderer/platform/mojo/features.h"
14 #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
15 
16 namespace blink {
17 
18 // HeapMojoAssociatedReceiver is a wrapper for mojo::AssociatedReceiver to be
19 // owned by a garbage-collected object. Blink is expected to use
20 // HeapMojoAssociatedReceiver by default. HeapMojoAssociatedReceiver must be
21 // associated with context. HeapMojoAssociatedReceiver's constructor takes
22 // context as a mandatory parameter. HeapMojoAssociatedReceiver resets the mojo
23 // connection when 1) the owner object is garbage-collected and 2) the
24 // associated ExecutionContext is detached.
25 
26 // TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
27 // that the interface is not used after ContextDestroyed().
28 template <typename Interface,
29           typename Owner,
30           HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
31 class HeapMojoAssociatedReceiver {
32   DISALLOW_NEW();
33 
34  public:
HeapMojoAssociatedReceiver(Owner * owner,ContextLifecycleNotifier * context)35   HeapMojoAssociatedReceiver(Owner* owner, ContextLifecycleNotifier* context)
36       : wrapper_(MakeGarbageCollected<Wrapper>(owner, context)) {
37     static_assert(std::is_base_of<Interface, Owner>::value,
38                   "Owner should implement Interface");
39     static_assert(IsGarbageCollectedType<Owner>::value,
40                   "Owner needs to be a garbage collected object");
41   }
42   HeapMojoAssociatedReceiver(const HeapMojoAssociatedReceiver&) = delete;
43   HeapMojoAssociatedReceiver& operator=(const HeapMojoAssociatedReceiver&) =
44       delete;
45 
46   // Methods to redirect to mojo::AssociatedReceiver:
is_bound()47   bool is_bound() const { return wrapper_->associated_receiver().is_bound(); }
reset()48   void reset() { wrapper_->associated_receiver().reset(); }
set_disconnect_handler(base::OnceClosure handler)49   void set_disconnect_handler(base::OnceClosure handler) {
50     wrapper_->associated_receiver().set_disconnect_handler(std::move(handler));
51   }
BindNewEndpointAndPassRemote(scoped_refptr<base::SequencedTaskRunner> task_runner)52   mojo::PendingAssociatedRemote<Interface> BindNewEndpointAndPassRemote(
53       scoped_refptr<base::SequencedTaskRunner> task_runner) WARN_UNUSED_RESULT {
54     DCHECK(task_runner);
55     return wrapper_->associated_receiver().BindNewEndpointAndPassRemote(
56         std::move(task_runner));
57   }
Bind(mojo::PendingAssociatedReceiver<Interface> pending_associated_receiver,scoped_refptr<base::SequencedTaskRunner> task_runner)58   void Bind(
59       mojo::PendingAssociatedReceiver<Interface> pending_associated_receiver,
60       scoped_refptr<base::SequencedTaskRunner> task_runner) {
61     DCHECK(task_runner);
62     wrapper_->associated_receiver().Bind(std::move(pending_associated_receiver),
63                                          std::move(task_runner));
64   }
WaitForIncomingCall()65   bool WaitForIncomingCall() {
66     return wrapper_->associated_receiver().WaitForIncomingCall();
67   }
68 
SetFilter(std::unique_ptr<mojo::MessageFilter> filter)69   void SetFilter(std::unique_ptr<mojo::MessageFilter> filter) {
70     wrapper_->associated_receiver().SetFilter(std::move(filter));
71   }
72 
Trace(Visitor * visitor)73   void Trace(Visitor* visitor) const { visitor->Trace(wrapper_); }
74 
75  private:
76   FRIEND_TEST_ALL_PREFIXES(HeapMojoAssociatedReceiverGCWithContextObserverTest,
77                            NoResetOnConservativeGC);
78 
79   // Garbage collected wrapper class to add a prefinalizer.
80   class Wrapper final : public GarbageCollected<Wrapper>,
81                         public ContextLifecycleObserver {
82     USING_PRE_FINALIZER(Wrapper, Dispose);
83 
84    public:
Wrapper(Owner * owner,ContextLifecycleNotifier * notifier)85     Wrapper(Owner* owner, ContextLifecycleNotifier* notifier)
86         : owner_(owner), associated_receiver_(owner) {
87       SetContextLifecycleNotifier(notifier);
88     }
89 
Trace(Visitor * visitor)90     void Trace(Visitor* visitor) const override {
91       visitor->Trace(owner_);
92       ContextLifecycleObserver::Trace(visitor);
93     }
94 
Dispose()95     void Dispose() { associated_receiver_.reset(); }
96 
associated_receiver()97     mojo::AssociatedReceiver<Interface>& associated_receiver() {
98       return associated_receiver_;
99     }
100 
101     // ContextLifecycleObserver methods
ContextDestroyed()102     void ContextDestroyed() override {
103       if (Mode == HeapMojoWrapperMode::kWithContextObserver ||
104           (Mode == HeapMojoWrapperMode::kWithoutContextObserver &&
105            base::FeatureList::IsEnabled(kHeapMojoUseContextObserver)))
106         associated_receiver_.reset();
107     }
108 
109    private:
110     Member<Owner> owner_;
111     mojo::AssociatedReceiver<Interface> associated_receiver_;
112   };
113 
114   Member<Wrapper> wrapper_;
115 };
116 
117 }  // namespace blink
118 
119 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_ASSOCIATED_RECEIVER_H_
120