xref: /aosp_15_r20/external/libchrome/ipc/ipc_mojo_bootstrap.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_mojo_bootstrap.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <inttypes.h>
8*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <map>
11*635a8641SAndroid Build Coastguard Worker #include <memory>
12*635a8641SAndroid Build Coastguard Worker #include <set>
13*635a8641SAndroid Build Coastguard Worker #include <utility>
14*635a8641SAndroid Build Coastguard Worker #include <vector>
15*635a8641SAndroid Build Coastguard Worker 
16*635a8641SAndroid Build Coastguard Worker #include "base/callback.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/containers/queue.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
21*635a8641SAndroid Build Coastguard Worker #include "base/no_destructor.h"
22*635a8641SAndroid Build Coastguard Worker #include "base/sequenced_task_runner.h"
23*635a8641SAndroid Build Coastguard Worker #include "base/single_thread_task_runner.h"
24*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
25*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
26*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
27*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_task_runner_handle.h"
28*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/memory_allocator_dump.h"
29*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/memory_dump_manager.h"
30*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/memory_dump_provider.h"
31*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_channel.h"
32*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/associated_group.h"
33*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/associated_group_controller.h"
34*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/connector.h"
35*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
36*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
37*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/interface_id.h"
38*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/message.h"
39*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/message_header_validator.h"
40*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
41*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
42*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
43*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
44*635a8641SAndroid Build Coastguard Worker 
45*635a8641SAndroid Build Coastguard Worker namespace IPC {
46*635a8641SAndroid Build Coastguard Worker 
47*635a8641SAndroid Build Coastguard Worker namespace {
48*635a8641SAndroid Build Coastguard Worker 
49*635a8641SAndroid Build Coastguard Worker class ChannelAssociatedGroupController;
50*635a8641SAndroid Build Coastguard Worker 
51*635a8641SAndroid Build Coastguard Worker // Used to track some internal Channel state in pursuit of message leaks.
52*635a8641SAndroid Build Coastguard Worker //
53*635a8641SAndroid Build Coastguard Worker // TODO(https://crbug.com/813045): Remove this.
54*635a8641SAndroid Build Coastguard Worker class ControllerMemoryDumpProvider
55*635a8641SAndroid Build Coastguard Worker     : public base::trace_event::MemoryDumpProvider {
56*635a8641SAndroid Build Coastguard Worker  public:
ControllerMemoryDumpProvider()57*635a8641SAndroid Build Coastguard Worker   ControllerMemoryDumpProvider() {
58*635a8641SAndroid Build Coastguard Worker     base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
59*635a8641SAndroid Build Coastguard Worker         this, "IPCChannel", nullptr);
60*635a8641SAndroid Build Coastguard Worker   }
61*635a8641SAndroid Build Coastguard Worker 
~ControllerMemoryDumpProvider()62*635a8641SAndroid Build Coastguard Worker   ~ControllerMemoryDumpProvider() override {
63*635a8641SAndroid Build Coastguard Worker     base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
64*635a8641SAndroid Build Coastguard Worker         this);
65*635a8641SAndroid Build Coastguard Worker   }
66*635a8641SAndroid Build Coastguard Worker 
AddController(ChannelAssociatedGroupController * controller)67*635a8641SAndroid Build Coastguard Worker   void AddController(ChannelAssociatedGroupController* controller) {
68*635a8641SAndroid Build Coastguard Worker     base::AutoLock lock(lock_);
69*635a8641SAndroid Build Coastguard Worker     controllers_.insert(controller);
70*635a8641SAndroid Build Coastguard Worker   }
71*635a8641SAndroid Build Coastguard Worker 
RemoveController(ChannelAssociatedGroupController * controller)72*635a8641SAndroid Build Coastguard Worker   void RemoveController(ChannelAssociatedGroupController* controller) {
73*635a8641SAndroid Build Coastguard Worker     base::AutoLock lock(lock_);
74*635a8641SAndroid Build Coastguard Worker     controllers_.erase(controller);
75*635a8641SAndroid Build Coastguard Worker   }
76*635a8641SAndroid Build Coastguard Worker 
77*635a8641SAndroid Build Coastguard Worker   // base::trace_event::MemoryDumpProvider:
78*635a8641SAndroid Build Coastguard Worker   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
79*635a8641SAndroid Build Coastguard Worker                     base::trace_event::ProcessMemoryDump* pmd) override;
80*635a8641SAndroid Build Coastguard Worker 
81*635a8641SAndroid Build Coastguard Worker  private:
82*635a8641SAndroid Build Coastguard Worker   base::Lock lock_;
83*635a8641SAndroid Build Coastguard Worker   std::set<ChannelAssociatedGroupController*> controllers_;
84*635a8641SAndroid Build Coastguard Worker 
85*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ControllerMemoryDumpProvider);
86*635a8641SAndroid Build Coastguard Worker };
87*635a8641SAndroid Build Coastguard Worker 
GetMemoryDumpProvider()88*635a8641SAndroid Build Coastguard Worker ControllerMemoryDumpProvider& GetMemoryDumpProvider() {
89*635a8641SAndroid Build Coastguard Worker   static base::NoDestructor<ControllerMemoryDumpProvider> provider;
90*635a8641SAndroid Build Coastguard Worker   return *provider;
91*635a8641SAndroid Build Coastguard Worker }
92*635a8641SAndroid Build Coastguard Worker 
93*635a8641SAndroid Build Coastguard Worker class ChannelAssociatedGroupController
94*635a8641SAndroid Build Coastguard Worker     : public mojo::AssociatedGroupController,
95*635a8641SAndroid Build Coastguard Worker       public mojo::MessageReceiver,
96*635a8641SAndroid Build Coastguard Worker       public mojo::PipeControlMessageHandlerDelegate {
97*635a8641SAndroid 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)98*635a8641SAndroid Build Coastguard Worker   ChannelAssociatedGroupController(
99*635a8641SAndroid Build Coastguard Worker       bool set_interface_id_namespace_bit,
100*635a8641SAndroid Build Coastguard Worker       const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
101*635a8641SAndroid Build Coastguard Worker       const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner)
102*635a8641SAndroid Build Coastguard Worker       : task_runner_(ipc_task_runner),
103*635a8641SAndroid Build Coastguard Worker         proxy_task_runner_(proxy_task_runner),
104*635a8641SAndroid Build Coastguard Worker         set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
105*635a8641SAndroid Build Coastguard Worker         filters_(this),
106*635a8641SAndroid Build Coastguard Worker         control_message_handler_(this),
107*635a8641SAndroid Build Coastguard Worker         control_message_proxy_thunk_(this),
108*635a8641SAndroid Build Coastguard Worker         control_message_proxy_(&control_message_proxy_thunk_) {
109*635a8641SAndroid Build Coastguard Worker     thread_checker_.DetachFromThread();
110*635a8641SAndroid Build Coastguard Worker     control_message_handler_.SetDescription(
111*635a8641SAndroid Build Coastguard Worker         "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
112*635a8641SAndroid Build Coastguard Worker     filters_.Append<mojo::MessageHeaderValidator>(
113*635a8641SAndroid Build Coastguard Worker         "IPC::mojom::Bootstrap [master] MessageHeaderValidator");
114*635a8641SAndroid Build Coastguard Worker 
115*635a8641SAndroid Build Coastguard Worker     GetMemoryDumpProvider().AddController(this);
116*635a8641SAndroid Build Coastguard Worker   }
117*635a8641SAndroid Build Coastguard Worker 
GetQueuedMessageCount()118*635a8641SAndroid Build Coastguard Worker   size_t GetQueuedMessageCount() {
119*635a8641SAndroid Build Coastguard Worker     base::AutoLock lock(outgoing_messages_lock_);
120*635a8641SAndroid Build Coastguard Worker     return outgoing_messages_.size();
121*635a8641SAndroid Build Coastguard Worker   }
122*635a8641SAndroid Build Coastguard Worker 
Bind(mojo::ScopedMessagePipeHandle handle)123*635a8641SAndroid Build Coastguard Worker   void Bind(mojo::ScopedMessagePipeHandle handle) {
124*635a8641SAndroid Build Coastguard Worker     DCHECK(thread_checker_.CalledOnValidThread());
125*635a8641SAndroid Build Coastguard Worker     DCHECK(task_runner_->BelongsToCurrentThread());
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker     connector_.reset(new mojo::Connector(
128*635a8641SAndroid Build Coastguard Worker         std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
129*635a8641SAndroid Build Coastguard Worker         task_runner_));
130*635a8641SAndroid Build Coastguard Worker     connector_->set_incoming_receiver(&filters_);
131*635a8641SAndroid Build Coastguard Worker     connector_->set_connection_error_handler(
132*635a8641SAndroid Build Coastguard Worker         base::Bind(&ChannelAssociatedGroupController::OnPipeError,
133*635a8641SAndroid Build Coastguard Worker                    base::Unretained(this)));
134*635a8641SAndroid Build Coastguard Worker     connector_->set_enforce_errors_from_incoming_receiver(false);
135*635a8641SAndroid Build Coastguard Worker     connector_->SetWatcherHeapProfilerTag("IPC Channel");
136*635a8641SAndroid Build Coastguard Worker   }
137*635a8641SAndroid Build Coastguard Worker 
Pause()138*635a8641SAndroid Build Coastguard Worker   void Pause() {
139*635a8641SAndroid Build Coastguard Worker     DCHECK(!paused_);
140*635a8641SAndroid Build Coastguard Worker     paused_ = true;
141*635a8641SAndroid Build Coastguard Worker   }
142*635a8641SAndroid Build Coastguard Worker 
Unpause()143*635a8641SAndroid Build Coastguard Worker   void Unpause() {
144*635a8641SAndroid Build Coastguard Worker     DCHECK(paused_);
145*635a8641SAndroid Build Coastguard Worker     paused_ = false;
146*635a8641SAndroid Build Coastguard Worker   }
147*635a8641SAndroid Build Coastguard Worker 
FlushOutgoingMessages()148*635a8641SAndroid Build Coastguard Worker   void FlushOutgoingMessages() {
149*635a8641SAndroid Build Coastguard Worker     std::vector<mojo::Message> outgoing_messages;
150*635a8641SAndroid Build Coastguard Worker     {
151*635a8641SAndroid Build Coastguard Worker       base::AutoLock lock(outgoing_messages_lock_);
152*635a8641SAndroid Build Coastguard Worker       std::swap(outgoing_messages, outgoing_messages_);
153*635a8641SAndroid Build Coastguard Worker     }
154*635a8641SAndroid Build Coastguard Worker     for (auto& message : outgoing_messages)
155*635a8641SAndroid Build Coastguard Worker       SendMessage(&message);
156*635a8641SAndroid Build Coastguard Worker   }
157*635a8641SAndroid Build Coastguard Worker 
CreateChannelEndpoints(mojom::ChannelAssociatedPtr * sender,mojom::ChannelAssociatedRequest * receiver)158*635a8641SAndroid Build Coastguard Worker   void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
159*635a8641SAndroid Build Coastguard Worker                               mojom::ChannelAssociatedRequest* receiver) {
160*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceId sender_id, receiver_id;
161*635a8641SAndroid Build Coastguard Worker     if (set_interface_id_namespace_bit_) {
162*635a8641SAndroid Build Coastguard Worker       sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
163*635a8641SAndroid Build Coastguard Worker       receiver_id = 1;
164*635a8641SAndroid Build Coastguard Worker     } else {
165*635a8641SAndroid Build Coastguard Worker       sender_id = 1;
166*635a8641SAndroid Build Coastguard Worker       receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
167*635a8641SAndroid Build Coastguard Worker     }
168*635a8641SAndroid Build Coastguard Worker 
169*635a8641SAndroid Build Coastguard Worker     {
170*635a8641SAndroid Build Coastguard Worker       base::AutoLock locker(lock_);
171*635a8641SAndroid Build Coastguard Worker       Endpoint* sender_endpoint = new Endpoint(this, sender_id);
172*635a8641SAndroid Build Coastguard Worker       Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
173*635a8641SAndroid Build Coastguard Worker       endpoints_.insert({ sender_id, sender_endpoint });
174*635a8641SAndroid Build Coastguard Worker       endpoints_.insert({ receiver_id, receiver_endpoint });
175*635a8641SAndroid Build Coastguard Worker       sender_endpoint->set_handle_created();
176*635a8641SAndroid Build Coastguard Worker       receiver_endpoint->set_handle_created();
177*635a8641SAndroid Build Coastguard Worker     }
178*635a8641SAndroid Build Coastguard Worker 
179*635a8641SAndroid Build Coastguard Worker     mojo::ScopedInterfaceEndpointHandle sender_handle =
180*635a8641SAndroid Build Coastguard Worker         CreateScopedInterfaceEndpointHandle(sender_id);
181*635a8641SAndroid Build Coastguard Worker     mojo::ScopedInterfaceEndpointHandle receiver_handle =
182*635a8641SAndroid Build Coastguard Worker         CreateScopedInterfaceEndpointHandle(receiver_id);
183*635a8641SAndroid Build Coastguard Worker 
184*635a8641SAndroid Build Coastguard Worker     sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
185*635a8641SAndroid Build Coastguard Worker     *receiver = mojom::ChannelAssociatedRequest(std::move(receiver_handle));
186*635a8641SAndroid Build Coastguard Worker   }
187*635a8641SAndroid Build Coastguard Worker 
ShutDown()188*635a8641SAndroid Build Coastguard Worker   void ShutDown() {
189*635a8641SAndroid Build Coastguard Worker     DCHECK(thread_checker_.CalledOnValidThread());
190*635a8641SAndroid Build Coastguard Worker     shut_down_ = true;
191*635a8641SAndroid Build Coastguard Worker     connector_->CloseMessagePipe();
192*635a8641SAndroid Build Coastguard Worker     OnPipeError();
193*635a8641SAndroid Build Coastguard Worker     connector_.reset();
194*635a8641SAndroid Build Coastguard Worker 
195*635a8641SAndroid Build Coastguard Worker     base::AutoLock lock(outgoing_messages_lock_);
196*635a8641SAndroid Build Coastguard Worker     outgoing_messages_.clear();
197*635a8641SAndroid Build Coastguard Worker   }
198*635a8641SAndroid Build Coastguard Worker 
199*635a8641SAndroid Build Coastguard Worker   // mojo::AssociatedGroupController:
AssociateInterface(mojo::ScopedInterfaceEndpointHandle handle_to_send)200*635a8641SAndroid Build Coastguard Worker   mojo::InterfaceId AssociateInterface(
201*635a8641SAndroid Build Coastguard Worker       mojo::ScopedInterfaceEndpointHandle handle_to_send) override {
202*635a8641SAndroid Build Coastguard Worker     if (!handle_to_send.pending_association())
203*635a8641SAndroid Build Coastguard Worker       return mojo::kInvalidInterfaceId;
204*635a8641SAndroid Build Coastguard Worker 
205*635a8641SAndroid Build Coastguard Worker     uint32_t id = 0;
206*635a8641SAndroid Build Coastguard Worker     {
207*635a8641SAndroid Build Coastguard Worker       base::AutoLock locker(lock_);
208*635a8641SAndroid Build Coastguard Worker       do {
209*635a8641SAndroid Build Coastguard Worker         if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
210*635a8641SAndroid Build Coastguard Worker           next_interface_id_ = 2;
211*635a8641SAndroid Build Coastguard Worker         id = next_interface_id_++;
212*635a8641SAndroid Build Coastguard Worker         if (set_interface_id_namespace_bit_)
213*635a8641SAndroid Build Coastguard Worker           id |= mojo::kInterfaceIdNamespaceMask;
214*635a8641SAndroid Build Coastguard Worker       } while (ContainsKey(endpoints_, id));
215*635a8641SAndroid Build Coastguard Worker 
216*635a8641SAndroid Build Coastguard Worker       Endpoint* endpoint = new Endpoint(this, id);
217*635a8641SAndroid Build Coastguard Worker       if (encountered_error_)
218*635a8641SAndroid Build Coastguard Worker         endpoint->set_peer_closed();
219*635a8641SAndroid Build Coastguard Worker       endpoint->set_handle_created();
220*635a8641SAndroid Build Coastguard Worker       endpoints_.insert({id, endpoint});
221*635a8641SAndroid Build Coastguard Worker     }
222*635a8641SAndroid Build Coastguard Worker 
223*635a8641SAndroid Build Coastguard Worker     if (!NotifyAssociation(&handle_to_send, id)) {
224*635a8641SAndroid Build Coastguard Worker       // The peer handle of |handle_to_send|, which is supposed to join this
225*635a8641SAndroid Build Coastguard Worker       // associated group, has been closed.
226*635a8641SAndroid Build Coastguard Worker       {
227*635a8641SAndroid Build Coastguard Worker         base::AutoLock locker(lock_);
228*635a8641SAndroid Build Coastguard Worker         Endpoint* endpoint = FindEndpoint(id);
229*635a8641SAndroid Build Coastguard Worker         if (endpoint)
230*635a8641SAndroid Build Coastguard Worker           MarkClosedAndMaybeRemove(endpoint);
231*635a8641SAndroid Build Coastguard Worker       }
232*635a8641SAndroid Build Coastguard Worker 
233*635a8641SAndroid Build Coastguard Worker       control_message_proxy_.NotifyPeerEndpointClosed(
234*635a8641SAndroid Build Coastguard Worker           id, handle_to_send.disconnect_reason());
235*635a8641SAndroid Build Coastguard Worker     }
236*635a8641SAndroid Build Coastguard Worker     return id;
237*635a8641SAndroid Build Coastguard Worker   }
238*635a8641SAndroid Build Coastguard Worker 
CreateLocalEndpointHandle(mojo::InterfaceId id)239*635a8641SAndroid Build Coastguard Worker   mojo::ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(
240*635a8641SAndroid Build Coastguard Worker       mojo::InterfaceId id) override {
241*635a8641SAndroid Build Coastguard Worker     if (!mojo::IsValidInterfaceId(id))
242*635a8641SAndroid Build Coastguard Worker       return mojo::ScopedInterfaceEndpointHandle();
243*635a8641SAndroid Build Coastguard Worker 
244*635a8641SAndroid Build Coastguard Worker     // Unless it is the master ID, |id| is from the remote side and therefore
245*635a8641SAndroid Build Coastguard Worker     // its namespace bit is supposed to be different than the value that this
246*635a8641SAndroid Build Coastguard Worker     // router would use.
247*635a8641SAndroid Build Coastguard Worker     if (!mojo::IsMasterInterfaceId(id) &&
248*635a8641SAndroid Build Coastguard Worker         set_interface_id_namespace_bit_ ==
249*635a8641SAndroid Build Coastguard Worker             mojo::HasInterfaceIdNamespaceBitSet(id)) {
250*635a8641SAndroid Build Coastguard Worker       return mojo::ScopedInterfaceEndpointHandle();
251*635a8641SAndroid Build Coastguard Worker     }
252*635a8641SAndroid Build Coastguard Worker 
253*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
254*635a8641SAndroid Build Coastguard Worker     bool inserted = false;
255*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
256*635a8641SAndroid Build Coastguard Worker     if (inserted) {
257*635a8641SAndroid Build Coastguard Worker       DCHECK(!endpoint->handle_created());
258*635a8641SAndroid Build Coastguard Worker       if (encountered_error_)
259*635a8641SAndroid Build Coastguard Worker         endpoint->set_peer_closed();
260*635a8641SAndroid Build Coastguard Worker     } else {
261*635a8641SAndroid Build Coastguard Worker       if (endpoint->handle_created())
262*635a8641SAndroid Build Coastguard Worker         return mojo::ScopedInterfaceEndpointHandle();
263*635a8641SAndroid Build Coastguard Worker     }
264*635a8641SAndroid Build Coastguard Worker 
265*635a8641SAndroid Build Coastguard Worker     endpoint->set_handle_created();
266*635a8641SAndroid Build Coastguard Worker     return CreateScopedInterfaceEndpointHandle(id);
267*635a8641SAndroid Build Coastguard Worker   }
268*635a8641SAndroid Build Coastguard Worker 
CloseEndpointHandle(mojo::InterfaceId id,const base::Optional<mojo::DisconnectReason> & reason)269*635a8641SAndroid Build Coastguard Worker   void CloseEndpointHandle(
270*635a8641SAndroid Build Coastguard Worker       mojo::InterfaceId id,
271*635a8641SAndroid Build Coastguard Worker       const base::Optional<mojo::DisconnectReason>& reason) override {
272*635a8641SAndroid Build Coastguard Worker     if (!mojo::IsValidInterfaceId(id))
273*635a8641SAndroid Build Coastguard Worker       return;
274*635a8641SAndroid Build Coastguard Worker     {
275*635a8641SAndroid Build Coastguard Worker       base::AutoLock locker(lock_);
276*635a8641SAndroid Build Coastguard Worker       DCHECK(ContainsKey(endpoints_, id));
277*635a8641SAndroid Build Coastguard Worker       Endpoint* endpoint = endpoints_[id].get();
278*635a8641SAndroid Build Coastguard Worker       DCHECK(!endpoint->client());
279*635a8641SAndroid Build Coastguard Worker       DCHECK(!endpoint->closed());
280*635a8641SAndroid Build Coastguard Worker       MarkClosedAndMaybeRemove(endpoint);
281*635a8641SAndroid Build Coastguard Worker     }
282*635a8641SAndroid Build Coastguard Worker 
283*635a8641SAndroid Build Coastguard Worker     if (!mojo::IsMasterInterfaceId(id) || reason)
284*635a8641SAndroid Build Coastguard Worker       control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
285*635a8641SAndroid Build Coastguard Worker   }
286*635a8641SAndroid Build Coastguard Worker 
AttachEndpointClient(const mojo::ScopedInterfaceEndpointHandle & handle,mojo::InterfaceEndpointClient * client,scoped_refptr<base::SequencedTaskRunner> runner)287*635a8641SAndroid Build Coastguard Worker   mojo::InterfaceEndpointController* AttachEndpointClient(
288*635a8641SAndroid Build Coastguard Worker       const mojo::ScopedInterfaceEndpointHandle& handle,
289*635a8641SAndroid Build Coastguard Worker       mojo::InterfaceEndpointClient* client,
290*635a8641SAndroid Build Coastguard Worker       scoped_refptr<base::SequencedTaskRunner> runner) override {
291*635a8641SAndroid Build Coastguard Worker     const mojo::InterfaceId id = handle.id();
292*635a8641SAndroid Build Coastguard Worker 
293*635a8641SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id));
294*635a8641SAndroid Build Coastguard Worker     DCHECK(client);
295*635a8641SAndroid Build Coastguard Worker 
296*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
297*635a8641SAndroid Build Coastguard Worker     DCHECK(ContainsKey(endpoints_, id));
298*635a8641SAndroid Build Coastguard Worker 
299*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = endpoints_[id].get();
300*635a8641SAndroid Build Coastguard Worker     endpoint->AttachClient(client, std::move(runner));
301*635a8641SAndroid Build Coastguard Worker 
302*635a8641SAndroid Build Coastguard Worker     if (endpoint->peer_closed())
303*635a8641SAndroid Build Coastguard Worker       NotifyEndpointOfError(endpoint, true /* force_async */);
304*635a8641SAndroid Build Coastguard Worker 
305*635a8641SAndroid Build Coastguard Worker     return endpoint;
306*635a8641SAndroid Build Coastguard Worker   }
307*635a8641SAndroid Build Coastguard Worker 
DetachEndpointClient(const mojo::ScopedInterfaceEndpointHandle & handle)308*635a8641SAndroid Build Coastguard Worker   void DetachEndpointClient(
309*635a8641SAndroid Build Coastguard Worker       const mojo::ScopedInterfaceEndpointHandle& handle) override {
310*635a8641SAndroid Build Coastguard Worker     const mojo::InterfaceId id = handle.id();
311*635a8641SAndroid Build Coastguard Worker 
312*635a8641SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id));
313*635a8641SAndroid Build Coastguard Worker 
314*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
315*635a8641SAndroid Build Coastguard Worker     DCHECK(ContainsKey(endpoints_, id));
316*635a8641SAndroid Build Coastguard Worker 
317*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = endpoints_[id].get();
318*635a8641SAndroid Build Coastguard Worker     endpoint->DetachClient();
319*635a8641SAndroid Build Coastguard Worker   }
320*635a8641SAndroid Build Coastguard Worker 
RaiseError()321*635a8641SAndroid Build Coastguard Worker   void RaiseError() override {
322*635a8641SAndroid Build Coastguard Worker     // We ignore errors on channel endpoints, leaving the pipe open. There are
323*635a8641SAndroid Build Coastguard Worker     // good reasons for this:
324*635a8641SAndroid Build Coastguard Worker     //
325*635a8641SAndroid Build Coastguard Worker     //   * We should never close a channel endpoint in either process as long as
326*635a8641SAndroid Build Coastguard Worker     //     the child process is still alive. The child's endpoint should only be
327*635a8641SAndroid Build Coastguard Worker     //     closed implicitly by process death, and the browser's endpoint should
328*635a8641SAndroid Build Coastguard Worker     //     only be closed after the child process is confirmed to be dead. Crash
329*635a8641SAndroid Build Coastguard Worker     //     reporting logic in Chrome relies on this behavior in order to do the
330*635a8641SAndroid Build Coastguard Worker     //     right thing.
331*635a8641SAndroid Build Coastguard Worker     //
332*635a8641SAndroid Build Coastguard Worker     //   * There are two interesting conditions under which RaiseError() can be
333*635a8641SAndroid Build Coastguard Worker     //     implicitly reached: an incoming message fails validation, or the
334*635a8641SAndroid Build Coastguard Worker     //     local endpoint drops a response callback without calling it.
335*635a8641SAndroid Build Coastguard Worker     //
336*635a8641SAndroid Build Coastguard Worker     //   * In the validation case, we also report the message as bad, and this
337*635a8641SAndroid Build Coastguard Worker     //     will imminently trigger the common bad-IPC path in the browser,
338*635a8641SAndroid Build Coastguard Worker     //     causing the browser to kill the offending renderer.
339*635a8641SAndroid Build Coastguard Worker     //
340*635a8641SAndroid Build Coastguard Worker     //   * In the dropped response callback case, the net result of ignoring the
341*635a8641SAndroid Build Coastguard Worker     //     issue is generally innocuous. While indicative of programmer error,
342*635a8641SAndroid Build Coastguard Worker     //     it's not a severe failure and is already covered by separate DCHECKs.
343*635a8641SAndroid Build Coastguard Worker     //
344*635a8641SAndroid Build Coastguard Worker     // See https://crbug.com/861607 for additional discussion.
345*635a8641SAndroid Build Coastguard Worker   }
346*635a8641SAndroid Build Coastguard Worker 
PrefersSerializedMessages()347*635a8641SAndroid Build Coastguard Worker   bool PrefersSerializedMessages() override { return true; }
348*635a8641SAndroid Build Coastguard Worker 
349*635a8641SAndroid Build Coastguard Worker  private:
350*635a8641SAndroid Build Coastguard Worker   class Endpoint;
351*635a8641SAndroid Build Coastguard Worker   class ControlMessageProxyThunk;
352*635a8641SAndroid Build Coastguard Worker   friend class Endpoint;
353*635a8641SAndroid Build Coastguard Worker   friend class ControlMessageProxyThunk;
354*635a8641SAndroid Build Coastguard Worker 
355*635a8641SAndroid Build Coastguard Worker   // MessageWrapper objects are always destroyed under the controller's lock. On
356*635a8641SAndroid Build Coastguard Worker   // destruction, if the message it wrappers contains
357*635a8641SAndroid Build Coastguard Worker   // ScopedInterfaceEndpointHandles (which cannot be destructed under the
358*635a8641SAndroid Build Coastguard Worker   // controller's lock), the wrapper unlocks to clean them up.
359*635a8641SAndroid Build Coastguard Worker   class MessageWrapper {
360*635a8641SAndroid Build Coastguard Worker    public:
361*635a8641SAndroid Build Coastguard Worker     MessageWrapper() = default;
362*635a8641SAndroid Build Coastguard Worker 
MessageWrapper(ChannelAssociatedGroupController * controller,mojo::Message message)363*635a8641SAndroid Build Coastguard Worker     MessageWrapper(ChannelAssociatedGroupController* controller,
364*635a8641SAndroid Build Coastguard Worker                    mojo::Message message)
365*635a8641SAndroid Build Coastguard Worker         : controller_(controller), value_(std::move(message)) {}
366*635a8641SAndroid Build Coastguard Worker 
MessageWrapper(MessageWrapper && other)367*635a8641SAndroid Build Coastguard Worker     MessageWrapper(MessageWrapper&& other)
368*635a8641SAndroid Build Coastguard Worker         : controller_(other.controller_), value_(std::move(other.value_)) {}
369*635a8641SAndroid Build Coastguard Worker 
~MessageWrapper()370*635a8641SAndroid Build Coastguard Worker     ~MessageWrapper() {
371*635a8641SAndroid Build Coastguard Worker       if (value_.associated_endpoint_handles()->empty())
372*635a8641SAndroid Build Coastguard Worker         return;
373*635a8641SAndroid Build Coastguard Worker 
374*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
375*635a8641SAndroid Build Coastguard Worker       {
376*635a8641SAndroid Build Coastguard Worker         base::AutoUnlock unlocker(controller_->lock_);
377*635a8641SAndroid Build Coastguard Worker         value_.mutable_associated_endpoint_handles()->clear();
378*635a8641SAndroid Build Coastguard Worker       }
379*635a8641SAndroid Build Coastguard Worker     }
380*635a8641SAndroid Build Coastguard Worker 
operator =(MessageWrapper && other)381*635a8641SAndroid Build Coastguard Worker     MessageWrapper& operator=(MessageWrapper&& other) {
382*635a8641SAndroid Build Coastguard Worker       controller_ = other.controller_;
383*635a8641SAndroid Build Coastguard Worker       value_ = std::move(other.value_);
384*635a8641SAndroid Build Coastguard Worker       return *this;
385*635a8641SAndroid Build Coastguard Worker     }
386*635a8641SAndroid Build Coastguard Worker 
value()387*635a8641SAndroid Build Coastguard Worker     mojo::Message& value() { return value_; }
388*635a8641SAndroid Build Coastguard Worker 
389*635a8641SAndroid Build Coastguard Worker    private:
390*635a8641SAndroid Build Coastguard Worker     ChannelAssociatedGroupController* controller_ = nullptr;
391*635a8641SAndroid Build Coastguard Worker     mojo::Message value_;
392*635a8641SAndroid Build Coastguard Worker 
393*635a8641SAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(MessageWrapper);
394*635a8641SAndroid Build Coastguard Worker   };
395*635a8641SAndroid Build Coastguard Worker 
396*635a8641SAndroid Build Coastguard Worker   class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
397*635a8641SAndroid Build Coastguard Worker                    public mojo::InterfaceEndpointController {
398*635a8641SAndroid Build Coastguard Worker    public:
Endpoint(ChannelAssociatedGroupController * controller,mojo::InterfaceId id)399*635a8641SAndroid Build Coastguard Worker     Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
400*635a8641SAndroid Build Coastguard Worker         : controller_(controller), id_(id) {}
401*635a8641SAndroid Build Coastguard Worker 
id() const402*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceId id() const { return id_; }
403*635a8641SAndroid Build Coastguard Worker 
closed() const404*635a8641SAndroid Build Coastguard Worker     bool closed() const {
405*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
406*635a8641SAndroid Build Coastguard Worker       return closed_;
407*635a8641SAndroid Build Coastguard Worker     }
408*635a8641SAndroid Build Coastguard Worker 
set_closed()409*635a8641SAndroid Build Coastguard Worker     void set_closed() {
410*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
411*635a8641SAndroid Build Coastguard Worker       closed_ = true;
412*635a8641SAndroid Build Coastguard Worker     }
413*635a8641SAndroid Build Coastguard Worker 
peer_closed() const414*635a8641SAndroid Build Coastguard Worker     bool peer_closed() const {
415*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
416*635a8641SAndroid Build Coastguard Worker       return peer_closed_;
417*635a8641SAndroid Build Coastguard Worker     }
418*635a8641SAndroid Build Coastguard Worker 
set_peer_closed()419*635a8641SAndroid Build Coastguard Worker     void set_peer_closed() {
420*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
421*635a8641SAndroid Build Coastguard Worker       peer_closed_ = true;
422*635a8641SAndroid Build Coastguard Worker     }
423*635a8641SAndroid Build Coastguard Worker 
handle_created() const424*635a8641SAndroid Build Coastguard Worker     bool handle_created() const {
425*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
426*635a8641SAndroid Build Coastguard Worker       return handle_created_;
427*635a8641SAndroid Build Coastguard Worker     }
428*635a8641SAndroid Build Coastguard Worker 
set_handle_created()429*635a8641SAndroid Build Coastguard Worker     void set_handle_created() {
430*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
431*635a8641SAndroid Build Coastguard Worker       handle_created_ = true;
432*635a8641SAndroid Build Coastguard Worker     }
433*635a8641SAndroid Build Coastguard Worker 
disconnect_reason() const434*635a8641SAndroid Build Coastguard Worker     const base::Optional<mojo::DisconnectReason>& disconnect_reason() const {
435*635a8641SAndroid Build Coastguard Worker       return disconnect_reason_;
436*635a8641SAndroid Build Coastguard Worker     }
437*635a8641SAndroid Build Coastguard Worker 
set_disconnect_reason(const base::Optional<mojo::DisconnectReason> & disconnect_reason)438*635a8641SAndroid Build Coastguard Worker     void set_disconnect_reason(
439*635a8641SAndroid Build Coastguard Worker         const base::Optional<mojo::DisconnectReason>& disconnect_reason) {
440*635a8641SAndroid Build Coastguard Worker       disconnect_reason_ = disconnect_reason;
441*635a8641SAndroid Build Coastguard Worker     }
442*635a8641SAndroid Build Coastguard Worker 
task_runner() const443*635a8641SAndroid Build Coastguard Worker     base::SequencedTaskRunner* task_runner() const {
444*635a8641SAndroid Build Coastguard Worker       return task_runner_.get();
445*635a8641SAndroid Build Coastguard Worker     }
446*635a8641SAndroid Build Coastguard Worker 
client() const447*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client() const {
448*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
449*635a8641SAndroid Build Coastguard Worker       return client_;
450*635a8641SAndroid Build Coastguard Worker     }
451*635a8641SAndroid Build Coastguard Worker 
AttachClient(mojo::InterfaceEndpointClient * client,scoped_refptr<base::SequencedTaskRunner> runner)452*635a8641SAndroid Build Coastguard Worker     void AttachClient(mojo::InterfaceEndpointClient* client,
453*635a8641SAndroid Build Coastguard Worker                       scoped_refptr<base::SequencedTaskRunner> runner) {
454*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
455*635a8641SAndroid Build Coastguard Worker       DCHECK(!client_);
456*635a8641SAndroid Build Coastguard Worker       DCHECK(!closed_);
457*635a8641SAndroid Build Coastguard Worker       DCHECK(runner->RunsTasksInCurrentSequence());
458*635a8641SAndroid Build Coastguard Worker 
459*635a8641SAndroid Build Coastguard Worker       task_runner_ = std::move(runner);
460*635a8641SAndroid Build Coastguard Worker       client_ = client;
461*635a8641SAndroid Build Coastguard Worker     }
462*635a8641SAndroid Build Coastguard Worker 
DetachClient()463*635a8641SAndroid Build Coastguard Worker     void DetachClient() {
464*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
465*635a8641SAndroid Build Coastguard Worker       DCHECK(client_);
466*635a8641SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
467*635a8641SAndroid Build Coastguard Worker       DCHECK(!closed_);
468*635a8641SAndroid Build Coastguard Worker 
469*635a8641SAndroid Build Coastguard Worker       task_runner_ = nullptr;
470*635a8641SAndroid Build Coastguard Worker       client_ = nullptr;
471*635a8641SAndroid Build Coastguard Worker       sync_watcher_.reset();
472*635a8641SAndroid Build Coastguard Worker     }
473*635a8641SAndroid Build Coastguard Worker 
EnqueueSyncMessage(MessageWrapper message)474*635a8641SAndroid Build Coastguard Worker     uint32_t EnqueueSyncMessage(MessageWrapper message) {
475*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
476*635a8641SAndroid Build Coastguard Worker       uint32_t id = GenerateSyncMessageId();
477*635a8641SAndroid Build Coastguard Worker       sync_messages_.emplace(id, std::move(message));
478*635a8641SAndroid Build Coastguard Worker       SignalSyncMessageEvent();
479*635a8641SAndroid Build Coastguard Worker       return id;
480*635a8641SAndroid Build Coastguard Worker     }
481*635a8641SAndroid Build Coastguard Worker 
SignalSyncMessageEvent()482*635a8641SAndroid Build Coastguard Worker     void SignalSyncMessageEvent() {
483*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
484*635a8641SAndroid Build Coastguard Worker 
485*635a8641SAndroid Build Coastguard Worker       if (sync_watcher_)
486*635a8641SAndroid Build Coastguard Worker         sync_watcher_->SignalEvent();
487*635a8641SAndroid Build Coastguard Worker     }
488*635a8641SAndroid Build Coastguard Worker 
PopSyncMessage(uint32_t id)489*635a8641SAndroid Build Coastguard Worker     MessageWrapper PopSyncMessage(uint32_t id) {
490*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
491*635a8641SAndroid Build Coastguard Worker       if (sync_messages_.empty() || sync_messages_.front().first != id)
492*635a8641SAndroid Build Coastguard Worker         return MessageWrapper();
493*635a8641SAndroid Build Coastguard Worker       MessageWrapper message = std::move(sync_messages_.front().second);
494*635a8641SAndroid Build Coastguard Worker       sync_messages_.pop();
495*635a8641SAndroid Build Coastguard Worker       return message;
496*635a8641SAndroid Build Coastguard Worker     }
497*635a8641SAndroid Build Coastguard Worker 
498*635a8641SAndroid Build Coastguard Worker     // mojo::InterfaceEndpointController:
SendMessage(mojo::Message * message)499*635a8641SAndroid Build Coastguard Worker     bool SendMessage(mojo::Message* message) override {
500*635a8641SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
501*635a8641SAndroid Build Coastguard Worker       message->set_interface_id(id_);
502*635a8641SAndroid Build Coastguard Worker       return controller_->SendMessage(message);
503*635a8641SAndroid Build Coastguard Worker     }
504*635a8641SAndroid Build Coastguard Worker 
AllowWokenUpBySyncWatchOnSameThread()505*635a8641SAndroid Build Coastguard Worker     void AllowWokenUpBySyncWatchOnSameThread() override {
506*635a8641SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
507*635a8641SAndroid Build Coastguard Worker 
508*635a8641SAndroid Build Coastguard Worker       EnsureSyncWatcherExists();
509*635a8641SAndroid Build Coastguard Worker       sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence();
510*635a8641SAndroid Build Coastguard Worker     }
511*635a8641SAndroid Build Coastguard Worker 
SyncWatch(const bool * should_stop)512*635a8641SAndroid Build Coastguard Worker     bool SyncWatch(const bool* should_stop) override {
513*635a8641SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
514*635a8641SAndroid Build Coastguard Worker 
515*635a8641SAndroid Build Coastguard Worker       // It's not legal to make sync calls from the master endpoint's thread,
516*635a8641SAndroid Build Coastguard Worker       // and in fact they must only happen from the proxy task runner.
517*635a8641SAndroid Build Coastguard Worker       DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
518*635a8641SAndroid Build Coastguard Worker       DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
519*635a8641SAndroid Build Coastguard Worker 
520*635a8641SAndroid Build Coastguard Worker       EnsureSyncWatcherExists();
521*635a8641SAndroid Build Coastguard Worker       return sync_watcher_->SyncWatch(should_stop);
522*635a8641SAndroid Build Coastguard Worker     }
523*635a8641SAndroid Build Coastguard Worker 
524*635a8641SAndroid Build Coastguard Worker    private:
525*635a8641SAndroid Build Coastguard Worker     friend class base::RefCountedThreadSafe<Endpoint>;
526*635a8641SAndroid Build Coastguard Worker 
~Endpoint()527*635a8641SAndroid Build Coastguard Worker     ~Endpoint() override {
528*635a8641SAndroid Build Coastguard Worker       controller_->lock_.AssertAcquired();
529*635a8641SAndroid Build Coastguard Worker       DCHECK(!client_);
530*635a8641SAndroid Build Coastguard Worker       DCHECK(closed_);
531*635a8641SAndroid Build Coastguard Worker       DCHECK(peer_closed_);
532*635a8641SAndroid Build Coastguard Worker       DCHECK(!sync_watcher_);
533*635a8641SAndroid Build Coastguard Worker     }
534*635a8641SAndroid Build Coastguard Worker 
OnSyncMessageEventReady()535*635a8641SAndroid Build Coastguard Worker     void OnSyncMessageEventReady() {
536*635a8641SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
537*635a8641SAndroid Build Coastguard Worker 
538*635a8641SAndroid Build Coastguard Worker       scoped_refptr<Endpoint> keepalive(this);
539*635a8641SAndroid Build Coastguard Worker       scoped_refptr<AssociatedGroupController> controller_keepalive(
540*635a8641SAndroid Build Coastguard Worker           controller_);
541*635a8641SAndroid Build Coastguard Worker       base::AutoLock locker(controller_->lock_);
542*635a8641SAndroid Build Coastguard Worker       bool more_to_process = false;
543*635a8641SAndroid Build Coastguard Worker       if (!sync_messages_.empty()) {
544*635a8641SAndroid Build Coastguard Worker         MessageWrapper message_wrapper =
545*635a8641SAndroid Build Coastguard Worker             std::move(sync_messages_.front().second);
546*635a8641SAndroid Build Coastguard Worker         sync_messages_.pop();
547*635a8641SAndroid Build Coastguard Worker 
548*635a8641SAndroid Build Coastguard Worker         bool dispatch_succeeded;
549*635a8641SAndroid Build Coastguard Worker         mojo::InterfaceEndpointClient* client = client_;
550*635a8641SAndroid Build Coastguard Worker         {
551*635a8641SAndroid Build Coastguard Worker           base::AutoUnlock unlocker(controller_->lock_);
552*635a8641SAndroid Build Coastguard Worker           dispatch_succeeded =
553*635a8641SAndroid Build Coastguard Worker               client->HandleIncomingMessage(&message_wrapper.value());
554*635a8641SAndroid Build Coastguard Worker         }
555*635a8641SAndroid Build Coastguard Worker 
556*635a8641SAndroid Build Coastguard Worker         if (!sync_messages_.empty())
557*635a8641SAndroid Build Coastguard Worker           more_to_process = true;
558*635a8641SAndroid Build Coastguard Worker 
559*635a8641SAndroid Build Coastguard Worker         if (!dispatch_succeeded)
560*635a8641SAndroid Build Coastguard Worker           controller_->RaiseError();
561*635a8641SAndroid Build Coastguard Worker       }
562*635a8641SAndroid Build Coastguard Worker 
563*635a8641SAndroid Build Coastguard Worker       if (!more_to_process)
564*635a8641SAndroid Build Coastguard Worker         sync_watcher_->ResetEvent();
565*635a8641SAndroid Build Coastguard Worker 
566*635a8641SAndroid Build Coastguard Worker       // If there are no queued sync messages and the peer has closed, there
567*635a8641SAndroid Build Coastguard Worker       // there won't be incoming sync messages in the future. If any
568*635a8641SAndroid Build Coastguard Worker       // SyncWatch() calls are on the stack for this endpoint, resetting the
569*635a8641SAndroid Build Coastguard Worker       // watcher will allow them to exit as the stack undwinds.
570*635a8641SAndroid Build Coastguard Worker       if (!more_to_process && peer_closed_)
571*635a8641SAndroid Build Coastguard Worker         sync_watcher_.reset();
572*635a8641SAndroid Build Coastguard Worker     }
573*635a8641SAndroid Build Coastguard Worker 
EnsureSyncWatcherExists()574*635a8641SAndroid Build Coastguard Worker     void EnsureSyncWatcherExists() {
575*635a8641SAndroid Build Coastguard Worker       DCHECK(task_runner_->RunsTasksInCurrentSequence());
576*635a8641SAndroid Build Coastguard Worker       if (sync_watcher_)
577*635a8641SAndroid Build Coastguard Worker         return;
578*635a8641SAndroid Build Coastguard Worker 
579*635a8641SAndroid Build Coastguard Worker       base::AutoLock locker(controller_->lock_);
580*635a8641SAndroid Build Coastguard Worker       sync_watcher_ = std::make_unique<mojo::SequenceLocalSyncEventWatcher>(
581*635a8641SAndroid Build Coastguard Worker           base::BindRepeating(&Endpoint::OnSyncMessageEventReady,
582*635a8641SAndroid Build Coastguard Worker                               base::Unretained(this)));
583*635a8641SAndroid Build Coastguard Worker       if (peer_closed_ || !sync_messages_.empty())
584*635a8641SAndroid Build Coastguard Worker         SignalSyncMessageEvent();
585*635a8641SAndroid Build Coastguard Worker     }
586*635a8641SAndroid Build Coastguard Worker 
GenerateSyncMessageId()587*635a8641SAndroid Build Coastguard Worker     uint32_t GenerateSyncMessageId() {
588*635a8641SAndroid Build Coastguard Worker       // Overflow is fine.
589*635a8641SAndroid Build Coastguard Worker       uint32_t id = next_sync_message_id_++;
590*635a8641SAndroid Build Coastguard Worker       DCHECK(sync_messages_.empty() || sync_messages_.front().first != id);
591*635a8641SAndroid Build Coastguard Worker       return id;
592*635a8641SAndroid Build Coastguard Worker     }
593*635a8641SAndroid Build Coastguard Worker 
594*635a8641SAndroid Build Coastguard Worker     ChannelAssociatedGroupController* const controller_;
595*635a8641SAndroid Build Coastguard Worker     const mojo::InterfaceId id_;
596*635a8641SAndroid Build Coastguard Worker 
597*635a8641SAndroid Build Coastguard Worker     bool closed_ = false;
598*635a8641SAndroid Build Coastguard Worker     bool peer_closed_ = false;
599*635a8641SAndroid Build Coastguard Worker     bool handle_created_ = false;
600*635a8641SAndroid Build Coastguard Worker     base::Optional<mojo::DisconnectReason> disconnect_reason_;
601*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client_ = nullptr;
602*635a8641SAndroid Build Coastguard Worker     scoped_refptr<base::SequencedTaskRunner> task_runner_;
603*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
604*635a8641SAndroid Build Coastguard Worker     base::queue<std::pair<uint32_t, MessageWrapper>> sync_messages_;
605*635a8641SAndroid Build Coastguard Worker     uint32_t next_sync_message_id_ = 0;
606*635a8641SAndroid Build Coastguard Worker 
607*635a8641SAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(Endpoint);
608*635a8641SAndroid Build Coastguard Worker   };
609*635a8641SAndroid Build Coastguard Worker 
610*635a8641SAndroid Build Coastguard Worker   class ControlMessageProxyThunk : public MessageReceiver {
611*635a8641SAndroid Build Coastguard Worker    public:
ControlMessageProxyThunk(ChannelAssociatedGroupController * controller)612*635a8641SAndroid Build Coastguard Worker     explicit ControlMessageProxyThunk(
613*635a8641SAndroid Build Coastguard Worker         ChannelAssociatedGroupController* controller)
614*635a8641SAndroid Build Coastguard Worker         : controller_(controller) {}
615*635a8641SAndroid Build Coastguard Worker 
616*635a8641SAndroid Build Coastguard Worker    private:
617*635a8641SAndroid Build Coastguard Worker     // MessageReceiver:
Accept(mojo::Message * message)618*635a8641SAndroid Build Coastguard Worker     bool Accept(mojo::Message* message) override {
619*635a8641SAndroid Build Coastguard Worker       return controller_->SendMessage(message);
620*635a8641SAndroid Build Coastguard Worker     }
621*635a8641SAndroid Build Coastguard Worker 
622*635a8641SAndroid Build Coastguard Worker     ChannelAssociatedGroupController* controller_;
623*635a8641SAndroid Build Coastguard Worker 
624*635a8641SAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
625*635a8641SAndroid Build Coastguard Worker   };
626*635a8641SAndroid Build Coastguard Worker 
~ChannelAssociatedGroupController()627*635a8641SAndroid Build Coastguard Worker   ~ChannelAssociatedGroupController() override {
628*635a8641SAndroid Build Coastguard Worker     DCHECK(!connector_);
629*635a8641SAndroid Build Coastguard Worker 
630*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
631*635a8641SAndroid Build Coastguard Worker     for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
632*635a8641SAndroid Build Coastguard Worker       Endpoint* endpoint = iter->second.get();
633*635a8641SAndroid Build Coastguard Worker       ++iter;
634*635a8641SAndroid Build Coastguard Worker 
635*635a8641SAndroid Build Coastguard Worker       if (!endpoint->closed()) {
636*635a8641SAndroid Build Coastguard Worker         // This happens when a NotifyPeerEndpointClosed message been received,
637*635a8641SAndroid Build Coastguard Worker         // but the interface ID hasn't been used to create local endpoint
638*635a8641SAndroid Build Coastguard Worker         // handle.
639*635a8641SAndroid Build Coastguard Worker         DCHECK(!endpoint->client());
640*635a8641SAndroid Build Coastguard Worker         DCHECK(endpoint->peer_closed());
641*635a8641SAndroid Build Coastguard Worker         MarkClosedAndMaybeRemove(endpoint);
642*635a8641SAndroid Build Coastguard Worker       } else {
643*635a8641SAndroid Build Coastguard Worker         MarkPeerClosedAndMaybeRemove(endpoint);
644*635a8641SAndroid Build Coastguard Worker       }
645*635a8641SAndroid Build Coastguard Worker     }
646*635a8641SAndroid Build Coastguard Worker 
647*635a8641SAndroid Build Coastguard Worker     DCHECK(endpoints_.empty());
648*635a8641SAndroid Build Coastguard Worker 
649*635a8641SAndroid Build Coastguard Worker     GetMemoryDumpProvider().RemoveController(this);
650*635a8641SAndroid Build Coastguard Worker   }
651*635a8641SAndroid Build Coastguard Worker 
SendMessage(mojo::Message * message)652*635a8641SAndroid Build Coastguard Worker   bool SendMessage(mojo::Message* message) {
653*635a8641SAndroid Build Coastguard Worker     if (task_runner_->BelongsToCurrentThread()) {
654*635a8641SAndroid Build Coastguard Worker       DCHECK(thread_checker_.CalledOnValidThread());
655*635a8641SAndroid Build Coastguard Worker       if (!connector_ || paused_) {
656*635a8641SAndroid Build Coastguard Worker         if (!shut_down_) {
657*635a8641SAndroid Build Coastguard Worker           base::AutoLock lock(outgoing_messages_lock_);
658*635a8641SAndroid Build Coastguard Worker           outgoing_messages_.emplace_back(std::move(*message));
659*635a8641SAndroid Build Coastguard Worker         }
660*635a8641SAndroid Build Coastguard Worker         return true;
661*635a8641SAndroid Build Coastguard Worker       }
662*635a8641SAndroid Build Coastguard Worker       return connector_->Accept(message);
663*635a8641SAndroid Build Coastguard Worker     } else {
664*635a8641SAndroid Build Coastguard Worker       // Do a message size check here so we don't lose valuable stack
665*635a8641SAndroid Build Coastguard Worker       // information to the task scheduler.
666*635a8641SAndroid Build Coastguard Worker       CHECK_LE(message->data_num_bytes(), Channel::kMaximumMessageSize);
667*635a8641SAndroid Build Coastguard Worker 
668*635a8641SAndroid Build Coastguard Worker       // We always post tasks to the master endpoint thread when called from
669*635a8641SAndroid Build Coastguard Worker       // other threads in order to simulate IPC::ChannelProxy::Send behavior.
670*635a8641SAndroid Build Coastguard Worker       task_runner_->PostTask(
671*635a8641SAndroid Build Coastguard Worker           FROM_HERE,
672*635a8641SAndroid Build Coastguard Worker           base::Bind(
673*635a8641SAndroid Build Coastguard Worker               &ChannelAssociatedGroupController::SendMessageOnMasterThread,
674*635a8641SAndroid Build Coastguard Worker               this, base::Passed(message)));
675*635a8641SAndroid Build Coastguard Worker       return true;
676*635a8641SAndroid Build Coastguard Worker     }
677*635a8641SAndroid Build Coastguard Worker   }
678*635a8641SAndroid Build Coastguard Worker 
SendMessageOnMasterThread(mojo::Message message)679*635a8641SAndroid Build Coastguard Worker   void SendMessageOnMasterThread(mojo::Message message) {
680*635a8641SAndroid Build Coastguard Worker     DCHECK(thread_checker_.CalledOnValidThread());
681*635a8641SAndroid Build Coastguard Worker     if (!SendMessage(&message))
682*635a8641SAndroid Build Coastguard Worker       RaiseError();
683*635a8641SAndroid Build Coastguard Worker   }
684*635a8641SAndroid Build Coastguard Worker 
OnPipeError()685*635a8641SAndroid Build Coastguard Worker   void OnPipeError() {
686*635a8641SAndroid Build Coastguard Worker     DCHECK(thread_checker_.CalledOnValidThread());
687*635a8641SAndroid Build Coastguard Worker 
688*635a8641SAndroid Build Coastguard Worker     // We keep |this| alive here because it's possible for the notifications
689*635a8641SAndroid Build Coastguard Worker     // below to release all other references.
690*635a8641SAndroid Build Coastguard Worker     scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
691*635a8641SAndroid Build Coastguard Worker 
692*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
693*635a8641SAndroid Build Coastguard Worker     encountered_error_ = true;
694*635a8641SAndroid Build Coastguard Worker 
695*635a8641SAndroid Build Coastguard Worker     std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
696*635a8641SAndroid Build Coastguard Worker     for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
697*635a8641SAndroid Build Coastguard Worker       Endpoint* endpoint = iter->second.get();
698*635a8641SAndroid Build Coastguard Worker       ++iter;
699*635a8641SAndroid Build Coastguard Worker 
700*635a8641SAndroid Build Coastguard Worker       if (endpoint->client())
701*635a8641SAndroid Build Coastguard Worker         endpoints_to_notify.push_back(endpoint);
702*635a8641SAndroid Build Coastguard Worker 
703*635a8641SAndroid Build Coastguard Worker       MarkPeerClosedAndMaybeRemove(endpoint);
704*635a8641SAndroid Build Coastguard Worker     }
705*635a8641SAndroid Build Coastguard Worker 
706*635a8641SAndroid Build Coastguard Worker     for (auto& endpoint : endpoints_to_notify) {
707*635a8641SAndroid Build Coastguard Worker       // Because a notification may in turn detach any endpoint, we have to
708*635a8641SAndroid Build Coastguard Worker       // check each client again here.
709*635a8641SAndroid Build Coastguard Worker       if (endpoint->client())
710*635a8641SAndroid Build Coastguard Worker         NotifyEndpointOfError(endpoint.get(), false /* force_async */);
711*635a8641SAndroid Build Coastguard Worker     }
712*635a8641SAndroid Build Coastguard Worker   }
713*635a8641SAndroid Build Coastguard Worker 
NotifyEndpointOfError(Endpoint * endpoint,bool force_async)714*635a8641SAndroid Build Coastguard Worker   void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
715*635a8641SAndroid Build Coastguard Worker     lock_.AssertAcquired();
716*635a8641SAndroid Build Coastguard Worker     DCHECK(endpoint->task_runner() && endpoint->client());
717*635a8641SAndroid Build Coastguard Worker     if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) {
718*635a8641SAndroid Build Coastguard Worker       mojo::InterfaceEndpointClient* client = endpoint->client();
719*635a8641SAndroid Build Coastguard Worker       base::Optional<mojo::DisconnectReason> reason(
720*635a8641SAndroid Build Coastguard Worker           endpoint->disconnect_reason());
721*635a8641SAndroid Build Coastguard Worker 
722*635a8641SAndroid Build Coastguard Worker       base::AutoUnlock unlocker(lock_);
723*635a8641SAndroid Build Coastguard Worker       client->NotifyError(reason);
724*635a8641SAndroid Build Coastguard Worker     } else {
725*635a8641SAndroid Build Coastguard Worker       endpoint->task_runner()->PostTask(
726*635a8641SAndroid Build Coastguard Worker           FROM_HERE,
727*635a8641SAndroid Build Coastguard Worker           base::Bind(&ChannelAssociatedGroupController::
728*635a8641SAndroid Build Coastguard Worker                          NotifyEndpointOfErrorOnEndpointThread,
729*635a8641SAndroid Build Coastguard Worker                      this, endpoint->id(), base::Unretained(endpoint)));
730*635a8641SAndroid Build Coastguard Worker     }
731*635a8641SAndroid Build Coastguard Worker   }
732*635a8641SAndroid Build Coastguard Worker 
NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,Endpoint * endpoint)733*635a8641SAndroid Build Coastguard Worker   void NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,
734*635a8641SAndroid Build Coastguard Worker                                              Endpoint* endpoint) {
735*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
736*635a8641SAndroid Build Coastguard Worker     auto iter = endpoints_.find(id);
737*635a8641SAndroid Build Coastguard Worker     if (iter == endpoints_.end() || iter->second.get() != endpoint)
738*635a8641SAndroid Build Coastguard Worker       return;
739*635a8641SAndroid Build Coastguard Worker     if (!endpoint->client())
740*635a8641SAndroid Build Coastguard Worker       return;
741*635a8641SAndroid Build Coastguard Worker 
742*635a8641SAndroid Build Coastguard Worker     DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
743*635a8641SAndroid Build Coastguard Worker     NotifyEndpointOfError(endpoint, false /* force_async */);
744*635a8641SAndroid Build Coastguard Worker   }
745*635a8641SAndroid Build Coastguard Worker 
MarkClosedAndMaybeRemove(Endpoint * endpoint)746*635a8641SAndroid Build Coastguard Worker   void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
747*635a8641SAndroid Build Coastguard Worker     lock_.AssertAcquired();
748*635a8641SAndroid Build Coastguard Worker     endpoint->set_closed();
749*635a8641SAndroid Build Coastguard Worker     if (endpoint->closed() && endpoint->peer_closed())
750*635a8641SAndroid Build Coastguard Worker       endpoints_.erase(endpoint->id());
751*635a8641SAndroid Build Coastguard Worker   }
752*635a8641SAndroid Build Coastguard Worker 
MarkPeerClosedAndMaybeRemove(Endpoint * endpoint)753*635a8641SAndroid Build Coastguard Worker   void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
754*635a8641SAndroid Build Coastguard Worker     lock_.AssertAcquired();
755*635a8641SAndroid Build Coastguard Worker     endpoint->set_peer_closed();
756*635a8641SAndroid Build Coastguard Worker     endpoint->SignalSyncMessageEvent();
757*635a8641SAndroid Build Coastguard Worker     if (endpoint->closed() && endpoint->peer_closed())
758*635a8641SAndroid Build Coastguard Worker       endpoints_.erase(endpoint->id());
759*635a8641SAndroid Build Coastguard Worker   }
760*635a8641SAndroid Build Coastguard Worker 
FindOrInsertEndpoint(mojo::InterfaceId id,bool * inserted)761*635a8641SAndroid Build Coastguard Worker   Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
762*635a8641SAndroid Build Coastguard Worker     lock_.AssertAcquired();
763*635a8641SAndroid Build Coastguard Worker     DCHECK(!inserted || !*inserted);
764*635a8641SAndroid Build Coastguard Worker 
765*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(id);
766*635a8641SAndroid Build Coastguard Worker     if (!endpoint) {
767*635a8641SAndroid Build Coastguard Worker       endpoint = new Endpoint(this, id);
768*635a8641SAndroid Build Coastguard Worker       endpoints_.insert({id, endpoint});
769*635a8641SAndroid Build Coastguard Worker       if (inserted)
770*635a8641SAndroid Build Coastguard Worker         *inserted = true;
771*635a8641SAndroid Build Coastguard Worker     }
772*635a8641SAndroid Build Coastguard Worker     return endpoint;
773*635a8641SAndroid Build Coastguard Worker   }
774*635a8641SAndroid Build Coastguard Worker 
FindEndpoint(mojo::InterfaceId id)775*635a8641SAndroid Build Coastguard Worker   Endpoint* FindEndpoint(mojo::InterfaceId id) {
776*635a8641SAndroid Build Coastguard Worker     lock_.AssertAcquired();
777*635a8641SAndroid Build Coastguard Worker     auto iter = endpoints_.find(id);
778*635a8641SAndroid Build Coastguard Worker     return iter != endpoints_.end() ? iter->second.get() : nullptr;
779*635a8641SAndroid Build Coastguard Worker   }
780*635a8641SAndroid Build Coastguard Worker 
781*635a8641SAndroid Build Coastguard Worker   // mojo::MessageReceiver:
Accept(mojo::Message * message)782*635a8641SAndroid Build Coastguard Worker   bool Accept(mojo::Message* message) override {
783*635a8641SAndroid Build Coastguard Worker     DCHECK(thread_checker_.CalledOnValidThread());
784*635a8641SAndroid Build Coastguard Worker 
785*635a8641SAndroid Build Coastguard Worker     if (!message->DeserializeAssociatedEndpointHandles(this))
786*635a8641SAndroid Build Coastguard Worker       return false;
787*635a8641SAndroid Build Coastguard Worker 
788*635a8641SAndroid Build Coastguard Worker     if (mojo::PipeControlMessageHandler::IsPipeControlMessage(message))
789*635a8641SAndroid Build Coastguard Worker       return control_message_handler_.Accept(message);
790*635a8641SAndroid Build Coastguard Worker 
791*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceId id = message->interface_id();
792*635a8641SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id));
793*635a8641SAndroid Build Coastguard Worker 
794*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
795*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(id);
796*635a8641SAndroid Build Coastguard Worker     if (!endpoint)
797*635a8641SAndroid Build Coastguard Worker       return true;
798*635a8641SAndroid Build Coastguard Worker 
799*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client = endpoint->client();
800*635a8641SAndroid Build Coastguard Worker     if (!client || !endpoint->task_runner()->RunsTasksInCurrentSequence()) {
801*635a8641SAndroid Build Coastguard Worker       // No client has been bound yet or the client runs tasks on another
802*635a8641SAndroid Build Coastguard Worker       // thread. We assume the other thread must always be the one on which
803*635a8641SAndroid Build Coastguard Worker       // |proxy_task_runner_| runs tasks, since that's the only valid scenario.
804*635a8641SAndroid Build Coastguard Worker       //
805*635a8641SAndroid Build Coastguard Worker       // If the client is not yet bound, it must be bound by the time this task
806*635a8641SAndroid Build Coastguard Worker       // runs or else it's programmer error.
807*635a8641SAndroid Build Coastguard Worker       DCHECK(proxy_task_runner_);
808*635a8641SAndroid Build Coastguard Worker 
809*635a8641SAndroid Build Coastguard Worker       if (message->has_flag(mojo::Message::kFlagIsSync)) {
810*635a8641SAndroid Build Coastguard Worker         MessageWrapper message_wrapper(this, std::move(*message));
811*635a8641SAndroid Build Coastguard Worker         // Sync messages may need to be handled by the endpoint if it's blocking
812*635a8641SAndroid Build Coastguard Worker         // on a sync reply. We pass ownership of the message to the endpoint's
813*635a8641SAndroid Build Coastguard Worker         // sync message queue. If the endpoint was blocking, it will dequeue the
814*635a8641SAndroid Build Coastguard Worker         // message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
815*635a8641SAndroid Build Coastguard Worker         // call will dequeue the message and dispatch it.
816*635a8641SAndroid Build Coastguard Worker         uint32_t message_id =
817*635a8641SAndroid Build Coastguard Worker             endpoint->EnqueueSyncMessage(std::move(message_wrapper));
818*635a8641SAndroid Build Coastguard Worker         proxy_task_runner_->PostTask(
819*635a8641SAndroid Build Coastguard Worker             FROM_HERE,
820*635a8641SAndroid Build Coastguard Worker             base::Bind(&ChannelAssociatedGroupController::AcceptSyncMessage,
821*635a8641SAndroid Build Coastguard Worker                        this, id, message_id));
822*635a8641SAndroid Build Coastguard Worker         return true;
823*635a8641SAndroid Build Coastguard Worker       }
824*635a8641SAndroid Build Coastguard Worker 
825*635a8641SAndroid Build Coastguard Worker       proxy_task_runner_->PostTask(
826*635a8641SAndroid Build Coastguard Worker           FROM_HERE,
827*635a8641SAndroid Build Coastguard Worker           base::Bind(&ChannelAssociatedGroupController::AcceptOnProxyThread,
828*635a8641SAndroid Build Coastguard Worker                      this, base::Passed(message)));
829*635a8641SAndroid Build Coastguard Worker       return true;
830*635a8641SAndroid Build Coastguard Worker     }
831*635a8641SAndroid Build Coastguard Worker 
832*635a8641SAndroid Build Coastguard Worker     // We do not expect to receive sync responses on the master endpoint thread.
833*635a8641SAndroid Build Coastguard Worker     // If it's happening, it's a bug.
834*635a8641SAndroid Build Coastguard Worker     DCHECK(!message->has_flag(mojo::Message::kFlagIsSync) ||
835*635a8641SAndroid Build Coastguard Worker            !message->has_flag(mojo::Message::kFlagIsResponse));
836*635a8641SAndroid Build Coastguard Worker 
837*635a8641SAndroid Build Coastguard Worker     base::AutoUnlock unlocker(lock_);
838*635a8641SAndroid Build Coastguard Worker     return client->HandleIncomingMessage(message);
839*635a8641SAndroid Build Coastguard Worker   }
840*635a8641SAndroid Build Coastguard Worker 
AcceptOnProxyThread(mojo::Message message)841*635a8641SAndroid Build Coastguard Worker   void AcceptOnProxyThread(mojo::Message message) {
842*635a8641SAndroid Build Coastguard Worker     DCHECK(proxy_task_runner_->BelongsToCurrentThread());
843*635a8641SAndroid Build Coastguard Worker 
844*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceId id = message.interface_id();
845*635a8641SAndroid Build Coastguard Worker     DCHECK(mojo::IsValidInterfaceId(id) && !mojo::IsMasterInterfaceId(id));
846*635a8641SAndroid Build Coastguard Worker 
847*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
848*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(id);
849*635a8641SAndroid Build Coastguard Worker     if (!endpoint)
850*635a8641SAndroid Build Coastguard Worker       return;
851*635a8641SAndroid Build Coastguard Worker 
852*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client = endpoint->client();
853*635a8641SAndroid Build Coastguard Worker     if (!client)
854*635a8641SAndroid Build Coastguard Worker       return;
855*635a8641SAndroid Build Coastguard Worker 
856*635a8641SAndroid Build Coastguard Worker     DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
857*635a8641SAndroid Build Coastguard Worker 
858*635a8641SAndroid Build Coastguard Worker     // Sync messages should never make their way to this method.
859*635a8641SAndroid Build Coastguard Worker     DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
860*635a8641SAndroid Build Coastguard Worker 
861*635a8641SAndroid Build Coastguard Worker     bool result = false;
862*635a8641SAndroid Build Coastguard Worker     {
863*635a8641SAndroid Build Coastguard Worker       base::AutoUnlock unlocker(lock_);
864*635a8641SAndroid Build Coastguard Worker       result = client->HandleIncomingMessage(&message);
865*635a8641SAndroid Build Coastguard Worker     }
866*635a8641SAndroid Build Coastguard Worker 
867*635a8641SAndroid Build Coastguard Worker     if (!result)
868*635a8641SAndroid Build Coastguard Worker       RaiseError();
869*635a8641SAndroid Build Coastguard Worker   }
870*635a8641SAndroid Build Coastguard Worker 
AcceptSyncMessage(mojo::InterfaceId interface_id,uint32_t message_id)871*635a8641SAndroid Build Coastguard Worker   void AcceptSyncMessage(mojo::InterfaceId interface_id, uint32_t message_id) {
872*635a8641SAndroid Build Coastguard Worker     DCHECK(proxy_task_runner_->BelongsToCurrentThread());
873*635a8641SAndroid Build Coastguard Worker 
874*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
875*635a8641SAndroid Build Coastguard Worker     Endpoint* endpoint = FindEndpoint(interface_id);
876*635a8641SAndroid Build Coastguard Worker     if (!endpoint)
877*635a8641SAndroid Build Coastguard Worker       return;
878*635a8641SAndroid Build Coastguard Worker 
879*635a8641SAndroid Build Coastguard Worker     // Careful, if the endpoint is detached its members are cleared. Check for
880*635a8641SAndroid Build Coastguard Worker     // that before dereferencing.
881*635a8641SAndroid Build Coastguard Worker     mojo::InterfaceEndpointClient* client = endpoint->client();
882*635a8641SAndroid Build Coastguard Worker     if (!client)
883*635a8641SAndroid Build Coastguard Worker       return;
884*635a8641SAndroid Build Coastguard Worker 
885*635a8641SAndroid Build Coastguard Worker     DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
886*635a8641SAndroid Build Coastguard Worker     MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
887*635a8641SAndroid Build Coastguard Worker 
888*635a8641SAndroid Build Coastguard Worker     // The message must have already been dequeued by the endpoint waking up
889*635a8641SAndroid Build Coastguard Worker     // from a sync wait. Nothing to do.
890*635a8641SAndroid Build Coastguard Worker     if (message_wrapper.value().IsNull())
891*635a8641SAndroid Build Coastguard Worker       return;
892*635a8641SAndroid Build Coastguard Worker 
893*635a8641SAndroid Build Coastguard Worker     bool result = false;
894*635a8641SAndroid Build Coastguard Worker     {
895*635a8641SAndroid Build Coastguard Worker       base::AutoUnlock unlocker(lock_);
896*635a8641SAndroid Build Coastguard Worker       result = client->HandleIncomingMessage(&message_wrapper.value());
897*635a8641SAndroid Build Coastguard Worker     }
898*635a8641SAndroid Build Coastguard Worker 
899*635a8641SAndroid Build Coastguard Worker     if (!result)
900*635a8641SAndroid Build Coastguard Worker       RaiseError();
901*635a8641SAndroid Build Coastguard Worker   }
902*635a8641SAndroid Build Coastguard Worker 
903*635a8641SAndroid Build Coastguard Worker   // mojo::PipeControlMessageHandlerDelegate:
OnPeerAssociatedEndpointClosed(mojo::InterfaceId id,const base::Optional<mojo::DisconnectReason> & reason)904*635a8641SAndroid Build Coastguard Worker   bool OnPeerAssociatedEndpointClosed(
905*635a8641SAndroid Build Coastguard Worker       mojo::InterfaceId id,
906*635a8641SAndroid Build Coastguard Worker       const base::Optional<mojo::DisconnectReason>& reason) override {
907*635a8641SAndroid Build Coastguard Worker     DCHECK(thread_checker_.CalledOnValidThread());
908*635a8641SAndroid Build Coastguard Worker 
909*635a8641SAndroid Build Coastguard Worker     scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
910*635a8641SAndroid Build Coastguard Worker     base::AutoLock locker(lock_);
911*635a8641SAndroid Build Coastguard Worker     scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
912*635a8641SAndroid Build Coastguard Worker     if (reason)
913*635a8641SAndroid Build Coastguard Worker       endpoint->set_disconnect_reason(reason);
914*635a8641SAndroid Build Coastguard Worker     if (!endpoint->peer_closed()) {
915*635a8641SAndroid Build Coastguard Worker       if (endpoint->client())
916*635a8641SAndroid Build Coastguard Worker         NotifyEndpointOfError(endpoint.get(), false /* force_async */);
917*635a8641SAndroid Build Coastguard Worker       MarkPeerClosedAndMaybeRemove(endpoint.get());
918*635a8641SAndroid Build Coastguard Worker     }
919*635a8641SAndroid Build Coastguard Worker 
920*635a8641SAndroid Build Coastguard Worker     return true;
921*635a8641SAndroid Build Coastguard Worker   }
922*635a8641SAndroid Build Coastguard Worker 
923*635a8641SAndroid Build Coastguard Worker   // Checked in places which must be run on the master endpoint's thread.
924*635a8641SAndroid Build Coastguard Worker   base::ThreadChecker thread_checker_;
925*635a8641SAndroid Build Coastguard Worker 
926*635a8641SAndroid Build Coastguard Worker   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
927*635a8641SAndroid Build Coastguard Worker 
928*635a8641SAndroid Build Coastguard Worker   scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
929*635a8641SAndroid Build Coastguard Worker   const bool set_interface_id_namespace_bit_;
930*635a8641SAndroid Build Coastguard Worker   bool paused_ = false;
931*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<mojo::Connector> connector_;
932*635a8641SAndroid Build Coastguard Worker   mojo::FilterChain filters_;
933*635a8641SAndroid Build Coastguard Worker   mojo::PipeControlMessageHandler control_message_handler_;
934*635a8641SAndroid Build Coastguard Worker   ControlMessageProxyThunk control_message_proxy_thunk_;
935*635a8641SAndroid Build Coastguard Worker 
936*635a8641SAndroid Build Coastguard Worker   // NOTE: It is unsafe to call into this object while holding |lock_|.
937*635a8641SAndroid Build Coastguard Worker   mojo::PipeControlMessageProxy control_message_proxy_;
938*635a8641SAndroid Build Coastguard Worker 
939*635a8641SAndroid Build Coastguard Worker   // Guards access to |outgoing_messages_| only. Used to support memory dumps
940*635a8641SAndroid Build Coastguard Worker   // which may be triggered from any thread.
941*635a8641SAndroid Build Coastguard Worker   base::Lock outgoing_messages_lock_;
942*635a8641SAndroid Build Coastguard Worker 
943*635a8641SAndroid Build Coastguard Worker   // Outgoing messages that were sent before this controller was bound to a
944*635a8641SAndroid Build Coastguard Worker   // real message pipe.
945*635a8641SAndroid Build Coastguard Worker   std::vector<mojo::Message> outgoing_messages_;
946*635a8641SAndroid Build Coastguard Worker 
947*635a8641SAndroid Build Coastguard Worker   // Guards the fields below for thread-safe access.
948*635a8641SAndroid Build Coastguard Worker   base::Lock lock_;
949*635a8641SAndroid Build Coastguard Worker 
950*635a8641SAndroid Build Coastguard Worker   bool encountered_error_ = false;
951*635a8641SAndroid Build Coastguard Worker   bool shut_down_ = false;
952*635a8641SAndroid Build Coastguard Worker 
953*635a8641SAndroid Build Coastguard Worker   // ID #1 is reserved for the mojom::Channel interface.
954*635a8641SAndroid Build Coastguard Worker   uint32_t next_interface_id_ = 2;
955*635a8641SAndroid Build Coastguard Worker 
956*635a8641SAndroid Build Coastguard Worker   std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
957*635a8641SAndroid Build Coastguard Worker 
958*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
959*635a8641SAndroid Build Coastguard Worker };
960*635a8641SAndroid Build Coastguard Worker 
OnMemoryDump(const base::trace_event::MemoryDumpArgs & args,base::trace_event::ProcessMemoryDump * pmd)961*635a8641SAndroid Build Coastguard Worker bool ControllerMemoryDumpProvider::OnMemoryDump(
962*635a8641SAndroid Build Coastguard Worker     const base::trace_event::MemoryDumpArgs& args,
963*635a8641SAndroid Build Coastguard Worker     base::trace_event::ProcessMemoryDump* pmd) {
964*635a8641SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
965*635a8641SAndroid Build Coastguard Worker   for (auto* controller : controllers_) {
966*635a8641SAndroid Build Coastguard Worker     base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
967*635a8641SAndroid Build Coastguard Worker         base::StringPrintf("mojo/queued_ipc_channel_message/0x%" PRIxPTR,
968*635a8641SAndroid Build Coastguard Worker                            reinterpret_cast<uintptr_t>(controller)));
969*635a8641SAndroid Build Coastguard Worker     dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
970*635a8641SAndroid Build Coastguard Worker                     base::trace_event::MemoryAllocatorDump::kUnitsObjects,
971*635a8641SAndroid Build Coastguard Worker                     controller->GetQueuedMessageCount());
972*635a8641SAndroid Build Coastguard Worker   }
973*635a8641SAndroid Build Coastguard Worker 
974*635a8641SAndroid Build Coastguard Worker   return true;
975*635a8641SAndroid Build Coastguard Worker }
976*635a8641SAndroid Build Coastguard Worker 
977*635a8641SAndroid Build Coastguard Worker class MojoBootstrapImpl : public MojoBootstrap {
978*635a8641SAndroid Build Coastguard Worker  public:
MojoBootstrapImpl(mojo::ScopedMessagePipeHandle handle,const scoped_refptr<ChannelAssociatedGroupController> controller)979*635a8641SAndroid Build Coastguard Worker   MojoBootstrapImpl(
980*635a8641SAndroid Build Coastguard Worker       mojo::ScopedMessagePipeHandle handle,
981*635a8641SAndroid Build Coastguard Worker       const scoped_refptr<ChannelAssociatedGroupController> controller)
982*635a8641SAndroid Build Coastguard Worker       : controller_(controller),
983*635a8641SAndroid Build Coastguard Worker         associated_group_(controller),
984*635a8641SAndroid Build Coastguard Worker         handle_(std::move(handle)) {}
985*635a8641SAndroid Build Coastguard Worker 
~MojoBootstrapImpl()986*635a8641SAndroid Build Coastguard Worker   ~MojoBootstrapImpl() override {
987*635a8641SAndroid Build Coastguard Worker     controller_->ShutDown();
988*635a8641SAndroid Build Coastguard Worker   }
989*635a8641SAndroid Build Coastguard Worker 
990*635a8641SAndroid Build Coastguard Worker  private:
Connect(mojom::ChannelAssociatedPtr * sender,mojom::ChannelAssociatedRequest * receiver)991*635a8641SAndroid Build Coastguard Worker   void Connect(mojom::ChannelAssociatedPtr* sender,
992*635a8641SAndroid Build Coastguard Worker                mojom::ChannelAssociatedRequest* receiver) override {
993*635a8641SAndroid Build Coastguard Worker     controller_->Bind(std::move(handle_));
994*635a8641SAndroid Build Coastguard Worker     controller_->CreateChannelEndpoints(sender, receiver);
995*635a8641SAndroid Build Coastguard Worker   }
996*635a8641SAndroid Build Coastguard Worker 
Pause()997*635a8641SAndroid Build Coastguard Worker   void Pause() override {
998*635a8641SAndroid Build Coastguard Worker     controller_->Pause();
999*635a8641SAndroid Build Coastguard Worker   }
1000*635a8641SAndroid Build Coastguard Worker 
Unpause()1001*635a8641SAndroid Build Coastguard Worker   void Unpause() override {
1002*635a8641SAndroid Build Coastguard Worker     controller_->Unpause();
1003*635a8641SAndroid Build Coastguard Worker   }
1004*635a8641SAndroid Build Coastguard Worker 
Flush()1005*635a8641SAndroid Build Coastguard Worker   void Flush() override {
1006*635a8641SAndroid Build Coastguard Worker     controller_->FlushOutgoingMessages();
1007*635a8641SAndroid Build Coastguard Worker   }
1008*635a8641SAndroid Build Coastguard Worker 
GetAssociatedGroup()1009*635a8641SAndroid Build Coastguard Worker   mojo::AssociatedGroup* GetAssociatedGroup() override {
1010*635a8641SAndroid Build Coastguard Worker     return &associated_group_;
1011*635a8641SAndroid Build Coastguard Worker   }
1012*635a8641SAndroid Build Coastguard Worker 
1013*635a8641SAndroid Build Coastguard Worker   scoped_refptr<ChannelAssociatedGroupController> controller_;
1014*635a8641SAndroid Build Coastguard Worker   mojo::AssociatedGroup associated_group_;
1015*635a8641SAndroid Build Coastguard Worker 
1016*635a8641SAndroid Build Coastguard Worker   mojo::ScopedMessagePipeHandle handle_;
1017*635a8641SAndroid Build Coastguard Worker 
1018*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl);
1019*635a8641SAndroid Build Coastguard Worker };
1020*635a8641SAndroid Build Coastguard Worker 
1021*635a8641SAndroid Build Coastguard Worker }  // namespace
1022*635a8641SAndroid Build Coastguard Worker 
1023*635a8641SAndroid 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)1024*635a8641SAndroid Build Coastguard Worker std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
1025*635a8641SAndroid Build Coastguard Worker     mojo::ScopedMessagePipeHandle handle,
1026*635a8641SAndroid Build Coastguard Worker     Channel::Mode mode,
1027*635a8641SAndroid Build Coastguard Worker     const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
1028*635a8641SAndroid Build Coastguard Worker     const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner) {
1029*635a8641SAndroid Build Coastguard Worker   return std::make_unique<MojoBootstrapImpl>(
1030*635a8641SAndroid Build Coastguard Worker       std::move(handle),
1031*635a8641SAndroid Build Coastguard Worker       new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER,
1032*635a8641SAndroid Build Coastguard Worker                                            ipc_task_runner, proxy_task_runner));
1033*635a8641SAndroid Build Coastguard Worker }
1034*635a8641SAndroid Build Coastguard Worker 
1035*635a8641SAndroid Build Coastguard Worker }  // namespace IPC
1036