xref: /aosp_15_r20/external/cronet/ipc/ipc_mojo_bootstrap.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_mojo_bootstrap.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <inttypes.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <map>
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker #include <optional>
13*6777b538SAndroid Build Coastguard Worker #include <set>
14*6777b538SAndroid Build Coastguard Worker #include <utility>
15*6777b538SAndroid Build Coastguard Worker #include <vector>
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/containers/circular_deque.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/task/common/task_annotator.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
34*6777b538SAndroid Build Coastguard Worker #include "base/thread_annotations.h"
35*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/memory_allocator_dump.h"
36*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/memory_dump_manager.h"
37*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/memory_dump_provider.h"
38*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/typed_macros.h"
39*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_channel.h"
40*6777b538SAndroid Build Coastguard Worker #include "ipc/urgent_message_observer.h"
41*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/associated_group.h"
42*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/associated_group_controller.h"
43*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/connector.h"
44*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/features.h"
45*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
46*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
47*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/interface_id.h"
48*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/message.h"
49*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/message_header_validator.h"
50*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/mojo_buildflags.h"
51*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
52*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
53*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
54*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
55*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/tracing_helpers.h"
56*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/base/attributes.h"
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker namespace IPC {
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker class ChannelAssociatedGroupController;
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker namespace {
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker ABSL_CONST_INIT thread_local bool off_sequence_binding_allowed = false;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(kMojoChannelAssociatedSendUsesRunOrPostTask,
67*6777b538SAndroid Build Coastguard Worker              "MojoChannelAssociatedSendUsesRunOrPostTask",
68*6777b538SAndroid Build Coastguard Worker              base::FEATURE_DISABLED_BY_DEFAULT);
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker // Used to track some internal Channel state in pursuit of message leaks.
71*6777b538SAndroid Build Coastguard Worker //
72*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/813045): Remove this.
73*6777b538SAndroid Build Coastguard Worker class ControllerMemoryDumpProvider
74*6777b538SAndroid Build Coastguard Worker     : public base::trace_event::MemoryDumpProvider {
75*6777b538SAndroid Build Coastguard Worker  public:
ControllerMemoryDumpProvider()76*6777b538SAndroid Build Coastguard Worker   ControllerMemoryDumpProvider() {
77*6777b538SAndroid Build Coastguard Worker     base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
78*6777b538SAndroid Build Coastguard Worker         this, "IPCChannel", nullptr);
79*6777b538SAndroid Build Coastguard Worker   }
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   ControllerMemoryDumpProvider(const ControllerMemoryDumpProvider&) = delete;
82*6777b538SAndroid Build Coastguard Worker   ControllerMemoryDumpProvider& operator=(const ControllerMemoryDumpProvider&) =
83*6777b538SAndroid Build Coastguard Worker       delete;
84*6777b538SAndroid Build Coastguard Worker 
~ControllerMemoryDumpProvider()85*6777b538SAndroid Build Coastguard Worker   ~ControllerMemoryDumpProvider() override {
86*6777b538SAndroid Build Coastguard Worker     base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
87*6777b538SAndroid Build Coastguard Worker         this);
88*6777b538SAndroid Build Coastguard Worker   }
89*6777b538SAndroid Build Coastguard Worker 
AddController(ChannelAssociatedGroupController * controller)90*6777b538SAndroid Build Coastguard Worker   void AddController(ChannelAssociatedGroupController* controller) {
91*6777b538SAndroid Build Coastguard Worker     base::AutoLock lock(lock_);
92*6777b538SAndroid Build Coastguard Worker     controllers_.insert(controller);
93*6777b538SAndroid Build Coastguard Worker   }
94*6777b538SAndroid Build Coastguard Worker 
RemoveController(ChannelAssociatedGroupController * controller)95*6777b538SAndroid Build Coastguard Worker   void RemoveController(ChannelAssociatedGroupController* controller) {
96*6777b538SAndroid Build Coastguard Worker     base::AutoLock lock(lock_);
97*6777b538SAndroid Build Coastguard Worker     controllers_.erase(controller);
98*6777b538SAndroid Build Coastguard Worker   }
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker   // base::trace_event::MemoryDumpProvider:
101*6777b538SAndroid Build Coastguard Worker   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
102*6777b538SAndroid Build Coastguard Worker                     base::trace_event::ProcessMemoryDump* pmd) override;
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker  private:
105*6777b538SAndroid Build Coastguard Worker   base::Lock lock_;
106*6777b538SAndroid Build Coastguard Worker   std::set<raw_ptr<ChannelAssociatedGroupController, SetExperimental>>
107*6777b538SAndroid Build Coastguard Worker       controllers_;
108*6777b538SAndroid Build Coastguard Worker };
109*6777b538SAndroid Build Coastguard Worker 
GetMemoryDumpProvider()110*6777b538SAndroid Build Coastguard Worker ControllerMemoryDumpProvider& GetMemoryDumpProvider() {
111*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<ControllerMemoryDumpProvider> provider;
112*6777b538SAndroid Build Coastguard Worker   return *provider;
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker // Messages are grouped by this info when recording memory metrics.
116*6777b538SAndroid Build Coastguard Worker struct MessageMemoryDumpInfo {
MessageMemoryDumpInfoIPC::__anon2063248d0111::MessageMemoryDumpInfo117*6777b538SAndroid Build Coastguard Worker   MessageMemoryDumpInfo(const mojo::Message& message)
118*6777b538SAndroid Build Coastguard Worker       : id(message.name()), profiler_tag(message.heap_profiler_tag()) {}
119*6777b538SAndroid Build Coastguard Worker   MessageMemoryDumpInfo() = default;
120*6777b538SAndroid Build Coastguard Worker 
operator ==IPC::__anon2063248d0111::MessageMemoryDumpInfo121*6777b538SAndroid Build Coastguard Worker   bool operator==(const MessageMemoryDumpInfo& other) const {
122*6777b538SAndroid Build Coastguard Worker     return other.id == id && other.profiler_tag == profiler_tag;
123*6777b538SAndroid Build Coastguard Worker   }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   uint32_t id = 0;
126*6777b538SAndroid Build Coastguard Worker   const char* profiler_tag = nullptr;
127*6777b538SAndroid Build Coastguard Worker };
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker struct MessageMemoryDumpInfoHash {
operator ()IPC::__anon2063248d0111::MessageMemoryDumpInfoHash130*6777b538SAndroid Build Coastguard Worker   size_t operator()(const MessageMemoryDumpInfo& info) const {
131*6777b538SAndroid Build Coastguard Worker     return base::HashInts(
132*6777b538SAndroid Build Coastguard Worker         info.id, info.profiler_tag ? base::FastHash(info.profiler_tag) : 0);
133*6777b538SAndroid Build Coastguard Worker   }
134*6777b538SAndroid Build Coastguard Worker };
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker class ScopedUrgentMessageNotification {
137*6777b538SAndroid Build Coastguard Worker  public:
ScopedUrgentMessageNotification(UrgentMessageObserver * observer=nullptr)138*6777b538SAndroid Build Coastguard Worker   explicit ScopedUrgentMessageNotification(
139*6777b538SAndroid Build Coastguard Worker       UrgentMessageObserver* observer = nullptr)
140*6777b538SAndroid Build Coastguard Worker       : observer_(observer) {
141*6777b538SAndroid Build Coastguard Worker     if (observer_) {
142*6777b538SAndroid Build Coastguard Worker       observer_->OnUrgentMessageReceived();
143*6777b538SAndroid Build Coastguard Worker     }
144*6777b538SAndroid Build Coastguard Worker   }
145*6777b538SAndroid Build Coastguard Worker 
~ScopedUrgentMessageNotification()146*6777b538SAndroid Build Coastguard Worker   ~ScopedUrgentMessageNotification() {
147*6777b538SAndroid Build Coastguard Worker     if (observer_) {
148*6777b538SAndroid Build Coastguard Worker       observer_->OnUrgentMessageProcessed();
149*6777b538SAndroid Build Coastguard Worker     }
150*6777b538SAndroid Build Coastguard Worker   }
151*6777b538SAndroid Build Coastguard Worker 
ScopedUrgentMessageNotification(ScopedUrgentMessageNotification && other)152*6777b538SAndroid Build Coastguard Worker   ScopedUrgentMessageNotification(ScopedUrgentMessageNotification&& other)
153*6777b538SAndroid Build Coastguard Worker       : observer_(std::exchange(other.observer_, nullptr)) {}
154*6777b538SAndroid Build Coastguard Worker 
operator =(ScopedUrgentMessageNotification && other)155*6777b538SAndroid Build Coastguard Worker   ScopedUrgentMessageNotification& operator=(
156*6777b538SAndroid Build Coastguard Worker       ScopedUrgentMessageNotification&& other) {
157*6777b538SAndroid Build Coastguard Worker     observer_ = std::exchange(other.observer_, nullptr);
158*6777b538SAndroid Build Coastguard Worker     return *this;
159*6777b538SAndroid Build Coastguard Worker   }
160*6777b538SAndroid Build Coastguard Worker 
161*6777b538SAndroid Build Coastguard Worker  private:
162*6777b538SAndroid Build Coastguard Worker   raw_ptr<UrgentMessageObserver> observer_;
163*6777b538SAndroid Build Coastguard Worker };
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker }  // namespace
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker class ChannelAssociatedGroupController
168*6777b538SAndroid Build Coastguard Worker     : public mojo::AssociatedGroupController,
169*6777b538SAndroid Build Coastguard Worker       public mojo::MessageReceiver,
170*6777b538SAndroid Build Coastguard Worker       public mojo::PipeControlMessageHandlerDelegate {
171*6777b538SAndroid Build Coastguard Worker  public:
ChannelAssociatedGroupController(bool set_interface_id_namespace_bit,const scoped_refptr<base::SingleThreadTaskRunner> & ipc_task_runner,const scoped_refptr<base::SingleThreadTaskRunner> & proxy_task_runner)172*6777b538SAndroid Build Coastguard Worker   ChannelAssociatedGroupController(
173*6777b538SAndroid Build Coastguard Worker       bool set_interface_id_namespace_bit,
174*6777b538SAndroid Build Coastguard Worker       const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
175*6777b538SAndroid Build Coastguard Worker       const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner)
176*6777b538SAndroid Build Coastguard Worker       : task_runner_(ipc_task_runner),
177*6777b538SAndroid Build Coastguard Worker         proxy_task_runner_(proxy_task_runner),
178*6777b538SAndroid Build Coastguard Worker         set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
179*6777b538SAndroid Build Coastguard Worker         dispatcher_(this),
180*6777b538SAndroid Build Coastguard Worker         control_message_handler_(this),
181*6777b538SAndroid Build Coastguard Worker         control_message_proxy_thunk_(this),
182*6777b538SAndroid Build Coastguard Worker         control_message_proxy_(&control_message_proxy_thunk_) {
183*6777b538SAndroid Build Coastguard Worker     control_message_handler_.SetDescription(
184*6777b538SAndroid Build Coastguard Worker         "IPC::mojom::Bootstrap [primary] PipeControlMessageHandler");
185*6777b538SAndroid Build Coastguard Worker     dispatcher_.SetValidator(std::make_unique<mojo::MessageHeaderValidator>(
186*6777b538SAndroid Build Coastguard Worker         "IPC::mojom::Bootstrap [primary] MessageHeaderValidator"));
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker     GetMemoryDumpProvider().AddController(this);
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker     DETACH_FROM_SEQUENCE(sequence_checker_);
191*6777b538SAndroid Build Coastguard Worker   }
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker   ChannelAssociatedGroupController(const ChannelAssociatedGroupController&) =
194*6777b538SAndroid Build Coastguard Worker       delete;
195*6777b538SAndroid Build Coastguard Worker   ChannelAssociatedGroupController& operator=(
196*6777b538SAndroid Build Coastguard Worker       const ChannelAssociatedGroupController&) = delete;
197*6777b538SAndroid Build Coastguard Worker 
GetQueuedMessageCount()198*6777b538SAndroid Build Coastguard Worker   size_t GetQueuedMessageCount() {
199*6777b538SAndroid Build Coastguard Worker     base::AutoLock lock(outgoing_messages_lock_);
200*6777b538SAndroid Build Coastguard Worker     return outgoing_messages_.size();
201*6777b538SAndroid Build Coastguard Worker   }
202*6777b538SAndroid Build Coastguard Worker 
GetTopQueuedMessageMemoryDumpInfo(MessageMemoryDumpInfo * info,size_t * count)203*6777b538SAndroid Build Coastguard Worker   void GetTopQueuedMessageMemoryDumpInfo(MessageMemoryDumpInfo* info,
204*6777b538SAndroid Build Coastguard Worker                                          size_t* count) {
205*6777b538SAndroid Build Coastguard Worker     std::unordered_map<MessageMemoryDumpInfo, size_t, MessageMemoryDumpInfoHash>
206*6777b538SAndroid Build Coastguard Worker         counts;
207*6777b538SAndroid Build Coastguard Worker     std::pair<MessageMemoryDumpInfo, size_t> top_message_info_and_count = {
208*6777b538SAndroid Build Coastguard Worker         MessageMemoryDumpInfo(), 0};
209*6777b538SAndroid Build Coastguard Worker     base::AutoLock lock(outgoing_messages_lock_);
210*6777b538SAndroid Build Coastguard Worker     for (const auto& message : outgoing_messages_) {
211*6777b538SAndroid Build Coastguard Worker       auto it_and_inserted = counts.emplace(MessageMemoryDumpInfo(message), 0);
212*6777b538SAndroid Build Coastguard Worker       it_and_inserted.first->second++;
213*6777b538SAndroid Build Coastguard Worker       if (it_and_inserted.first->second > top_message_info_and_count.second)
214*6777b538SAndroid Build Coastguard Worker         top_message_info_and_count = *it_and_inserted.first;
215*6777b538SAndroid Build Coastguard Worker     }
216*6777b538SAndroid Build Coastguard Worker     *info = top_message_info_and_count.first;
217*6777b538SAndroid Build Coastguard Worker     *count = top_message_info_and_count.second;
218*6777b538SAndroid Build Coastguard Worker   }
219*6777b538SAndroid Build Coastguard Worker 
Pause()220*6777b538SAndroid Build Coastguard Worker   void Pause() {
221*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
222*6777b538SAndroid Build Coastguard Worker     CHECK(was_bound_or_message_sent_);
223*6777b538SAndroid Build Coastguard Worker     CHECK(!paused_);
224*6777b538SAndroid Build Coastguard Worker     paused_ = true;
225*6777b538SAndroid Build Coastguard Worker   }
226*6777b538SAndroid Build Coastguard Worker 
Unpause()227*6777b538SAndroid Build Coastguard Worker   void Unpause() {
228*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
229*6777b538SAndroid Build Coastguard Worker     CHECK(was_bound_or_message_sent_);
230*6777b538SAndroid Build Coastguard Worker     CHECK(paused_);
231*6777b538SAndroid Build Coastguard Worker     paused_ = false;
232*6777b538SAndroid Build Coastguard Worker   }
233*6777b538SAndroid Build Coastguard Worker 
FlushOutgoingMessages()234*6777b538SAndroid Build Coastguard Worker   void FlushOutgoingMessages() {
235*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
236*6777b538SAndroid Build Coastguard Worker     CHECK(was_bound_or_message_sent_);
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker     std::vector<mojo::Message> outgoing_messages;
239*6777b538SAndroid Build Coastguard Worker     {
240*6777b538SAndroid Build Coastguard Worker       base::AutoLock lock(outgoing_messages_lock_);
241*6777b538SAndroid Build Coastguard Worker       std::swap(outgoing_messages, outgoing_messages_);
242*6777b538SAndroid Build Coastguard Worker     }
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker     for (auto& message : outgoing_messages)
245*6777b538SAndroid Build Coastguard Worker       SendMessage(&message);
246*6777b538SAndroid Build Coastguard Worker   }
247*6777b538SAndroid Build Coastguard Worker 
Bind(mojo::ScopedMessagePipeHandle handle,mojo::PendingAssociatedRemote<mojom::Channel> * sender,mojo::PendingAssociatedReceiver<mojom::Channel> * receiver)248*6777b538SAndroid Build Coastguard Worker   void Bind(mojo::ScopedMessagePipeHandle handle,
249*6777b538SAndroid Build Coastguard Worker             mojo::PendingAssociatedRemote<mojom::Channel>* sender,
250*6777b538SAndroid Build Coastguard Worker             mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) {
251*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
252*6777b538SAndroid Build Coastguard Worker 
253*6777b538SAndroid Build Coastguard Worker     connector_ = std::make_unique<mojo::Connector>(
254*6777b538SAndroid Build Coastguard Worker         std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
255*6777b538SAndroid Build Coastguard Worker         "IPC Channel");
256*6777b538SAndroid Build Coastguard Worker     connector_->set_incoming_receiver(&dispatcher_);
257*6777b538SAndroid Build Coastguard Worker     connector_->set_connection_error_handler(
258*6777b538SAndroid Build Coastguard Worker         base::BindOnce(&ChannelAssociatedGroupController::OnPipeError,
259*6777b538SAndroid Build Coastguard Worker                        base::Unretained(this)));
260*6777b538SAndroid Build Coastguard Worker     connector_->set_enforce_errors_from_incoming_receiver(false);
261*6777b538SAndroid Build Coastguard Worker 
262*6777b538SAndroid Build Coastguard Worker     // Don't let the Connector do any sort of queuing on our behalf. Individual
263*6777b538SAndroid Build Coastguard Worker     // messages bound for the IPC::ChannelProxy thread (i.e. that vast majority
264*6777b538SAndroid Build Coastguard Worker     // of messages received by this Connector) are already individually
265*6777b538SAndroid Build Coastguard Worker     // scheduled for dispatch by ChannelProxy, so Connector's normal mode of
266*6777b538SAndroid Build Coastguard Worker     // operation would only introduce a redundant scheduling step for most
267*6777b538SAndroid Build Coastguard Worker     // messages.
268*6777b538SAndroid Build Coastguard Worker     connector_->set_force_immediate_dispatch(true);
269*6777b538SAndroid Build Coastguard Worker 
270*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceId sender_id, receiver_id;
271*6777b538SAndroid Build Coastguard Worker     if (set_interface_id_namespace_bit_) {
272*6777b538SAndroid Build Coastguard Worker       sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
273*6777b538SAndroid Build Coastguard Worker       receiver_id = 1;
274*6777b538SAndroid Build Coastguard Worker     } else {
275*6777b538SAndroid Build Coastguard Worker       sender_id = 1;
276*6777b538SAndroid Build Coastguard Worker       receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
277*6777b538SAndroid Build Coastguard Worker     }
278*6777b538SAndroid Build Coastguard Worker 
279*6777b538SAndroid Build Coastguard Worker     {
280*6777b538SAndroid Build Coastguard Worker       base::AutoLock locker(lock_);
281*6777b538SAndroid Build Coastguard Worker       Endpoint* sender_endpoint = new Endpoint(this, sender_id);
282*6777b538SAndroid Build Coastguard Worker       Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
283*6777b538SAndroid Build Coastguard Worker       endpoints_.insert({ sender_id, sender_endpoint });
284*6777b538SAndroid Build Coastguard Worker       endpoints_.insert({ receiver_id, receiver_endpoint });
285*6777b538SAndroid Build Coastguard Worker       sender_endpoint->set_handle_created();
286*6777b538SAndroid Build Coastguard Worker       receiver_endpoint->set_handle_created();
287*6777b538SAndroid Build Coastguard Worker     }
288*6777b538SAndroid Build Coastguard Worker 
289*6777b538SAndroid Build Coastguard Worker     mojo::ScopedInterfaceEndpointHandle sender_handle =
290*6777b538SAndroid Build Coastguard Worker         CreateScopedInterfaceEndpointHandle(sender_id);
291*6777b538SAndroid Build Coastguard Worker     mojo::ScopedInterfaceEndpointHandle receiver_handle =
292*6777b538SAndroid Build Coastguard Worker         CreateScopedInterfaceEndpointHandle(receiver_id);
293*6777b538SAndroid Build Coastguard Worker 
294*6777b538SAndroid Build Coastguard Worker     *sender = mojo::PendingAssociatedRemote<mojom::Channel>(
295*6777b538SAndroid Build Coastguard Worker         std::move(sender_handle), 0);
296*6777b538SAndroid Build Coastguard Worker     *receiver = mojo::PendingAssociatedReceiver<mojom::Channel>(
297*6777b538SAndroid Build Coastguard Worker         std::move(receiver_handle));
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker     if (!was_bound_or_message_sent_) {
300*6777b538SAndroid Build Coastguard Worker       was_bound_or_message_sent_ = true;
301*6777b538SAndroid Build Coastguard Worker       DETACH_FROM_SEQUENCE(sequence_checker_);
302*6777b538SAndroid Build Coastguard Worker     }
303*6777b538SAndroid Build Coastguard Worker   }
304*6777b538SAndroid Build Coastguard Worker 
StartReceiving()305*6777b538SAndroid Build Coastguard Worker   void StartReceiving() {
306*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
307*6777b538SAndroid Build Coastguard Worker     CHECK(was_bound_or_message_sent_);
308*6777b538SAndroid Build Coastguard Worker     connector_->StartReceiving(task_runner_);
309*6777b538SAndroid Build Coastguard Worker   }
310*6777b538SAndroid Build Coastguard Worker 
ShutDown()311*6777b538SAndroid Build Coastguard Worker   void ShutDown() {
312*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
313*6777b538SAndroid Build Coastguard Worker     shut_down_ = true;
314*6777b538SAndroid Build Coastguard Worker     if (connector_)
315*6777b538SAndroid Build Coastguard Worker       connector_->CloseMessagePipe();
316*6777b538SAndroid Build Coastguard Worker     OnPipeError();
317*6777b538SAndroid Build Coastguard Worker     connector_.reset();
318*6777b538SAndroid Build Coastguard Worker 
319*6777b538SAndroid Build Coastguard Worker     base::AutoLock lock(outgoing_messages_lock_);
320*6777b538SAndroid Build Coastguard Worker     outgoing_messages_.clear();
321*6777b538SAndroid Build Coastguard Worker   }
322*6777b538SAndroid Build Coastguard Worker 
323*6777b538SAndroid Build Coastguard Worker   // mojo::AssociatedGroupController:
AssociateInterface(mojo::ScopedInterfaceEndpointHandle handle_to_send)324*6777b538SAndroid Build Coastguard Worker   mojo::InterfaceId AssociateInterface(
325*6777b538SAndroid Build Coastguard Worker       mojo::ScopedInterfaceEndpointHandle handle_to_send) override {
326*6777b538SAndroid Build Coastguard Worker     if (!handle_to_send.pending_association())
327*6777b538SAndroid Build Coastguard Worker       return mojo::kInvalidInterfaceId;
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker     uint32_t id = 0;
330*6777b538SAndroid Build Coastguard Worker     {
331*6777b538SAndroid Build Coastguard Worker       base::AutoLock locker(lock_);
332*6777b538SAndroid Build Coastguard Worker       do {
333*6777b538SAndroid Build Coastguard Worker         if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
334*6777b538SAndroid Build Coastguard Worker           next_interface_id_ = 2;
335*6777b538SAndroid Build Coastguard Worker         id = next_interface_id_++;
336*6777b538SAndroid Build Coastguard Worker         if (set_interface_id_namespace_bit_)
337*6777b538SAndroid Build Coastguard Worker           id |= mojo::kInterfaceIdNamespaceMask;
338*6777b538SAndroid Build Coastguard Worker       } while (base::Contains(endpoints_, id));
339*6777b538SAndroid Build Coastguard Worker 
340*6777b538SAndroid Build Coastguard Worker       Endpoint* endpoint = new Endpoint(this, id);
341*6777b538SAndroid Build Coastguard Worker       if (encountered_error_)
342*6777b538SAndroid Build Coastguard Worker         endpoint->set_peer_closed();
343*6777b538SAndroid Build Coastguard Worker       endpoint->set_handle_created();
344*6777b538SAndroid Build Coastguard Worker       endpoints_.insert({id, endpoint});
345*6777b538SAndroid Build Coastguard Worker     }
346*6777b538SAndroid Build Coastguard Worker 
347*6777b538SAndroid Build Coastguard Worker     if (!NotifyAssociation(&handle_to_send, id)) {
348*6777b538SAndroid Build Coastguard Worker       // The peer handle of |handle_to_send|, which is supposed to join this
349*6777b538SAndroid Build Coastguard Worker       // associated group, has been closed.
350*6777b538SAndroid Build Coastguard Worker       {
351*6777b538SAndroid Build Coastguard Worker         base::AutoLock locker(lock_);
352*6777b538SAndroid Build Coastguard Worker         Endpoint* endpoint = FindEndpoint(id);
353*6777b538SAndroid Build Coastguard Worker         if (endpoint)
354*6777b538SAndroid Build Coastguard Worker           MarkClosedAndMaybeRemove(endpoint);
355*6777b538SAndroid Build Coastguard Worker       }
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker       control_message_proxy_.NotifyPeerEndpointClosed(
358*6777b538SAndroid Build Coastguard Worker           id, handle_to_send.disconnect_reason());
359*6777b538SAndroid Build Coastguard Worker     }
360*6777b538SAndroid Build Coastguard Worker     return id;
361*6777b538SAndroid Build Coastguard Worker   }
362*6777b538SAndroid Build Coastguard Worker 
CreateLocalEndpointHandle(mojo::InterfaceId id)363*6777b538SAndroid Build Coastguard Worker   mojo::ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(
364*6777b538SAndroid Build Coastguard Worker       mojo::InterfaceId id) override {
365*6777b538SAndroid Build Coastguard Worker     if (!mojo::IsValidInterfaceId(id))
366*6777b538SAndroid Build Coastguard Worker       return mojo::ScopedInterfaceEndpointHandle();
367*6777b538SAndroid Build Coastguard Worker 
368*6777b538SAndroid Build Coastguard Worker     // Unless it is the primary ID, |id| is from the remote side and therefore
369*6777b538SAndroid Build Coastguard Worker     // its namespace bit is supposed to be different than the value that this
370*6777b538SAndroid Build Coastguard Worker     // router would use.
371*6777b538SAndroid Build Coastguard Worker     if (!mojo::IsPrimaryInterfaceId(id) &&
372*6777b538SAndroid Build Coastguard Worker         set_interface_id_namespace_bit_ ==
373*6777b538SAndroid Build Coastguard Worker             mojo::HasInterfaceIdNamespaceBitSet(id)) {
374*6777b538SAndroid Build Coastguard Worker       return mojo::ScopedInterfaceEndpointHandle();
375*6777b538SAndroid Build Coastguard Worker     }
376*6777b538SAndroid Build Coastguard Worker 
377*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
378*6777b538SAndroid Build Coastguard Worker     bool inserted = false;
379*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
380*6777b538SAndroid Build Coastguard Worker     if (inserted) {
381*6777b538SAndroid Build Coastguard Worker       DCHECK(!endpoint->handle_created());
382*6777b538SAndroid Build Coastguard Worker       if (encountered_error_)
383*6777b538SAndroid Build Coastguard Worker         endpoint->set_peer_closed();
384*6777b538SAndroid Build Coastguard Worker     } else {
385*6777b538SAndroid Build Coastguard Worker       if (endpoint->handle_created())
386*6777b538SAndroid Build Coastguard Worker         return mojo::ScopedInterfaceEndpointHandle();
387*6777b538SAndroid Build Coastguard Worker     }
388*6777b538SAndroid Build Coastguard Worker 
389*6777b538SAndroid Build Coastguard Worker     endpoint->set_handle_created();
390*6777b538SAndroid Build Coastguard Worker     return CreateScopedInterfaceEndpointHandle(id);
391*6777b538SAndroid Build Coastguard Worker   }
392*6777b538SAndroid Build Coastguard Worker 
CloseEndpointHandle(mojo::InterfaceId id,const std::optional<mojo::DisconnectReason> & reason)393*6777b538SAndroid Build Coastguard Worker   void CloseEndpointHandle(
394*6777b538SAndroid Build Coastguard Worker       mojo::InterfaceId id,
395*6777b538SAndroid Build Coastguard Worker       const std::optional<mojo::DisconnectReason>& reason) override {
396*6777b538SAndroid Build Coastguard Worker     if (!mojo::IsValidInterfaceId(id))
397*6777b538SAndroid Build Coastguard Worker       return;
398*6777b538SAndroid Build Coastguard Worker     {
399*6777b538SAndroid Build Coastguard Worker       base::AutoLock locker(lock_);
400*6777b538SAndroid Build Coastguard Worker       DCHECK(base::Contains(endpoints_, id));
401*6777b538SAndroid Build Coastguard Worker       Endpoint* endpoint = endpoints_[id].get();
402*6777b538SAndroid Build Coastguard Worker       DCHECK(!endpoint->client());
403*6777b538SAndroid Build Coastguard Worker       DCHECK(!endpoint->closed());
404*6777b538SAndroid Build Coastguard Worker       MarkClosedAndMaybeRemove(endpoint);
405*6777b538SAndroid Build Coastguard Worker     }
406*6777b538SAndroid Build Coastguard Worker 
407*6777b538SAndroid Build Coastguard Worker     if (!mojo::IsPrimaryInterfaceId(id) || reason)
408*6777b538SAndroid Build Coastguard Worker       control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
409*6777b538SAndroid Build Coastguard Worker   }
410*6777b538SAndroid Build Coastguard Worker 
NotifyLocalEndpointOfPeerClosure(mojo::InterfaceId id)411*6777b538SAndroid Build Coastguard Worker   void NotifyLocalEndpointOfPeerClosure(mojo::InterfaceId id) override {
412*6777b538SAndroid Build Coastguard Worker     if (!base::FeatureList::IsEnabled(
413*6777b538SAndroid Build Coastguard Worker             mojo::features::kMojoFixAssociatedHandleLeak)) {
414*6777b538SAndroid Build Coastguard Worker       return;
415*6777b538SAndroid Build Coastguard Worker     }
416*6777b538SAndroid Build Coastguard Worker 
417*6777b538SAndroid Build Coastguard Worker     if (!task_runner_->RunsTasksInCurrentSequence()) {
418*6777b538SAndroid Build Coastguard Worker       task_runner_->PostTask(
419*6777b538SAndroid Build Coastguard Worker           FROM_HERE, base::BindOnce(&ChannelAssociatedGroupController::
420*6777b538SAndroid Build Coastguard Worker                                         NotifyLocalEndpointOfPeerClosure,
421*6777b538SAndroid Build Coastguard Worker                                     base::WrapRefCounted(this), id));
422*6777b538SAndroid Build Coastguard Worker       return;
423*6777b538SAndroid Build Coastguard Worker     }
424*6777b538SAndroid Build Coastguard Worker     OnPeerAssociatedEndpointClosed(id, std::nullopt);
425*6777b538SAndroid Build Coastguard Worker   }
426*6777b538SAndroid Build Coastguard Worker 
AttachEndpointClient(const mojo::ScopedInterfaceEndpointHandle & handle,mojo::InterfaceEndpointClient * client,scoped_refptr<base::SequencedTaskRunner> runner)427*6777b538SAndroid Build Coastguard Worker   mojo::InterfaceEndpointController* AttachEndpointClient(
428*6777b538SAndroid Build Coastguard Worker       const mojo::ScopedInterfaceEndpointHandle& handle,
429*6777b538SAndroid Build Coastguard Worker       mojo::InterfaceEndpointClient* client,
430*6777b538SAndroid Build Coastguard Worker       scoped_refptr<base::SequencedTaskRunner> runner) override {
431*6777b538SAndroid Build Coastguard Worker     const mojo::InterfaceId id = handle.id();
432*6777b538SAndroid Build Coastguard Worker 
433*6777b538SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id));
434*6777b538SAndroid Build Coastguard Worker     DCHECK(client);
435*6777b538SAndroid Build Coastguard Worker 
436*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
437*6777b538SAndroid Build Coastguard Worker     DCHECK(base::Contains(endpoints_, id));
438*6777b538SAndroid Build Coastguard Worker 
439*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = endpoints_[id].get();
440*6777b538SAndroid Build Coastguard Worker     endpoint->AttachClient(client, std::move(runner));
441*6777b538SAndroid Build Coastguard Worker 
442*6777b538SAndroid Build Coastguard Worker     if (endpoint->peer_closed())
443*6777b538SAndroid Build Coastguard Worker       NotifyEndpointOfError(endpoint, true /* force_async */);
444*6777b538SAndroid Build Coastguard Worker 
445*6777b538SAndroid Build Coastguard Worker     return endpoint;
446*6777b538SAndroid Build Coastguard Worker   }
447*6777b538SAndroid Build Coastguard Worker 
DetachEndpointClient(const mojo::ScopedInterfaceEndpointHandle & handle)448*6777b538SAndroid Build Coastguard Worker   void DetachEndpointClient(
449*6777b538SAndroid Build Coastguard Worker       const mojo::ScopedInterfaceEndpointHandle& handle) override {
450*6777b538SAndroid Build Coastguard Worker     const mojo::InterfaceId id = handle.id();
451*6777b538SAndroid Build Coastguard Worker 
452*6777b538SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id));
453*6777b538SAndroid Build Coastguard Worker 
454*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
455*6777b538SAndroid Build Coastguard Worker     DCHECK(base::Contains(endpoints_, id));
456*6777b538SAndroid Build Coastguard Worker 
457*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = endpoints_[id].get();
458*6777b538SAndroid Build Coastguard Worker     endpoint->DetachClient();
459*6777b538SAndroid Build Coastguard Worker   }
460*6777b538SAndroid Build Coastguard Worker 
RaiseError()461*6777b538SAndroid Build Coastguard Worker   void RaiseError() override {
462*6777b538SAndroid Build Coastguard Worker     // We ignore errors on channel endpoints, leaving the pipe open. There are
463*6777b538SAndroid Build Coastguard Worker     // good reasons for this:
464*6777b538SAndroid Build Coastguard Worker     //
465*6777b538SAndroid Build Coastguard Worker     //   * We should never close a channel endpoint in either process as long as
466*6777b538SAndroid Build Coastguard Worker     //     the child process is still alive. The child's endpoint should only be
467*6777b538SAndroid Build Coastguard Worker     //     closed implicitly by process death, and the browser's endpoint should
468*6777b538SAndroid Build Coastguard Worker     //     only be closed after the child process is confirmed to be dead. Crash
469*6777b538SAndroid Build Coastguard Worker     //     reporting logic in Chrome relies on this behavior in order to do the
470*6777b538SAndroid Build Coastguard Worker     //     right thing.
471*6777b538SAndroid Build Coastguard Worker     //
472*6777b538SAndroid Build Coastguard Worker     //   * There are two interesting conditions under which RaiseError() can be
473*6777b538SAndroid Build Coastguard Worker     //     implicitly reached: an incoming message fails validation, or the
474*6777b538SAndroid Build Coastguard Worker     //     local endpoint drops a response callback without calling it.
475*6777b538SAndroid Build Coastguard Worker     //
476*6777b538SAndroid Build Coastguard Worker     //   * In the validation case, we also report the message as bad, and this
477*6777b538SAndroid Build Coastguard Worker     //     will imminently trigger the common bad-IPC path in the browser,
478*6777b538SAndroid Build Coastguard Worker     //     causing the browser to kill the offending renderer.
479*6777b538SAndroid Build Coastguard Worker     //
480*6777b538SAndroid Build Coastguard Worker     //   * In the dropped response callback case, the net result of ignoring the
481*6777b538SAndroid Build Coastguard Worker     //     issue is generally innocuous. While indicative of programmer error,
482*6777b538SAndroid Build Coastguard Worker     //     it's not a severe failure and is already covered by separate DCHECKs.
483*6777b538SAndroid Build Coastguard Worker     //
484*6777b538SAndroid Build Coastguard Worker     // See https://crbug.com/861607 for additional discussion.
485*6777b538SAndroid Build Coastguard Worker   }
486*6777b538SAndroid Build Coastguard Worker 
PrefersSerializedMessages()487*6777b538SAndroid Build Coastguard Worker   bool PrefersSerializedMessages() override { return true; }
488*6777b538SAndroid Build Coastguard Worker 
SetUrgentMessageObserver(UrgentMessageObserver * observer)489*6777b538SAndroid Build Coastguard Worker   void SetUrgentMessageObserver(UrgentMessageObserver* observer) {
490*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
491*6777b538SAndroid Build Coastguard Worker     CHECK(!was_bound_or_message_sent_);
492*6777b538SAndroid Build Coastguard Worker     urgent_message_observer_ = observer;
493*6777b538SAndroid Build Coastguard Worker     DETACH_FROM_SEQUENCE(sequence_checker_);
494*6777b538SAndroid Build Coastguard Worker   }
495*6777b538SAndroid Build Coastguard Worker 
496*6777b538SAndroid Build Coastguard Worker  private:
497*6777b538SAndroid Build Coastguard Worker   class Endpoint;
498*6777b538SAndroid Build Coastguard Worker   class ControlMessageProxyThunk;
499*6777b538SAndroid Build Coastguard Worker   friend class Endpoint;
500*6777b538SAndroid Build Coastguard Worker   friend class ControlMessageProxyThunk;
501*6777b538SAndroid Build Coastguard Worker 
502*6777b538SAndroid Build Coastguard Worker   // MessageWrapper objects are always destroyed under the controller's lock. On
503*6777b538SAndroid Build Coastguard Worker   // destruction, if the message it wrappers contains
504*6777b538SAndroid Build Coastguard Worker   // ScopedInterfaceEndpointHandles (which cannot be destructed under the
505*6777b538SAndroid Build Coastguard Worker   // controller's lock), the wrapper unlocks to clean them up.
506*6777b538SAndroid Build Coastguard Worker   class MessageWrapper {
507*6777b538SAndroid Build Coastguard Worker    public:
508*6777b538SAndroid Build Coastguard Worker     MessageWrapper() = default;
509*6777b538SAndroid Build Coastguard Worker 
MessageWrapper(ChannelAssociatedGroupController * controller,mojo::Message message)510*6777b538SAndroid Build Coastguard Worker     MessageWrapper(ChannelAssociatedGroupController* controller,
511*6777b538SAndroid Build Coastguard Worker                    mojo::Message message)
512*6777b538SAndroid Build Coastguard Worker         : controller_(controller), value_(std::move(message)) {}
513*6777b538SAndroid Build Coastguard Worker 
MessageWrapper(MessageWrapper && other)514*6777b538SAndroid Build Coastguard Worker     MessageWrapper(MessageWrapper&& other)
515*6777b538SAndroid Build Coastguard Worker         : controller_(other.controller_), value_(std::move(other.value_)) {}
516*6777b538SAndroid Build Coastguard Worker 
517*6777b538SAndroid Build Coastguard Worker     MessageWrapper(const MessageWrapper&) = delete;
518*6777b538SAndroid Build Coastguard Worker     MessageWrapper& operator=(const MessageWrapper&) = delete;
519*6777b538SAndroid Build Coastguard Worker 
~MessageWrapper()520*6777b538SAndroid Build Coastguard Worker     ~MessageWrapper() {
521*6777b538SAndroid Build Coastguard Worker       if (value_.associated_endpoint_handles()->empty())
522*6777b538SAndroid Build Coastguard Worker         return;
523*6777b538SAndroid Build Coastguard Worker 
524*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
525*6777b538SAndroid Build Coastguard Worker       {
526*6777b538SAndroid Build Coastguard Worker         base::AutoUnlock unlocker(controller_->lock_);
527*6777b538SAndroid Build Coastguard Worker         value_.mutable_associated_endpoint_handles()->clear();
528*6777b538SAndroid Build Coastguard Worker       }
529*6777b538SAndroid Build Coastguard Worker     }
530*6777b538SAndroid Build Coastguard Worker 
operator =(MessageWrapper && other)531*6777b538SAndroid Build Coastguard Worker     MessageWrapper& operator=(MessageWrapper&& other) {
532*6777b538SAndroid Build Coastguard Worker       controller_ = other.controller_;
533*6777b538SAndroid Build Coastguard Worker       value_ = std::move(other.value_);
534*6777b538SAndroid Build Coastguard Worker       return *this;
535*6777b538SAndroid Build Coastguard Worker     }
536*6777b538SAndroid Build Coastguard Worker 
HasRequestId(uint64_t request_id)537*6777b538SAndroid Build Coastguard Worker     bool HasRequestId(uint64_t request_id) {
538*6777b538SAndroid Build Coastguard Worker       return !value_.IsNull() && value_.version() >= 1 &&
539*6777b538SAndroid Build Coastguard Worker              value_.header_v1()->request_id == request_id;
540*6777b538SAndroid Build Coastguard Worker     }
541*6777b538SAndroid Build Coastguard Worker 
value()542*6777b538SAndroid Build Coastguard Worker     mojo::Message& value() { return value_; }
543*6777b538SAndroid Build Coastguard Worker 
544*6777b538SAndroid Build Coastguard Worker    private:
545*6777b538SAndroid Build Coastguard Worker     raw_ptr<ChannelAssociatedGroupController> controller_ = nullptr;
546*6777b538SAndroid Build Coastguard Worker     mojo::Message value_;
547*6777b538SAndroid Build Coastguard Worker   };
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker   class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
550*6777b538SAndroid Build Coastguard Worker                    public mojo::InterfaceEndpointController {
551*6777b538SAndroid Build Coastguard Worker    public:
Endpoint(ChannelAssociatedGroupController * controller,mojo::InterfaceId id)552*6777b538SAndroid Build Coastguard Worker     Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
553*6777b538SAndroid Build Coastguard Worker         : controller_(controller), id_(id) {}
554*6777b538SAndroid Build Coastguard Worker 
555*6777b538SAndroid Build Coastguard Worker     Endpoint(const Endpoint&) = delete;
556*6777b538SAndroid Build Coastguard Worker     Endpoint& operator=(const Endpoint&) = delete;
557*6777b538SAndroid Build Coastguard Worker 
id() const558*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceId id() const { return id_; }
559*6777b538SAndroid Build Coastguard Worker 
closed() const560*6777b538SAndroid Build Coastguard Worker     bool closed() const {
561*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
562*6777b538SAndroid Build Coastguard Worker       return closed_;
563*6777b538SAndroid Build Coastguard Worker     }
564*6777b538SAndroid Build Coastguard Worker 
set_closed()565*6777b538SAndroid Build Coastguard Worker     void set_closed() {
566*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
567*6777b538SAndroid Build Coastguard Worker       closed_ = true;
568*6777b538SAndroid Build Coastguard Worker     }
569*6777b538SAndroid Build Coastguard Worker 
peer_closed() const570*6777b538SAndroid Build Coastguard Worker     bool peer_closed() const {
571*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
572*6777b538SAndroid Build Coastguard Worker       return peer_closed_;
573*6777b538SAndroid Build Coastguard Worker     }
574*6777b538SAndroid Build Coastguard Worker 
set_peer_closed()575*6777b538SAndroid Build Coastguard Worker     void set_peer_closed() {
576*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
577*6777b538SAndroid Build Coastguard Worker       peer_closed_ = true;
578*6777b538SAndroid Build Coastguard Worker     }
579*6777b538SAndroid Build Coastguard Worker 
handle_created() const580*6777b538SAndroid Build Coastguard Worker     bool handle_created() const {
581*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
582*6777b538SAndroid Build Coastguard Worker       return handle_created_;
583*6777b538SAndroid Build Coastguard Worker     }
584*6777b538SAndroid Build Coastguard Worker 
set_handle_created()585*6777b538SAndroid Build Coastguard Worker     void set_handle_created() {
586*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
587*6777b538SAndroid Build Coastguard Worker       handle_created_ = true;
588*6777b538SAndroid Build Coastguard Worker     }
589*6777b538SAndroid Build Coastguard Worker 
disconnect_reason() const590*6777b538SAndroid Build Coastguard Worker     const std::optional<mojo::DisconnectReason>& disconnect_reason() const {
591*6777b538SAndroid Build Coastguard Worker       return disconnect_reason_;
592*6777b538SAndroid Build Coastguard Worker     }
593*6777b538SAndroid Build Coastguard Worker 
set_disconnect_reason(const std::optional<mojo::DisconnectReason> & disconnect_reason)594*6777b538SAndroid Build Coastguard Worker     void set_disconnect_reason(
595*6777b538SAndroid Build Coastguard Worker         const std::optional<mojo::DisconnectReason>& disconnect_reason) {
596*6777b538SAndroid Build Coastguard Worker       disconnect_reason_ = disconnect_reason;
597*6777b538SAndroid Build Coastguard Worker     }
598*6777b538SAndroid Build Coastguard Worker 
task_runner() const599*6777b538SAndroid Build Coastguard Worker     base::SequencedTaskRunner* task_runner() const {
600*6777b538SAndroid Build Coastguard Worker       return task_runner_.get();
601*6777b538SAndroid Build Coastguard Worker     }
602*6777b538SAndroid Build Coastguard Worker 
was_bound_off_sequence() const603*6777b538SAndroid Build Coastguard Worker     bool was_bound_off_sequence() const { return was_bound_off_sequence_; }
604*6777b538SAndroid Build Coastguard Worker 
client() const605*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client() const {
606*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
607*6777b538SAndroid Build Coastguard Worker       return client_;
608*6777b538SAndroid Build Coastguard Worker     }
609*6777b538SAndroid Build Coastguard Worker 
AttachClient(mojo::InterfaceEndpointClient * client,scoped_refptr<base::SequencedTaskRunner> runner)610*6777b538SAndroid Build Coastguard Worker     void AttachClient(mojo::InterfaceEndpointClient* client,
611*6777b538SAndroid Build Coastguard Worker                       scoped_refptr<base::SequencedTaskRunner> runner) {
612*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
613*6777b538SAndroid Build Coastguard Worker       DCHECK(!client_);
614*6777b538SAndroid Build Coastguard Worker       DCHECK(!closed_);
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker       task_runner_ = std::move(runner);
617*6777b538SAndroid Build Coastguard Worker       client_ = client;
618*6777b538SAndroid Build Coastguard Worker 
619*6777b538SAndroid Build Coastguard Worker       if (off_sequence_binding_allowed) {
620*6777b538SAndroid Build Coastguard Worker         was_bound_off_sequence_ = true;
621*6777b538SAndroid Build Coastguard Worker       }
622*6777b538SAndroid Build Coastguard Worker     }
623*6777b538SAndroid Build Coastguard Worker 
DetachClient()624*6777b538SAndroid Build Coastguard Worker     void DetachClient() {
625*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
626*6777b538SAndroid Build Coastguard Worker       DCHECK(client_);
627*6777b538SAndroid Build Coastguard Worker       DCHECK(!closed_);
628*6777b538SAndroid Build Coastguard Worker 
629*6777b538SAndroid Build Coastguard Worker       task_runner_ = nullptr;
630*6777b538SAndroid Build Coastguard Worker       client_ = nullptr;
631*6777b538SAndroid Build Coastguard Worker       sync_watcher_.reset();
632*6777b538SAndroid Build Coastguard Worker     }
633*6777b538SAndroid Build Coastguard Worker 
EnqueueSyncMessage(MessageWrapper message)634*6777b538SAndroid Build Coastguard Worker     std::optional<uint32_t> EnqueueSyncMessage(MessageWrapper message) {
635*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
636*6777b538SAndroid Build Coastguard Worker       if (exclusive_wait_ && exclusive_wait_->TryFulfillingWith(message)) {
637*6777b538SAndroid Build Coastguard Worker         exclusive_wait_ = nullptr;
638*6777b538SAndroid Build Coastguard Worker         return std::nullopt;
639*6777b538SAndroid Build Coastguard Worker       }
640*6777b538SAndroid Build Coastguard Worker 
641*6777b538SAndroid Build Coastguard Worker       uint32_t id = GenerateSyncMessageId();
642*6777b538SAndroid Build Coastguard Worker       sync_messages_.emplace_back(id, std::move(message));
643*6777b538SAndroid Build Coastguard Worker       SignalSyncMessageEvent();
644*6777b538SAndroid Build Coastguard Worker       return id;
645*6777b538SAndroid Build Coastguard Worker     }
646*6777b538SAndroid Build Coastguard Worker 
SignalSyncMessageEvent()647*6777b538SAndroid Build Coastguard Worker     void SignalSyncMessageEvent() {
648*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
649*6777b538SAndroid Build Coastguard Worker 
650*6777b538SAndroid Build Coastguard Worker       if (sync_watcher_)
651*6777b538SAndroid Build Coastguard Worker         sync_watcher_->SignalEvent();
652*6777b538SAndroid Build Coastguard Worker     }
653*6777b538SAndroid Build Coastguard Worker 
PopSyncMessage(uint32_t id)654*6777b538SAndroid Build Coastguard Worker     MessageWrapper PopSyncMessage(uint32_t id) {
655*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
656*6777b538SAndroid Build Coastguard Worker       if (sync_messages_.empty() || sync_messages_.front().first != id)
657*6777b538SAndroid Build Coastguard Worker         return MessageWrapper();
658*6777b538SAndroid Build Coastguard Worker       MessageWrapper message = std::move(sync_messages_.front().second);
659*6777b538SAndroid Build Coastguard Worker       sync_messages_.pop_front();
660*6777b538SAndroid Build Coastguard Worker       return message;
661*6777b538SAndroid Build Coastguard Worker     }
662*6777b538SAndroid Build Coastguard Worker 
663*6777b538SAndroid Build Coastguard Worker     // mojo::InterfaceEndpointController:
SendMessage(mojo::Message * message)664*6777b538SAndroid Build Coastguard Worker     bool SendMessage(mojo::Message* message) override {
665*6777b538SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
666*6777b538SAndroid Build Coastguard Worker       message->set_interface_id(id_);
667*6777b538SAndroid Build Coastguard Worker       return controller_->SendMessage(message);
668*6777b538SAndroid Build Coastguard Worker     }
669*6777b538SAndroid Build Coastguard Worker 
AllowWokenUpBySyncWatchOnSameThread()670*6777b538SAndroid Build Coastguard Worker     void AllowWokenUpBySyncWatchOnSameThread() override {
671*6777b538SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
672*6777b538SAndroid Build Coastguard Worker 
673*6777b538SAndroid Build Coastguard Worker       EnsureSyncWatcherExists();
674*6777b538SAndroid Build Coastguard Worker       sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence();
675*6777b538SAndroid Build Coastguard Worker     }
676*6777b538SAndroid Build Coastguard Worker 
SyncWatch(const bool & should_stop)677*6777b538SAndroid Build Coastguard Worker     bool SyncWatch(const bool& should_stop) override {
678*6777b538SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
679*6777b538SAndroid Build Coastguard Worker 
680*6777b538SAndroid Build Coastguard Worker       // It's not legal to make sync calls from the primary endpoint's thread,
681*6777b538SAndroid Build Coastguard Worker       // and in fact they must only happen from the proxy task runner.
682*6777b538SAndroid Build Coastguard Worker       DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
683*6777b538SAndroid Build Coastguard Worker       DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
684*6777b538SAndroid Build Coastguard Worker 
685*6777b538SAndroid Build Coastguard Worker       EnsureSyncWatcherExists();
686*6777b538SAndroid Build Coastguard Worker       {
687*6777b538SAndroid Build Coastguard Worker         base::AutoLock locker(controller_->lock_);
688*6777b538SAndroid Build Coastguard Worker         if (peer_closed_) {
689*6777b538SAndroid Build Coastguard Worker           SignalSyncMessageEvent();
690*6777b538SAndroid Build Coastguard Worker         }
691*6777b538SAndroid Build Coastguard Worker       }
692*6777b538SAndroid Build Coastguard Worker       return sync_watcher_->SyncWatch(&should_stop);
693*6777b538SAndroid Build Coastguard Worker     }
694*6777b538SAndroid Build Coastguard Worker 
WaitForIncomingSyncReply(uint64_t request_id)695*6777b538SAndroid Build Coastguard Worker     MessageWrapper WaitForIncomingSyncReply(uint64_t request_id) {
696*6777b538SAndroid Build Coastguard Worker       std::optional<ExclusiveSyncWait> wait;
697*6777b538SAndroid Build Coastguard Worker       {
698*6777b538SAndroid Build Coastguard Worker         base::AutoLock lock(controller_->lock_);
699*6777b538SAndroid Build Coastguard Worker         for (auto& [id, message] : sync_messages_) {
700*6777b538SAndroid Build Coastguard Worker           if (message.HasRequestId(request_id)) {
701*6777b538SAndroid Build Coastguard Worker             return std::move(message);
702*6777b538SAndroid Build Coastguard Worker           }
703*6777b538SAndroid Build Coastguard Worker         }
704*6777b538SAndroid Build Coastguard Worker 
705*6777b538SAndroid Build Coastguard Worker         DCHECK(!exclusive_wait_);
706*6777b538SAndroid Build Coastguard Worker         wait.emplace(request_id);
707*6777b538SAndroid Build Coastguard Worker         exclusive_wait_ = &wait.value();
708*6777b538SAndroid Build Coastguard Worker       }
709*6777b538SAndroid Build Coastguard Worker 
710*6777b538SAndroid Build Coastguard Worker       wait->event.Wait();
711*6777b538SAndroid Build Coastguard Worker       return std::move(wait->message);
712*6777b538SAndroid Build Coastguard Worker     }
713*6777b538SAndroid Build Coastguard Worker 
SyncWatchExclusive(uint64_t request_id)714*6777b538SAndroid Build Coastguard Worker     bool SyncWatchExclusive(uint64_t request_id) override {
715*6777b538SAndroid Build Coastguard Worker       MessageWrapper message = WaitForIncomingSyncReply(request_id);
716*6777b538SAndroid Build Coastguard Worker       if (message.value().IsNull() || !client_) {
717*6777b538SAndroid Build Coastguard Worker         return false;
718*6777b538SAndroid Build Coastguard Worker       }
719*6777b538SAndroid Build Coastguard Worker 
720*6777b538SAndroid Build Coastguard Worker       if (!client_->HandleIncomingMessage(&message.value())) {
721*6777b538SAndroid Build Coastguard Worker         base::AutoLock locker(controller_->lock_);
722*6777b538SAndroid Build Coastguard Worker         controller_->RaiseError();
723*6777b538SAndroid Build Coastguard Worker         return false;
724*6777b538SAndroid Build Coastguard Worker       }
725*6777b538SAndroid Build Coastguard Worker 
726*6777b538SAndroid Build Coastguard Worker       return true;
727*6777b538SAndroid Build Coastguard Worker     }
728*6777b538SAndroid Build Coastguard Worker 
RegisterExternalSyncWaiter(uint64_t request_id)729*6777b538SAndroid Build Coastguard Worker     void RegisterExternalSyncWaiter(uint64_t request_id) override {}
730*6777b538SAndroid Build Coastguard Worker 
731*6777b538SAndroid Build Coastguard Worker    private:
732*6777b538SAndroid Build Coastguard Worker     friend class base::RefCountedThreadSafe<Endpoint>;
733*6777b538SAndroid Build Coastguard Worker 
~Endpoint()734*6777b538SAndroid Build Coastguard Worker     ~Endpoint() override {
735*6777b538SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
736*6777b538SAndroid Build Coastguard Worker       DCHECK(!client_);
737*6777b538SAndroid Build Coastguard Worker       DCHECK(closed_);
738*6777b538SAndroid Build Coastguard Worker       DCHECK(peer_closed_);
739*6777b538SAndroid Build Coastguard Worker       DCHECK(!sync_watcher_);
740*6777b538SAndroid Build Coastguard Worker       if (exclusive_wait_) {
741*6777b538SAndroid Build Coastguard Worker         exclusive_wait_->event.Signal();
742*6777b538SAndroid Build Coastguard Worker       }
743*6777b538SAndroid Build Coastguard Worker     }
744*6777b538SAndroid Build Coastguard Worker 
OnSyncMessageEventReady()745*6777b538SAndroid Build Coastguard Worker     void OnSyncMessageEventReady() {
746*6777b538SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
747*6777b538SAndroid Build Coastguard Worker 
748*6777b538SAndroid Build Coastguard Worker       // SUBTLE: The order of these scoped_refptrs matters.
749*6777b538SAndroid Build Coastguard Worker       // `controller_keepalive` MUST outlive `keepalive` because the Endpoint
750*6777b538SAndroid Build Coastguard Worker       // holds raw pointer to the AssociatedGroupController.
751*6777b538SAndroid Build Coastguard Worker       scoped_refptr<AssociatedGroupController> controller_keepalive(
752*6777b538SAndroid Build Coastguard Worker           controller_.get());
753*6777b538SAndroid Build Coastguard Worker       scoped_refptr<Endpoint> keepalive(this);
754*6777b538SAndroid Build Coastguard Worker       base::AutoLock locker(controller_->lock_);
755*6777b538SAndroid Build Coastguard Worker       bool more_to_process = false;
756*6777b538SAndroid Build Coastguard Worker       if (!sync_messages_.empty()) {
757*6777b538SAndroid Build Coastguard Worker         MessageWrapper message_wrapper =
758*6777b538SAndroid Build Coastguard Worker             std::move(sync_messages_.front().second);
759*6777b538SAndroid Build Coastguard Worker         sync_messages_.pop_front();
760*6777b538SAndroid Build Coastguard Worker 
761*6777b538SAndroid Build Coastguard Worker         bool dispatch_succeeded;
762*6777b538SAndroid Build Coastguard Worker         mojo::InterfaceEndpointClient* client = client_;
763*6777b538SAndroid Build Coastguard Worker         {
764*6777b538SAndroid Build Coastguard Worker           base::AutoUnlock unlocker(controller_->lock_);
765*6777b538SAndroid Build Coastguard Worker           dispatch_succeeded =
766*6777b538SAndroid Build Coastguard Worker               client->HandleIncomingMessage(&message_wrapper.value());
767*6777b538SAndroid Build Coastguard Worker         }
768*6777b538SAndroid Build Coastguard Worker 
769*6777b538SAndroid Build Coastguard Worker         if (!sync_messages_.empty())
770*6777b538SAndroid Build Coastguard Worker           more_to_process = true;
771*6777b538SAndroid Build Coastguard Worker 
772*6777b538SAndroid Build Coastguard Worker         if (!dispatch_succeeded)
773*6777b538SAndroid Build Coastguard Worker           controller_->RaiseError();
774*6777b538SAndroid Build Coastguard Worker       }
775*6777b538SAndroid Build Coastguard Worker 
776*6777b538SAndroid Build Coastguard Worker       if (!more_to_process)
777*6777b538SAndroid Build Coastguard Worker         sync_watcher_->ResetEvent();
778*6777b538SAndroid Build Coastguard Worker 
779*6777b538SAndroid Build Coastguard Worker       // If there are no queued sync messages and the peer has closed, there
780*6777b538SAndroid Build Coastguard Worker       // there won't be incoming sync messages in the future. If any
781*6777b538SAndroid Build Coastguard Worker       // SyncWatch() calls are on the stack for this endpoint, resetting the
782*6777b538SAndroid Build Coastguard Worker       // watcher will allow them to exit as the stack undwinds.
783*6777b538SAndroid Build Coastguard Worker       if (!more_to_process && peer_closed_)
784*6777b538SAndroid Build Coastguard Worker         sync_watcher_.reset();
785*6777b538SAndroid Build Coastguard Worker     }
786*6777b538SAndroid Build Coastguard Worker 
EnsureSyncWatcherExists()787*6777b538SAndroid Build Coastguard Worker     void EnsureSyncWatcherExists() {
788*6777b538SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
789*6777b538SAndroid Build Coastguard Worker       if (sync_watcher_)
790*6777b538SAndroid Build Coastguard Worker         return;
791*6777b538SAndroid Build Coastguard Worker 
792*6777b538SAndroid Build Coastguard Worker       base::AutoLock locker(controller_->lock_);
793*6777b538SAndroid Build Coastguard Worker       sync_watcher_ = std::make_unique<mojo::SequenceLocalSyncEventWatcher>(
794*6777b538SAndroid Build Coastguard Worker           base::BindRepeating(&Endpoint::OnSyncMessageEventReady,
795*6777b538SAndroid Build Coastguard Worker                               base::Unretained(this)));
796*6777b538SAndroid Build Coastguard Worker       if (peer_closed_ || !sync_messages_.empty())
797*6777b538SAndroid Build Coastguard Worker         SignalSyncMessageEvent();
798*6777b538SAndroid Build Coastguard Worker     }
799*6777b538SAndroid Build Coastguard Worker 
GenerateSyncMessageId()800*6777b538SAndroid Build Coastguard Worker     uint32_t GenerateSyncMessageId() {
801*6777b538SAndroid Build Coastguard Worker       // Overflow is fine.
802*6777b538SAndroid Build Coastguard Worker       uint32_t id = next_sync_message_id_++;
803*6777b538SAndroid Build Coastguard Worker       DCHECK(sync_messages_.empty() || sync_messages_.front().first != id);
804*6777b538SAndroid Build Coastguard Worker       return id;
805*6777b538SAndroid Build Coastguard Worker     }
806*6777b538SAndroid Build Coastguard Worker 
807*6777b538SAndroid Build Coastguard Worker     // Tracks the state of a pending sync wait which excludes all other incoming
808*6777b538SAndroid Build Coastguard Worker     // IPC on the waiting thread.
809*6777b538SAndroid Build Coastguard Worker     struct ExclusiveSyncWait {
ExclusiveSyncWaitIPC::ChannelAssociatedGroupController::Endpoint::ExclusiveSyncWait810*6777b538SAndroid Build Coastguard Worker       explicit ExclusiveSyncWait(uint64_t request_id)
811*6777b538SAndroid Build Coastguard Worker           : request_id(request_id) {}
812*6777b538SAndroid Build Coastguard Worker       ~ExclusiveSyncWait() = default;
813*6777b538SAndroid Build Coastguard Worker 
TryFulfillingWithIPC::ChannelAssociatedGroupController::Endpoint::ExclusiveSyncWait814*6777b538SAndroid Build Coastguard Worker       bool TryFulfillingWith(MessageWrapper& wrapper) {
815*6777b538SAndroid Build Coastguard Worker         if (!wrapper.HasRequestId(request_id)) {
816*6777b538SAndroid Build Coastguard Worker           return false;
817*6777b538SAndroid Build Coastguard Worker         }
818*6777b538SAndroid Build Coastguard Worker 
819*6777b538SAndroid Build Coastguard Worker         message = std::move(wrapper);
820*6777b538SAndroid Build Coastguard Worker         event.Signal();
821*6777b538SAndroid Build Coastguard Worker         return true;
822*6777b538SAndroid Build Coastguard Worker       }
823*6777b538SAndroid Build Coastguard Worker 
824*6777b538SAndroid Build Coastguard Worker       uint64_t request_id;
825*6777b538SAndroid Build Coastguard Worker       base::WaitableEvent event;
826*6777b538SAndroid Build Coastguard Worker       MessageWrapper message;
827*6777b538SAndroid Build Coastguard Worker     };
828*6777b538SAndroid Build Coastguard Worker 
829*6777b538SAndroid Build Coastguard Worker     const raw_ptr<ChannelAssociatedGroupController> controller_;
830*6777b538SAndroid Build Coastguard Worker     const mojo::InterfaceId id_;
831*6777b538SAndroid Build Coastguard Worker 
832*6777b538SAndroid Build Coastguard Worker     bool closed_ = false;
833*6777b538SAndroid Build Coastguard Worker     bool peer_closed_ = false;
834*6777b538SAndroid Build Coastguard Worker     bool handle_created_ = false;
835*6777b538SAndroid Build Coastguard Worker     bool was_bound_off_sequence_ = false;
836*6777b538SAndroid Build Coastguard Worker     std::optional<mojo::DisconnectReason> disconnect_reason_;
837*6777b538SAndroid Build Coastguard Worker     raw_ptr<mojo::InterfaceEndpointClient> client_ = nullptr;
838*6777b538SAndroid Build Coastguard Worker     scoped_refptr<base::SequencedTaskRunner> task_runner_;
839*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
840*6777b538SAndroid Build Coastguard Worker     base::circular_deque<std::pair<uint32_t, MessageWrapper>> sync_messages_;
841*6777b538SAndroid Build Coastguard Worker     raw_ptr<ExclusiveSyncWait> exclusive_wait_ = nullptr;
842*6777b538SAndroid Build Coastguard Worker     uint32_t next_sync_message_id_ = 0;
843*6777b538SAndroid Build Coastguard Worker   };
844*6777b538SAndroid Build Coastguard Worker 
845*6777b538SAndroid Build Coastguard Worker   class ControlMessageProxyThunk : public MessageReceiver {
846*6777b538SAndroid Build Coastguard Worker    public:
ControlMessageProxyThunk(ChannelAssociatedGroupController * controller)847*6777b538SAndroid Build Coastguard Worker     explicit ControlMessageProxyThunk(
848*6777b538SAndroid Build Coastguard Worker         ChannelAssociatedGroupController* controller)
849*6777b538SAndroid Build Coastguard Worker         : controller_(controller) {}
850*6777b538SAndroid Build Coastguard Worker 
851*6777b538SAndroid Build Coastguard Worker     ControlMessageProxyThunk(const ControlMessageProxyThunk&) = delete;
852*6777b538SAndroid Build Coastguard Worker     ControlMessageProxyThunk& operator=(const ControlMessageProxyThunk&) =
853*6777b538SAndroid Build Coastguard Worker         delete;
854*6777b538SAndroid Build Coastguard Worker 
855*6777b538SAndroid Build Coastguard Worker    private:
856*6777b538SAndroid Build Coastguard Worker     // MessageReceiver:
Accept(mojo::Message * message)857*6777b538SAndroid Build Coastguard Worker     bool Accept(mojo::Message* message) override {
858*6777b538SAndroid Build Coastguard Worker       return controller_->SendMessage(message);
859*6777b538SAndroid Build Coastguard Worker     }
860*6777b538SAndroid Build Coastguard Worker 
861*6777b538SAndroid Build Coastguard Worker     raw_ptr<ChannelAssociatedGroupController> controller_;
862*6777b538SAndroid Build Coastguard Worker   };
863*6777b538SAndroid Build Coastguard Worker 
~ChannelAssociatedGroupController()864*6777b538SAndroid Build Coastguard Worker   ~ChannelAssociatedGroupController() override {
865*6777b538SAndroid Build Coastguard Worker     DCHECK(!connector_);
866*6777b538SAndroid Build Coastguard Worker 
867*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
868*6777b538SAndroid Build Coastguard Worker     for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
869*6777b538SAndroid Build Coastguard Worker       Endpoint* endpoint = iter->second.get();
870*6777b538SAndroid Build Coastguard Worker       ++iter;
871*6777b538SAndroid Build Coastguard Worker 
872*6777b538SAndroid Build Coastguard Worker       if (!endpoint->closed()) {
873*6777b538SAndroid Build Coastguard Worker         // This happens when a NotifyPeerEndpointClosed message been received,
874*6777b538SAndroid Build Coastguard Worker         // but the interface ID hasn't been used to create local endpoint
875*6777b538SAndroid Build Coastguard Worker         // handle.
876*6777b538SAndroid Build Coastguard Worker         DCHECK(!endpoint->client());
877*6777b538SAndroid Build Coastguard Worker         DCHECK(endpoint->peer_closed());
878*6777b538SAndroid Build Coastguard Worker         MarkClosed(endpoint);
879*6777b538SAndroid Build Coastguard Worker       } else {
880*6777b538SAndroid Build Coastguard Worker         MarkPeerClosed(endpoint);
881*6777b538SAndroid Build Coastguard Worker       }
882*6777b538SAndroid Build Coastguard Worker     }
883*6777b538SAndroid Build Coastguard Worker     endpoints_.clear();
884*6777b538SAndroid Build Coastguard Worker 
885*6777b538SAndroid Build Coastguard Worker     GetMemoryDumpProvider().RemoveController(this);
886*6777b538SAndroid Build Coastguard Worker   }
887*6777b538SAndroid Build Coastguard Worker 
SendMessage(mojo::Message * message)888*6777b538SAndroid Build Coastguard Worker   bool SendMessage(mojo::Message* message) {
889*6777b538SAndroid Build Coastguard Worker     DCHECK(message->heap_profiler_tag());
890*6777b538SAndroid Build Coastguard Worker     if (task_runner_->BelongsToCurrentThread()) {
891*6777b538SAndroid Build Coastguard Worker       return SendMessageOnSequence(message);
892*6777b538SAndroid Build Coastguard Worker     }
893*6777b538SAndroid Build Coastguard Worker 
894*6777b538SAndroid Build Coastguard Worker     // PostTask (or RunOrPostTask) so that `message` is sent after messages from
895*6777b538SAndroid Build Coastguard Worker     // tasks that are already queued (e.g. by `IPC::ChannelProxy::Send`).
896*6777b538SAndroid Build Coastguard Worker     auto callback = base::BindOnce(
897*6777b538SAndroid Build Coastguard Worker         &ChannelAssociatedGroupController::SendMessageOnSequenceViaTask, this,
898*6777b538SAndroid Build Coastguard Worker         std::move(*message));
899*6777b538SAndroid Build Coastguard Worker     if (base::FeatureList::IsEnabled(
900*6777b538SAndroid Build Coastguard Worker             kMojoChannelAssociatedSendUsesRunOrPostTask)) {
901*6777b538SAndroid Build Coastguard Worker       task_runner_->RunOrPostTask(base::subtle::RunOrPostTaskPassKey(),
902*6777b538SAndroid Build Coastguard Worker                                   FROM_HERE, std::move(callback));
903*6777b538SAndroid Build Coastguard Worker     } else {
904*6777b538SAndroid Build Coastguard Worker       task_runner_->PostTask(FROM_HERE, std::move(callback));
905*6777b538SAndroid Build Coastguard Worker     }
906*6777b538SAndroid Build Coastguard Worker 
907*6777b538SAndroid Build Coastguard Worker     return true;
908*6777b538SAndroid Build Coastguard Worker   }
909*6777b538SAndroid Build Coastguard Worker 
SendMessageOnSequence(mojo::Message * message)910*6777b538SAndroid Build Coastguard Worker   bool SendMessageOnSequence(mojo::Message* message) {
911*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
912*6777b538SAndroid Build Coastguard Worker     was_bound_or_message_sent_ = true;
913*6777b538SAndroid Build Coastguard Worker 
914*6777b538SAndroid Build Coastguard Worker     if (!connector_ || paused_) {
915*6777b538SAndroid Build Coastguard Worker       if (!shut_down_) {
916*6777b538SAndroid Build Coastguard Worker         base::AutoLock lock(outgoing_messages_lock_);
917*6777b538SAndroid Build Coastguard Worker         outgoing_messages_.emplace_back(std::move(*message));
918*6777b538SAndroid Build Coastguard Worker       }
919*6777b538SAndroid Build Coastguard Worker       return true;
920*6777b538SAndroid Build Coastguard Worker     }
921*6777b538SAndroid Build Coastguard Worker     return connector_->Accept(message);
922*6777b538SAndroid Build Coastguard Worker   }
923*6777b538SAndroid Build Coastguard Worker 
SendMessageOnSequenceViaTask(mojo::Message message)924*6777b538SAndroid Build Coastguard Worker   void SendMessageOnSequenceViaTask(mojo::Message message) {
925*6777b538SAndroid Build Coastguard Worker     if (!SendMessageOnSequence(&message)) {
926*6777b538SAndroid Build Coastguard Worker       RaiseError();
927*6777b538SAndroid Build Coastguard Worker     }
928*6777b538SAndroid Build Coastguard Worker   }
929*6777b538SAndroid Build Coastguard Worker 
OnPipeError()930*6777b538SAndroid Build Coastguard Worker   void OnPipeError() {
931*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
932*6777b538SAndroid Build Coastguard Worker 
933*6777b538SAndroid Build Coastguard Worker     // We keep |this| alive here because it's possible for the notifications
934*6777b538SAndroid Build Coastguard Worker     // below to release all other references.
935*6777b538SAndroid Build Coastguard Worker     scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
936*6777b538SAndroid Build Coastguard Worker 
937*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
938*6777b538SAndroid Build Coastguard Worker     encountered_error_ = true;
939*6777b538SAndroid Build Coastguard Worker 
940*6777b538SAndroid Build Coastguard Worker     std::vector<uint32_t> endpoints_to_remove;
941*6777b538SAndroid Build Coastguard Worker     std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
942*6777b538SAndroid Build Coastguard Worker     for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
943*6777b538SAndroid Build Coastguard Worker       Endpoint* endpoint = iter->second.get();
944*6777b538SAndroid Build Coastguard Worker       ++iter;
945*6777b538SAndroid Build Coastguard Worker 
946*6777b538SAndroid Build Coastguard Worker       if (endpoint->client()) {
947*6777b538SAndroid Build Coastguard Worker         endpoints_to_notify.push_back(endpoint);
948*6777b538SAndroid Build Coastguard Worker       }
949*6777b538SAndroid Build Coastguard Worker 
950*6777b538SAndroid Build Coastguard Worker       if (MarkPeerClosed(endpoint)) {
951*6777b538SAndroid Build Coastguard Worker         endpoints_to_remove.push_back(endpoint->id());
952*6777b538SAndroid Build Coastguard Worker       }
953*6777b538SAndroid Build Coastguard Worker     }
954*6777b538SAndroid Build Coastguard Worker 
955*6777b538SAndroid Build Coastguard Worker     for (auto& endpoint : endpoints_to_notify) {
956*6777b538SAndroid Build Coastguard Worker       // Because a notification may in turn detach any endpoint, we have to
957*6777b538SAndroid Build Coastguard Worker       // check each client again here.
958*6777b538SAndroid Build Coastguard Worker       if (endpoint->client())
959*6777b538SAndroid Build Coastguard Worker         NotifyEndpointOfError(endpoint.get(), false /* force_async */);
960*6777b538SAndroid Build Coastguard Worker     }
961*6777b538SAndroid Build Coastguard Worker 
962*6777b538SAndroid Build Coastguard Worker     for (uint32_t id : endpoints_to_remove) {
963*6777b538SAndroid Build Coastguard Worker       endpoints_.erase(id);
964*6777b538SAndroid Build Coastguard Worker     }
965*6777b538SAndroid Build Coastguard Worker   }
966*6777b538SAndroid Build Coastguard Worker 
NotifyEndpointOfError(Endpoint * endpoint,bool force_async)967*6777b538SAndroid Build Coastguard Worker   void NotifyEndpointOfError(Endpoint* endpoint, bool force_async)
968*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCKS_REQUIRED(lock_) {
969*6777b538SAndroid Build Coastguard Worker     DCHECK(endpoint->task_runner() && endpoint->client());
970*6777b538SAndroid Build Coastguard Worker     if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) {
971*6777b538SAndroid Build Coastguard Worker       mojo::InterfaceEndpointClient* client = endpoint->client();
972*6777b538SAndroid Build Coastguard Worker       std::optional<mojo::DisconnectReason> reason(
973*6777b538SAndroid Build Coastguard Worker           endpoint->disconnect_reason());
974*6777b538SAndroid Build Coastguard Worker 
975*6777b538SAndroid Build Coastguard Worker       base::AutoUnlock unlocker(lock_);
976*6777b538SAndroid Build Coastguard Worker       client->NotifyError(reason);
977*6777b538SAndroid Build Coastguard Worker     } else {
978*6777b538SAndroid Build Coastguard Worker       endpoint->task_runner()->PostTask(
979*6777b538SAndroid Build Coastguard Worker           FROM_HERE,
980*6777b538SAndroid Build Coastguard Worker           base::BindOnce(&ChannelAssociatedGroupController::
981*6777b538SAndroid Build Coastguard Worker                              NotifyEndpointOfErrorOnEndpointThread,
982*6777b538SAndroid Build Coastguard Worker                          this, endpoint->id(),
983*6777b538SAndroid Build Coastguard Worker                          // This is safe as `endpoint` is verified to be in
984*6777b538SAndroid Build Coastguard Worker                          // `endpoints_` (a map with ownership) before use.
985*6777b538SAndroid Build Coastguard Worker                          base::UnsafeDangling(endpoint)));
986*6777b538SAndroid Build Coastguard Worker     }
987*6777b538SAndroid Build Coastguard Worker   }
988*6777b538SAndroid Build Coastguard Worker 
989*6777b538SAndroid Build Coastguard Worker   // `endpoint` might be a dangling ptr and must be checked before dereference.
NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,MayBeDangling<Endpoint> endpoint)990*6777b538SAndroid Build Coastguard Worker   void NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,
991*6777b538SAndroid Build Coastguard Worker                                              MayBeDangling<Endpoint> endpoint) {
992*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
993*6777b538SAndroid Build Coastguard Worker     auto iter = endpoints_.find(id);
994*6777b538SAndroid Build Coastguard Worker     if (iter == endpoints_.end() || iter->second.get() != endpoint)
995*6777b538SAndroid Build Coastguard Worker       return;
996*6777b538SAndroid Build Coastguard Worker     if (!endpoint->client())
997*6777b538SAndroid Build Coastguard Worker       return;
998*6777b538SAndroid Build Coastguard Worker 
999*6777b538SAndroid Build Coastguard Worker     DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
1000*6777b538SAndroid Build Coastguard Worker     NotifyEndpointOfError(endpoint, false /* force_async */);
1001*6777b538SAndroid Build Coastguard Worker   }
1002*6777b538SAndroid Build Coastguard Worker 
1003*6777b538SAndroid Build Coastguard Worker   // Marks `endpoint` as closed and returns true if and only if its peer was
1004*6777b538SAndroid Build Coastguard Worker   // also already closed.
MarkClosed(Endpoint * endpoint)1005*6777b538SAndroid Build Coastguard Worker   bool MarkClosed(Endpoint* endpoint) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1006*6777b538SAndroid Build Coastguard Worker     endpoint->set_closed();
1007*6777b538SAndroid Build Coastguard Worker     return endpoint->peer_closed();
1008*6777b538SAndroid Build Coastguard Worker   }
1009*6777b538SAndroid Build Coastguard Worker 
1010*6777b538SAndroid Build Coastguard Worker   // Marks `endpoint` as having a closed peer and returns true if and only if
1011*6777b538SAndroid Build Coastguard Worker   // `endpoint` itself was also already closed.
MarkPeerClosed(Endpoint * endpoint)1012*6777b538SAndroid Build Coastguard Worker   bool MarkPeerClosed(Endpoint* endpoint) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1013*6777b538SAndroid Build Coastguard Worker     endpoint->set_peer_closed();
1014*6777b538SAndroid Build Coastguard Worker     endpoint->SignalSyncMessageEvent();
1015*6777b538SAndroid Build Coastguard Worker     return endpoint->closed();
1016*6777b538SAndroid Build Coastguard Worker   }
1017*6777b538SAndroid Build Coastguard Worker 
MarkClosedAndMaybeRemove(Endpoint * endpoint)1018*6777b538SAndroid Build Coastguard Worker   void MarkClosedAndMaybeRemove(Endpoint* endpoint)
1019*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1020*6777b538SAndroid Build Coastguard Worker     if (MarkClosed(endpoint)) {
1021*6777b538SAndroid Build Coastguard Worker       endpoints_.erase(endpoint->id());
1022*6777b538SAndroid Build Coastguard Worker     }
1023*6777b538SAndroid Build Coastguard Worker   }
1024*6777b538SAndroid Build Coastguard Worker 
MarkPeerClosedAndMaybeRemove(Endpoint * endpoint)1025*6777b538SAndroid Build Coastguard Worker   void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint)
1026*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1027*6777b538SAndroid Build Coastguard Worker     if (MarkPeerClosed(endpoint)) {
1028*6777b538SAndroid Build Coastguard Worker       endpoints_.erase(endpoint->id());
1029*6777b538SAndroid Build Coastguard Worker     }
1030*6777b538SAndroid Build Coastguard Worker   }
1031*6777b538SAndroid Build Coastguard Worker 
FindOrInsertEndpoint(mojo::InterfaceId id,bool * inserted)1032*6777b538SAndroid Build Coastguard Worker   Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted)
1033*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1034*6777b538SAndroid Build Coastguard Worker     DCHECK(!inserted || !*inserted);
1035*6777b538SAndroid Build Coastguard Worker 
1036*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(id);
1037*6777b538SAndroid Build Coastguard Worker     if (!endpoint) {
1038*6777b538SAndroid Build Coastguard Worker       endpoint = new Endpoint(this, id);
1039*6777b538SAndroid Build Coastguard Worker       endpoints_.insert({id, endpoint});
1040*6777b538SAndroid Build Coastguard Worker       if (inserted)
1041*6777b538SAndroid Build Coastguard Worker         *inserted = true;
1042*6777b538SAndroid Build Coastguard Worker     }
1043*6777b538SAndroid Build Coastguard Worker     return endpoint;
1044*6777b538SAndroid Build Coastguard Worker   }
1045*6777b538SAndroid Build Coastguard Worker 
FindEndpoint(mojo::InterfaceId id)1046*6777b538SAndroid Build Coastguard Worker   Endpoint* FindEndpoint(mojo::InterfaceId id) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1047*6777b538SAndroid Build Coastguard Worker     auto iter = endpoints_.find(id);
1048*6777b538SAndroid Build Coastguard Worker     return iter != endpoints_.end() ? iter->second.get() : nullptr;
1049*6777b538SAndroid Build Coastguard Worker   }
1050*6777b538SAndroid Build Coastguard Worker 
1051*6777b538SAndroid Build Coastguard Worker   // mojo::MessageReceiver:
Accept(mojo::Message * message)1052*6777b538SAndroid Build Coastguard Worker   bool Accept(mojo::Message* message) override {
1053*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1054*6777b538SAndroid Build Coastguard Worker 
1055*6777b538SAndroid Build Coastguard Worker     if (!message->DeserializeAssociatedEndpointHandles(this))
1056*6777b538SAndroid Build Coastguard Worker       return false;
1057*6777b538SAndroid Build Coastguard Worker 
1058*6777b538SAndroid Build Coastguard Worker     if (mojo::PipeControlMessageHandler::IsPipeControlMessage(message))
1059*6777b538SAndroid Build Coastguard Worker       return control_message_handler_.Accept(message);
1060*6777b538SAndroid Build Coastguard Worker 
1061*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceId id = message->interface_id();
1062*6777b538SAndroid Build Coastguard Worker     if (!mojo::IsValidInterfaceId(id))
1063*6777b538SAndroid Build Coastguard Worker       return false;
1064*6777b538SAndroid Build Coastguard Worker 
1065*6777b538SAndroid Build Coastguard Worker     base::ReleasableAutoLock locker(&lock_);
1066*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(id);
1067*6777b538SAndroid Build Coastguard Worker     if (!endpoint)
1068*6777b538SAndroid Build Coastguard Worker       return true;
1069*6777b538SAndroid Build Coastguard Worker 
1070*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client = endpoint->client();
1071*6777b538SAndroid Build Coastguard Worker     if (!client || !endpoint->task_runner()->RunsTasksInCurrentSequence()) {
1072*6777b538SAndroid Build Coastguard Worker       // The ChannelProxy for this channel is bound to `proxy_task_runner_` and
1073*6777b538SAndroid Build Coastguard Worker       // by default legacy IPCs must dispatch to either the IO thread or the
1074*6777b538SAndroid Build Coastguard Worker       // proxy task runner. We generally impose the same constraint on
1075*6777b538SAndroid Build Coastguard Worker       // associated interface endpoints so that FIFO can be guaranteed across
1076*6777b538SAndroid Build Coastguard Worker       // all interfaces without stalling any of them to wait for a pending
1077*6777b538SAndroid Build Coastguard Worker       // endpoint to be bound.
1078*6777b538SAndroid Build Coastguard Worker       //
1079*6777b538SAndroid Build Coastguard Worker       // This allows us to assume that if an endpoint is not yet bound when we
1080*6777b538SAndroid Build Coastguard Worker       // receive a message targeting it, it *will* be bound on the proxy task
1081*6777b538SAndroid Build Coastguard Worker       // runner by the time a newly posted task runs there. Hence we simply post
1082*6777b538SAndroid Build Coastguard Worker       // a hopeful dispatch task to that task runner.
1083*6777b538SAndroid Build Coastguard Worker       //
1084*6777b538SAndroid Build Coastguard Worker       // As it turns out, there are even some instances of endpoints binding to
1085*6777b538SAndroid Build Coastguard Worker       // alternative (non-IO-thread, non-proxy) task runners, but still
1086*6777b538SAndroid Build Coastguard Worker       // ultimately relying on the fact that we schedule their messages on the
1087*6777b538SAndroid Build Coastguard Worker       // proxy task runner. So even if the endpoint is already bound, we
1088*6777b538SAndroid Build Coastguard Worker       // default to scheduling it on the proxy task runner as long as it's not
1089*6777b538SAndroid Build Coastguard Worker       // bound specifically to the IO task runner.
1090*6777b538SAndroid Build Coastguard Worker       // TODO(rockot): Try to sort out these cases and maybe eliminate them.
1091*6777b538SAndroid Build Coastguard Worker       //
1092*6777b538SAndroid Build Coastguard Worker       // Finally, it's also possible that an endpoint was bound to an
1093*6777b538SAndroid Build Coastguard Worker       // alternative task runner and it really does want its messages to
1094*6777b538SAndroid Build Coastguard Worker       // dispatch there. In that case `was_bound_off_sequence()` will be true to
1095*6777b538SAndroid Build Coastguard Worker       // signal that we should really use that task runner.
1096*6777b538SAndroid Build Coastguard Worker       const scoped_refptr<base::SequencedTaskRunner> task_runner =
1097*6777b538SAndroid Build Coastguard Worker           client && endpoint->was_bound_off_sequence()
1098*6777b538SAndroid Build Coastguard Worker               ? endpoint->task_runner()
1099*6777b538SAndroid Build Coastguard Worker               : proxy_task_runner_.get();
1100*6777b538SAndroid Build Coastguard Worker 
1101*6777b538SAndroid Build Coastguard Worker       ScopedUrgentMessageNotification scoped_urgent_message_notification(
1102*6777b538SAndroid Build Coastguard Worker           message->has_flag(mojo::Message::kFlagIsUrgent)
1103*6777b538SAndroid Build Coastguard Worker               ? urgent_message_observer_
1104*6777b538SAndroid Build Coastguard Worker               : nullptr);
1105*6777b538SAndroid Build Coastguard Worker 
1106*6777b538SAndroid Build Coastguard Worker       if (message->has_flag(mojo::Message::kFlagIsSync)) {
1107*6777b538SAndroid Build Coastguard Worker         MessageWrapper message_wrapper(this, std::move(*message));
1108*6777b538SAndroid Build Coastguard Worker         // Sync messages may need to be handled by the endpoint if it's blocking
1109*6777b538SAndroid Build Coastguard Worker         // on a sync reply. We pass ownership of the message to the endpoint's
1110*6777b538SAndroid Build Coastguard Worker         // sync message queue. If the endpoint was blocking, it will dequeue the
1111*6777b538SAndroid Build Coastguard Worker         // message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
1112*6777b538SAndroid Build Coastguard Worker         // call will dequeue the message and dispatch it.
1113*6777b538SAndroid Build Coastguard Worker         std::optional<uint32_t> message_id =
1114*6777b538SAndroid Build Coastguard Worker             endpoint->EnqueueSyncMessage(std::move(message_wrapper));
1115*6777b538SAndroid Build Coastguard Worker         if (message_id) {
1116*6777b538SAndroid Build Coastguard Worker           task_runner->PostTask(
1117*6777b538SAndroid Build Coastguard Worker               FROM_HERE,
1118*6777b538SAndroid Build Coastguard Worker               base::BindOnce(
1119*6777b538SAndroid Build Coastguard Worker                   &ChannelAssociatedGroupController::AcceptSyncMessage, this,
1120*6777b538SAndroid Build Coastguard Worker                   id, *message_id,
1121*6777b538SAndroid Build Coastguard Worker                   std::move(scoped_urgent_message_notification)));
1122*6777b538SAndroid Build Coastguard Worker         }
1123*6777b538SAndroid Build Coastguard Worker         return true;
1124*6777b538SAndroid Build Coastguard Worker       }
1125*6777b538SAndroid Build Coastguard Worker 
1126*6777b538SAndroid Build Coastguard Worker       // If |task_runner| has been torn down already, this PostTask will fail
1127*6777b538SAndroid Build Coastguard Worker       // and destroy |message|. That operation may need to in turn destroy
1128*6777b538SAndroid Build Coastguard Worker       // in-transit associated endpoints and thus acquire |lock_|. We no longer
1129*6777b538SAndroid Build Coastguard Worker       // need the lock to be held now, so we can release it before the PostTask.
1130*6777b538SAndroid Build Coastguard Worker       {
1131*6777b538SAndroid Build Coastguard Worker         // Grab interface name from |client| before releasing the lock to ensure
1132*6777b538SAndroid Build Coastguard Worker         // that |client| is safe to access.
1133*6777b538SAndroid Build Coastguard Worker         base::TaskAnnotator::ScopedSetIpcHash scoped_set_ipc_hash(
1134*6777b538SAndroid Build Coastguard Worker             client ? client->interface_name() : "unknown interface");
1135*6777b538SAndroid Build Coastguard Worker         locker.Release();
1136*6777b538SAndroid Build Coastguard Worker         task_runner->PostTask(
1137*6777b538SAndroid Build Coastguard Worker             FROM_HERE,
1138*6777b538SAndroid Build Coastguard Worker             base::BindOnce(
1139*6777b538SAndroid Build Coastguard Worker                 &ChannelAssociatedGroupController::AcceptOnEndpointThread, this,
1140*6777b538SAndroid Build Coastguard Worker                 std::move(*message),
1141*6777b538SAndroid Build Coastguard Worker                 std::move(scoped_urgent_message_notification)));
1142*6777b538SAndroid Build Coastguard Worker       }
1143*6777b538SAndroid Build Coastguard Worker       return true;
1144*6777b538SAndroid Build Coastguard Worker     }
1145*6777b538SAndroid Build Coastguard Worker 
1146*6777b538SAndroid Build Coastguard Worker     locker.Release();
1147*6777b538SAndroid Build Coastguard Worker     // It's safe to access |client| here without holding a lock, because this
1148*6777b538SAndroid Build Coastguard Worker     // code runs on a proxy thread and |client| can't be destroyed from any
1149*6777b538SAndroid Build Coastguard Worker     // thread.
1150*6777b538SAndroid Build Coastguard Worker     return client->HandleIncomingMessage(message);
1151*6777b538SAndroid Build Coastguard Worker   }
1152*6777b538SAndroid Build Coastguard Worker 
AcceptOnEndpointThread(mojo::Message message,ScopedUrgentMessageNotification scoped_urgent_message_notification)1153*6777b538SAndroid Build Coastguard Worker   void AcceptOnEndpointThread(
1154*6777b538SAndroid Build Coastguard Worker       mojo::Message message,
1155*6777b538SAndroid Build Coastguard Worker       ScopedUrgentMessageNotification scoped_urgent_message_notification) {
1156*6777b538SAndroid Build Coastguard Worker     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mojom"),
1157*6777b538SAndroid Build Coastguard Worker                  "ChannelAssociatedGroupController::AcceptOnEndpointThread");
1158*6777b538SAndroid Build Coastguard Worker 
1159*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceId id = message.interface_id();
1160*6777b538SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id) && !mojo::IsPrimaryInterfaceId(id));
1161*6777b538SAndroid Build Coastguard Worker 
1162*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
1163*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(id);
1164*6777b538SAndroid Build Coastguard Worker     if (!endpoint)
1165*6777b538SAndroid Build Coastguard Worker       return;
1166*6777b538SAndroid Build Coastguard Worker 
1167*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client = endpoint->client();
1168*6777b538SAndroid Build Coastguard Worker     if (!client)
1169*6777b538SAndroid Build Coastguard Worker       return;
1170*6777b538SAndroid Build Coastguard Worker 
1171*6777b538SAndroid Build Coastguard Worker     if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
1172*6777b538SAndroid Build Coastguard Worker         !proxy_task_runner_->RunsTasksInCurrentSequence()) {
1173*6777b538SAndroid Build Coastguard Worker       return;
1174*6777b538SAndroid Build Coastguard Worker     }
1175*6777b538SAndroid Build Coastguard Worker 
1176*6777b538SAndroid Build Coastguard Worker     // TODO(altimin): This event is temporarily kept as a debug fallback. Remove
1177*6777b538SAndroid Build Coastguard Worker     // it once the new implementation proves to be stable.
1178*6777b538SAndroid Build Coastguard Worker     TRACE_EVENT(
1179*6777b538SAndroid Build Coastguard Worker         TRACE_DISABLED_BY_DEFAULT("mojom"),
1180*6777b538SAndroid Build Coastguard Worker         // Using client->interface_name() is safe here because this is a static
1181*6777b538SAndroid Build Coastguard Worker         // string defined for each mojo interface.
1182*6777b538SAndroid Build Coastguard Worker         perfetto::StaticString(client->interface_name()),
1183*6777b538SAndroid Build Coastguard Worker         [&](perfetto::EventContext& ctx) {
1184*6777b538SAndroid Build Coastguard Worker           static const uint8_t* toplevel_flow_enabled =
1185*6777b538SAndroid Build Coastguard Worker               TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("toplevel.flow");
1186*6777b538SAndroid Build Coastguard Worker           if (!*toplevel_flow_enabled)
1187*6777b538SAndroid Build Coastguard Worker             return;
1188*6777b538SAndroid Build Coastguard Worker 
1189*6777b538SAndroid Build Coastguard Worker           perfetto::Flow::Global(message.GetTraceId())(ctx);
1190*6777b538SAndroid Build Coastguard Worker         });
1191*6777b538SAndroid Build Coastguard Worker 
1192*6777b538SAndroid Build Coastguard Worker     // Sync messages should never make their way to this method.
1193*6777b538SAndroid Build Coastguard Worker     DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
1194*6777b538SAndroid Build Coastguard Worker 
1195*6777b538SAndroid Build Coastguard Worker     bool result = false;
1196*6777b538SAndroid Build Coastguard Worker     {
1197*6777b538SAndroid Build Coastguard Worker       base::AutoUnlock unlocker(lock_);
1198*6777b538SAndroid Build Coastguard Worker       result = client->HandleIncomingMessage(&message);
1199*6777b538SAndroid Build Coastguard Worker     }
1200*6777b538SAndroid Build Coastguard Worker 
1201*6777b538SAndroid Build Coastguard Worker     if (!result)
1202*6777b538SAndroid Build Coastguard Worker       RaiseError();
1203*6777b538SAndroid Build Coastguard Worker   }
1204*6777b538SAndroid Build Coastguard Worker 
AcceptSyncMessage(mojo::InterfaceId interface_id,uint32_t message_id,ScopedUrgentMessageNotification scoped_urgent_message_notification)1205*6777b538SAndroid Build Coastguard Worker   void AcceptSyncMessage(
1206*6777b538SAndroid Build Coastguard Worker       mojo::InterfaceId interface_id,
1207*6777b538SAndroid Build Coastguard Worker       uint32_t message_id,
1208*6777b538SAndroid Build Coastguard Worker       ScopedUrgentMessageNotification scoped_urgent_message_notification) {
1209*6777b538SAndroid Build Coastguard Worker     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mojom"),
1210*6777b538SAndroid Build Coastguard Worker                  "ChannelAssociatedGroupController::AcceptSyncMessage");
1211*6777b538SAndroid Build Coastguard Worker 
1212*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
1213*6777b538SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(interface_id);
1214*6777b538SAndroid Build Coastguard Worker     if (!endpoint)
1215*6777b538SAndroid Build Coastguard Worker       return;
1216*6777b538SAndroid Build Coastguard Worker 
1217*6777b538SAndroid Build Coastguard Worker     // Careful, if the endpoint is detached its members are cleared. Check for
1218*6777b538SAndroid Build Coastguard Worker     // that before dereferencing.
1219*6777b538SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client = endpoint->client();
1220*6777b538SAndroid Build Coastguard Worker     if (!client)
1221*6777b538SAndroid Build Coastguard Worker       return;
1222*6777b538SAndroid Build Coastguard Worker 
1223*6777b538SAndroid Build Coastguard Worker     if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
1224*6777b538SAndroid Build Coastguard Worker         !proxy_task_runner_->RunsTasksInCurrentSequence()) {
1225*6777b538SAndroid Build Coastguard Worker       return;
1226*6777b538SAndroid Build Coastguard Worker     }
1227*6777b538SAndroid Build Coastguard Worker 
1228*6777b538SAndroid Build Coastguard Worker     // Using client->interface_name() is safe here because this is a static
1229*6777b538SAndroid Build Coastguard Worker     // string defined for each mojo interface.
1230*6777b538SAndroid Build Coastguard Worker     TRACE_EVENT0("mojom", client->interface_name());
1231*6777b538SAndroid Build Coastguard Worker     MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
1232*6777b538SAndroid Build Coastguard Worker 
1233*6777b538SAndroid Build Coastguard Worker     // The message must have already been dequeued by the endpoint waking up
1234*6777b538SAndroid Build Coastguard Worker     // from a sync wait. Nothing to do.
1235*6777b538SAndroid Build Coastguard Worker     if (message_wrapper.value().IsNull())
1236*6777b538SAndroid Build Coastguard Worker       return;
1237*6777b538SAndroid Build Coastguard Worker 
1238*6777b538SAndroid Build Coastguard Worker     bool result = false;
1239*6777b538SAndroid Build Coastguard Worker     {
1240*6777b538SAndroid Build Coastguard Worker       base::AutoUnlock unlocker(lock_);
1241*6777b538SAndroid Build Coastguard Worker       result = client->HandleIncomingMessage(&message_wrapper.value());
1242*6777b538SAndroid Build Coastguard Worker     }
1243*6777b538SAndroid Build Coastguard Worker 
1244*6777b538SAndroid Build Coastguard Worker     if (!result)
1245*6777b538SAndroid Build Coastguard Worker       RaiseError();
1246*6777b538SAndroid Build Coastguard Worker   }
1247*6777b538SAndroid Build Coastguard Worker 
1248*6777b538SAndroid Build Coastguard Worker   // mojo::PipeControlMessageHandlerDelegate:
OnPeerAssociatedEndpointClosed(mojo::InterfaceId id,const std::optional<mojo::DisconnectReason> & reason)1249*6777b538SAndroid Build Coastguard Worker   bool OnPeerAssociatedEndpointClosed(
1250*6777b538SAndroid Build Coastguard Worker       mojo::InterfaceId id,
1251*6777b538SAndroid Build Coastguard Worker       const std::optional<mojo::DisconnectReason>& reason) override {
1252*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1253*6777b538SAndroid Build Coastguard Worker 
1254*6777b538SAndroid Build Coastguard Worker     scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
1255*6777b538SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
1256*6777b538SAndroid Build Coastguard Worker     scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
1257*6777b538SAndroid Build Coastguard Worker     if (reason)
1258*6777b538SAndroid Build Coastguard Worker       endpoint->set_disconnect_reason(reason);
1259*6777b538SAndroid Build Coastguard Worker     if (!endpoint->peer_closed()) {
1260*6777b538SAndroid Build Coastguard Worker       if (endpoint->client())
1261*6777b538SAndroid Build Coastguard Worker         NotifyEndpointOfError(endpoint.get(), false /* force_async */);
1262*6777b538SAndroid Build Coastguard Worker       MarkPeerClosedAndMaybeRemove(endpoint.get());
1263*6777b538SAndroid Build Coastguard Worker     }
1264*6777b538SAndroid Build Coastguard Worker 
1265*6777b538SAndroid Build Coastguard Worker     return true;
1266*6777b538SAndroid Build Coastguard Worker   }
1267*6777b538SAndroid Build Coastguard Worker 
WaitForFlushToComplete(mojo::ScopedMessagePipeHandle flush_pipe)1268*6777b538SAndroid Build Coastguard Worker   bool WaitForFlushToComplete(
1269*6777b538SAndroid Build Coastguard Worker       mojo::ScopedMessagePipeHandle flush_pipe) override {
1270*6777b538SAndroid Build Coastguard Worker     // We don't support async flushing on the IPC Channel pipe.
1271*6777b538SAndroid Build Coastguard Worker     return false;
1272*6777b538SAndroid Build Coastguard Worker   }
1273*6777b538SAndroid Build Coastguard Worker 
1274*6777b538SAndroid Build Coastguard Worker   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
1275*6777b538SAndroid Build Coastguard Worker   const scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
1276*6777b538SAndroid Build Coastguard Worker   const bool set_interface_id_namespace_bit_;
1277*6777b538SAndroid Build Coastguard Worker 
1278*6777b538SAndroid Build Coastguard Worker   // Ensures sequenced access to members below.
1279*6777b538SAndroid Build Coastguard Worker   SEQUENCE_CHECKER(sequence_checker_);
1280*6777b538SAndroid Build Coastguard Worker 
1281*6777b538SAndroid Build Coastguard Worker   // Whether `Bind()` or `SendMessageOnSequence()` was called.
1282*6777b538SAndroid Build Coastguard Worker   // `sequence_checker_` can be detached when this is `false`.
1283*6777b538SAndroid Build Coastguard Worker   bool was_bound_or_message_sent_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
1284*6777b538SAndroid Build Coastguard Worker 
1285*6777b538SAndroid Build Coastguard Worker   bool paused_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
1286*6777b538SAndroid Build Coastguard Worker   bool shut_down_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
1287*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<mojo::Connector> connector_
1288*6777b538SAndroid Build Coastguard Worker       GUARDED_BY_CONTEXT(sequence_checker_);
1289*6777b538SAndroid Build Coastguard Worker   mojo::MessageDispatcher dispatcher_ GUARDED_BY_CONTEXT(sequence_checker_);
1290*6777b538SAndroid Build Coastguard Worker   mojo::PipeControlMessageHandler control_message_handler_
1291*6777b538SAndroid Build Coastguard Worker       GUARDED_BY_CONTEXT(sequence_checker_);
1292*6777b538SAndroid Build Coastguard Worker   ControlMessageProxyThunk control_message_proxy_thunk_
1293*6777b538SAndroid Build Coastguard Worker       GUARDED_BY_CONTEXT(sequence_checker_);
1294*6777b538SAndroid Build Coastguard Worker   raw_ptr<UrgentMessageObserver> urgent_message_observer_
1295*6777b538SAndroid Build Coastguard Worker       GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;
1296*6777b538SAndroid Build Coastguard Worker 
1297*6777b538SAndroid Build Coastguard Worker   // NOTE: It is unsafe to call into this object while holding |lock_|.
1298*6777b538SAndroid Build Coastguard Worker   mojo::PipeControlMessageProxy control_message_proxy_;
1299*6777b538SAndroid Build Coastguard Worker 
1300*6777b538SAndroid Build Coastguard Worker   // Outgoing messages sent before this controller Bound() to a pipe or while it
1301*6777b538SAndroid Build Coastguard Worker   // was paused. Protected by a lock to support memory dumps from any thread.
1302*6777b538SAndroid Build Coastguard Worker   base::Lock outgoing_messages_lock_;
1303*6777b538SAndroid Build Coastguard Worker   std::vector<mojo::Message> outgoing_messages_
1304*6777b538SAndroid Build Coastguard Worker       GUARDED_BY(outgoing_messages_lock_);
1305*6777b538SAndroid Build Coastguard Worker 
1306*6777b538SAndroid Build Coastguard Worker   // Guards the fields below for thread-safe access.
1307*6777b538SAndroid Build Coastguard Worker   base::Lock lock_;
1308*6777b538SAndroid Build Coastguard Worker 
1309*6777b538SAndroid Build Coastguard Worker   bool encountered_error_ GUARDED_BY(lock_) = false;
1310*6777b538SAndroid Build Coastguard Worker 
1311*6777b538SAndroid Build Coastguard Worker   // ID #1 is reserved for the mojom::Channel interface.
1312*6777b538SAndroid Build Coastguard Worker   uint32_t next_interface_id_ GUARDED_BY(lock_) = 2;
1313*6777b538SAndroid Build Coastguard Worker 
1314*6777b538SAndroid Build Coastguard Worker   std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_ GUARDED_BY(lock_);
1315*6777b538SAndroid Build Coastguard Worker };
1316*6777b538SAndroid Build Coastguard Worker 
1317*6777b538SAndroid Build Coastguard Worker namespace {
1318*6777b538SAndroid Build Coastguard Worker 
OnMemoryDump(const base::trace_event::MemoryDumpArgs & args,base::trace_event::ProcessMemoryDump * pmd)1319*6777b538SAndroid Build Coastguard Worker bool ControllerMemoryDumpProvider::OnMemoryDump(
1320*6777b538SAndroid Build Coastguard Worker     const base::trace_event::MemoryDumpArgs& args,
1321*6777b538SAndroid Build Coastguard Worker     base::trace_event::ProcessMemoryDump* pmd) {
1322*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
1323*6777b538SAndroid Build Coastguard Worker   for (ChannelAssociatedGroupController* controller : controllers_) {
1324*6777b538SAndroid Build Coastguard Worker     base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
1325*6777b538SAndroid Build Coastguard Worker         base::StringPrintf("mojo/queued_ipc_channel_message/0x%" PRIxPTR,
1326*6777b538SAndroid Build Coastguard Worker                            reinterpret_cast<uintptr_t>(controller)));
1327*6777b538SAndroid Build Coastguard Worker     dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
1328*6777b538SAndroid Build Coastguard Worker                     base::trace_event::MemoryAllocatorDump::kUnitsObjects,
1329*6777b538SAndroid Build Coastguard Worker                     controller->GetQueuedMessageCount());
1330*6777b538SAndroid Build Coastguard Worker     MessageMemoryDumpInfo info;
1331*6777b538SAndroid Build Coastguard Worker     size_t count = 0;
1332*6777b538SAndroid Build Coastguard Worker     controller->GetTopQueuedMessageMemoryDumpInfo(&info, &count);
1333*6777b538SAndroid Build Coastguard Worker     dump->AddScalar("top_message_name", "id", info.id);
1334*6777b538SAndroid Build Coastguard Worker     dump->AddScalar("top_message_count",
1335*6777b538SAndroid Build Coastguard Worker                     base::trace_event::MemoryAllocatorDump::kUnitsObjects,
1336*6777b538SAndroid Build Coastguard Worker                     count);
1337*6777b538SAndroid Build Coastguard Worker 
1338*6777b538SAndroid Build Coastguard Worker     if (info.profiler_tag) {
1339*6777b538SAndroid Build Coastguard Worker       // TODO(ssid): Memory dumps currently do not support adding string
1340*6777b538SAndroid Build Coastguard Worker       // arguments in background dumps. So, add this value as a trace event for
1341*6777b538SAndroid Build Coastguard Worker       // now.
1342*6777b538SAndroid Build Coastguard Worker       TRACE_EVENT2(base::trace_event::MemoryDumpManager::kTraceCategory,
1343*6777b538SAndroid Build Coastguard Worker                    "ControllerMemoryDumpProvider::OnMemoryDump",
1344*6777b538SAndroid Build Coastguard Worker                    "top_queued_message_tag", info.profiler_tag,
1345*6777b538SAndroid Build Coastguard Worker                    "count", count);
1346*6777b538SAndroid Build Coastguard Worker     }
1347*6777b538SAndroid Build Coastguard Worker   }
1348*6777b538SAndroid Build Coastguard Worker 
1349*6777b538SAndroid Build Coastguard Worker   return true;
1350*6777b538SAndroid Build Coastguard Worker }
1351*6777b538SAndroid Build Coastguard Worker 
1352*6777b538SAndroid Build Coastguard Worker class MojoBootstrapImpl : public MojoBootstrap {
1353*6777b538SAndroid Build Coastguard Worker  public:
MojoBootstrapImpl(mojo::ScopedMessagePipeHandle handle,const scoped_refptr<ChannelAssociatedGroupController> controller)1354*6777b538SAndroid Build Coastguard Worker   MojoBootstrapImpl(
1355*6777b538SAndroid Build Coastguard Worker       mojo::ScopedMessagePipeHandle handle,
1356*6777b538SAndroid Build Coastguard Worker       const scoped_refptr<ChannelAssociatedGroupController> controller)
1357*6777b538SAndroid Build Coastguard Worker       : controller_(controller),
1358*6777b538SAndroid Build Coastguard Worker         associated_group_(controller),
1359*6777b538SAndroid Build Coastguard Worker         handle_(std::move(handle)) {}
1360*6777b538SAndroid Build Coastguard Worker 
1361*6777b538SAndroid Build Coastguard Worker   MojoBootstrapImpl(const MojoBootstrapImpl&) = delete;
1362*6777b538SAndroid Build Coastguard Worker   MojoBootstrapImpl& operator=(const MojoBootstrapImpl&) = delete;
1363*6777b538SAndroid Build Coastguard Worker 
~MojoBootstrapImpl()1364*6777b538SAndroid Build Coastguard Worker   ~MojoBootstrapImpl() override {
1365*6777b538SAndroid Build Coastguard Worker     controller_->ShutDown();
1366*6777b538SAndroid Build Coastguard Worker   }
1367*6777b538SAndroid Build Coastguard Worker 
1368*6777b538SAndroid Build Coastguard Worker  private:
Connect(mojo::PendingAssociatedRemote<mojom::Channel> * sender,mojo::PendingAssociatedReceiver<mojom::Channel> * receiver)1369*6777b538SAndroid Build Coastguard Worker   void Connect(
1370*6777b538SAndroid Build Coastguard Worker       mojo::PendingAssociatedRemote<mojom::Channel>* sender,
1371*6777b538SAndroid Build Coastguard Worker       mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) override {
1372*6777b538SAndroid Build Coastguard Worker     controller_->Bind(std::move(handle_), sender, receiver);
1373*6777b538SAndroid Build Coastguard Worker   }
1374*6777b538SAndroid Build Coastguard Worker 
StartReceiving()1375*6777b538SAndroid Build Coastguard Worker   void StartReceiving() override { controller_->StartReceiving(); }
1376*6777b538SAndroid Build Coastguard Worker 
Pause()1377*6777b538SAndroid Build Coastguard Worker   void Pause() override {
1378*6777b538SAndroid Build Coastguard Worker     controller_->Pause();
1379*6777b538SAndroid Build Coastguard Worker   }
1380*6777b538SAndroid Build Coastguard Worker 
Unpause()1381*6777b538SAndroid Build Coastguard Worker   void Unpause() override {
1382*6777b538SAndroid Build Coastguard Worker     controller_->Unpause();
1383*6777b538SAndroid Build Coastguard Worker   }
1384*6777b538SAndroid Build Coastguard Worker 
Flush()1385*6777b538SAndroid Build Coastguard Worker   void Flush() override {
1386*6777b538SAndroid Build Coastguard Worker     controller_->FlushOutgoingMessages();
1387*6777b538SAndroid Build Coastguard Worker   }
1388*6777b538SAndroid Build Coastguard Worker 
GetAssociatedGroup()1389*6777b538SAndroid Build Coastguard Worker   mojo::AssociatedGroup* GetAssociatedGroup() override {
1390*6777b538SAndroid Build Coastguard Worker     return &associated_group_;
1391*6777b538SAndroid Build Coastguard Worker   }
1392*6777b538SAndroid Build Coastguard Worker 
SetUrgentMessageObserver(UrgentMessageObserver * observer)1393*6777b538SAndroid Build Coastguard Worker   void SetUrgentMessageObserver(UrgentMessageObserver* observer) override {
1394*6777b538SAndroid Build Coastguard Worker     controller_->SetUrgentMessageObserver(observer);
1395*6777b538SAndroid Build Coastguard Worker   }
1396*6777b538SAndroid Build Coastguard Worker 
1397*6777b538SAndroid Build Coastguard Worker   scoped_refptr<ChannelAssociatedGroupController> controller_;
1398*6777b538SAndroid Build Coastguard Worker   mojo::AssociatedGroup associated_group_;
1399*6777b538SAndroid Build Coastguard Worker 
1400*6777b538SAndroid Build Coastguard Worker   mojo::ScopedMessagePipeHandle handle_;
1401*6777b538SAndroid Build Coastguard Worker };
1402*6777b538SAndroid Build Coastguard Worker 
1403*6777b538SAndroid Build Coastguard Worker }  // namespace
1404*6777b538SAndroid Build Coastguard Worker 
1405*6777b538SAndroid Build Coastguard Worker ScopedAllowOffSequenceChannelAssociatedBindings::
ScopedAllowOffSequenceChannelAssociatedBindings()1406*6777b538SAndroid Build Coastguard Worker     ScopedAllowOffSequenceChannelAssociatedBindings()
1407*6777b538SAndroid Build Coastguard Worker     : resetter_(&off_sequence_binding_allowed, true) {}
1408*6777b538SAndroid Build Coastguard Worker 
1409*6777b538SAndroid Build Coastguard Worker ScopedAllowOffSequenceChannelAssociatedBindings::
1410*6777b538SAndroid Build Coastguard Worker     ~ScopedAllowOffSequenceChannelAssociatedBindings() = default;
1411*6777b538SAndroid Build Coastguard Worker 
1412*6777b538SAndroid Build Coastguard Worker // static
Create(mojo::ScopedMessagePipeHandle handle,Channel::Mode mode,const scoped_refptr<base::SingleThreadTaskRunner> & ipc_task_runner,const scoped_refptr<base::SingleThreadTaskRunner> & proxy_task_runner)1413*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
1414*6777b538SAndroid Build Coastguard Worker     mojo::ScopedMessagePipeHandle handle,
1415*6777b538SAndroid Build Coastguard Worker     Channel::Mode mode,
1416*6777b538SAndroid Build Coastguard Worker     const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
1417*6777b538SAndroid Build Coastguard Worker     const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner) {
1418*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MojoBootstrapImpl>(
1419*6777b538SAndroid Build Coastguard Worker       std::move(handle),
1420*6777b538SAndroid Build Coastguard Worker       base::MakeRefCounted<ChannelAssociatedGroupController>(
1421*6777b538SAndroid Build Coastguard Worker           mode == Channel::MODE_SERVER, ipc_task_runner, proxy_task_runner));
1422*6777b538SAndroid Build Coastguard Worker }
1423*6777b538SAndroid Build Coastguard Worker 
1424*6777b538SAndroid Build Coastguard Worker }  // namespace IPC
1425