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