blob: 85e8d26f35b9d90f6c961def7e1b96453792af86 [file] [log] [blame]
morrita54f6f80c2014-09-23 21:16:001// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
amistryd4aa70d2016-06-23 07:52:375#include "ipc/ipc_mojo_bootstrap.h"
morrita54f6f80c2014-09-23 21:16:006
Ken Rockot2b6de982018-03-20 22:28:137#include <inttypes.h>
tfarina10a5c062015-09-04 18:47:578#include <stdint.h>
rockot02b8e182016-07-13 20:08:309
10#include <map>
11#include <memory>
Ken Rockot2b6de982018-03-20 22:28:1312#include <set>
dchenge48600452015-12-28 02:24:5013#include <utility>
rockot0e4de5f2016-07-22 21:18:0714#include <vector>
tfarina10a5c062015-09-04 18:47:5715
rockota21316a2016-06-19 17:08:3616#include "base/callback.h"
Brett Wilsona62d9c02017-09-20 20:53:2017#include "base/containers/queue.h"
morrita54f6f80c2014-09-23 21:16:0018#include "base/logging.h"
avi246998d82015-12-22 02:39:0419#include "base/macros.h"
danakj03de39b22016-04-23 04:21:0920#include "base/memory/ptr_util.h"
Ken Rockot2b6de982018-03-20 22:28:1321#include "base/no_destructor.h"
Gabriel Charette14520232018-04-30 23:27:2222#include "base/sequenced_task_runner.h"
rockot02b8e182016-07-13 20:08:3023#include "base/single_thread_task_runner.h"
Ken Rockot2b6de982018-03-20 22:28:1324#include "base/strings/stringprintf.h"
rockot02b8e182016-07-13 20:08:3025#include "base/synchronization/lock.h"
Sam McNallyde5ae672017-06-19 23:34:4526#include "base/threading/thread_checker.h"
rockot02b8e182016-07-13 20:08:3027#include "base/threading/thread_task_runner_handle.h"
Ken Rockot2b6de982018-03-20 22:28:1328#include "base/trace_event/memory_allocator_dump.h"
29#include "base/trace_event/memory_dump_manager.h"
30#include "base/trace_event/memory_dump_provider.h"
Ken Rockotfb81dc02018-05-15 21:59:2631#include "ipc/ipc_channel.h"
rockot02b8e182016-07-13 20:08:3032#include "mojo/public/cpp/bindings/associated_group.h"
33#include "mojo/public/cpp/bindings/associated_group_controller.h"
rockot02b8e182016-07-13 20:08:3034#include "mojo/public/cpp/bindings/connector.h"
35#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
36#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
37#include "mojo/public/cpp/bindings/interface_id.h"
rockot0e4de5f2016-07-22 21:18:0738#include "mojo/public/cpp/bindings/message.h"
rockot02b8e182016-07-13 20:08:3039#include "mojo/public/cpp/bindings/message_header_validator.h"
40#include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
41#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
42#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
Ken Rockotaa20dcc2018-03-28 03:06:5143#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
morrita54f6f80c2014-09-23 21:16:0044
45namespace IPC {
46
47namespace {
48
Ken Rockot2b6de982018-03-20 22:28:1349class ChannelAssociatedGroupController;
50
51// Used to track some internal Channel state in pursuit of message leaks.
52//
53// TODO(https://crbug.com/813045): Remove this.
54class ControllerMemoryDumpProvider
55 : public base::trace_event::MemoryDumpProvider {
56 public:
57 ControllerMemoryDumpProvider() {
58 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
59 this, "IPCChannel", nullptr);
60 }
61
62 ~ControllerMemoryDumpProvider() override {
63 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
64 this);
65 }
66
67 void AddController(ChannelAssociatedGroupController* controller) {
68 base::AutoLock lock(lock_);
69 controllers_.insert(controller);
70 }
71
72 void RemoveController(ChannelAssociatedGroupController* controller) {
73 base::AutoLock lock(lock_);
74 controllers_.erase(controller);
75 }
76
77 // base::trace_event::MemoryDumpProvider:
78 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
79 base::trace_event::ProcessMemoryDump* pmd) override;
80
81 private:
82 base::Lock lock_;
83 std::set<ChannelAssociatedGroupController*> controllers_;
84
85 DISALLOW_COPY_AND_ASSIGN(ControllerMemoryDumpProvider);
86};
87
88ControllerMemoryDumpProvider& GetMemoryDumpProvider() {
89 static base::NoDestructor<ControllerMemoryDumpProvider> provider;
90 return *provider;
91}
92
rockot02b8e182016-07-13 20:08:3093class ChannelAssociatedGroupController
94 : public mojo::AssociatedGroupController,
95 public mojo::MessageReceiver,
96 public mojo::PipeControlMessageHandlerDelegate {
97 public:
rockot0e4de5f2016-07-22 21:18:0798 ChannelAssociatedGroupController(
99 bool set_interface_id_namespace_bit,
Hajime Hoshia98f1102017-11-20 06:34:35100 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
101 const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner)
rockotb01ef6a2016-07-27 03:24:32102 : task_runner_(ipc_task_runner),
Hajime Hoshia98f1102017-11-20 06:34:35103 proxy_task_runner_(proxy_task_runner),
rockot0e4de5f2016-07-22 21:18:07104 set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
rockot222e7dd2016-08-24 23:37:11105 filters_(this),
rockot02b8e182016-07-13 20:08:30106 control_message_handler_(this),
rockot0e4de5f2016-07-22 21:18:07107 control_message_proxy_thunk_(this),
108 control_message_proxy_(&control_message_proxy_thunk_) {
109 thread_checker_.DetachFromThread();
rockot02b8e182016-07-13 20:08:30110 control_message_handler_.SetDescription(
111 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
rockot222e7dd2016-08-24 23:37:11112 filters_.Append<mojo::MessageHeaderValidator>(
113 "IPC::mojom::Bootstrap [master] MessageHeaderValidator");
Ken Rockot2b6de982018-03-20 22:28:13114
115 GetMemoryDumpProvider().AddController(this);
116 }
117
118 size_t GetQueuedMessageCount() {
119 base::AutoLock lock(outgoing_messages_lock_);
120 return outgoing_messages_.size();
rockot02b8e182016-07-13 20:08:30121 }
122
Siddharthad1cfec12018-09-17 21:42:15123 std::pair<uint32_t, size_t> GetTopQueuedMessageNameAndCount() {
124 std::unordered_map<uint32_t, size_t> counts;
125 std::pair<uint32_t, size_t> top_message_name_and_count = {0, 0};
126 base::AutoLock lock(outgoing_messages_lock_);
127 for (const auto& message : outgoing_messages_) {
128 auto it_and_inserted = counts.emplace(message.name(), 0);
129 it_and_inserted.first->second++;
130 if (it_and_inserted.first->second > top_message_name_and_count.second)
131 top_message_name_and_count = *it_and_inserted.first;
132 }
133 return top_message_name_and_count;
134 }
135
rockot0e4de5f2016-07-22 21:18:07136 void Bind(mojo::ScopedMessagePipeHandle handle) {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 DCHECK(task_runner_->BelongsToCurrentThread());
rockot90984352016-07-25 17:36:19139
rockot0e4de5f2016-07-22 21:18:07140 connector_.reset(new mojo::Connector(
141 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
142 task_runner_));
rockot222e7dd2016-08-24 23:37:11143 connector_->set_incoming_receiver(&filters_);
rockot0e4de5f2016-07-22 21:18:07144 connector_->set_connection_error_handler(
145 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
146 base::Unretained(this)));
Ken Rockot138153b2018-07-13 23:31:57147 connector_->set_enforce_errors_from_incoming_receiver(false);
jcivelli2207af12017-01-26 20:46:00148 connector_->SetWatcherHeapProfilerTag("IPC Channel");
Ken Rockot471aa7942019-01-17 02:46:59149
150 // Don't let the Connector do any sort of queuing on our behalf. Individual
151 // messages bound for the IPC::ChannelProxy thread (i.e. that vast majority
152 // of messages received by this Connector) are already individually
153 // scheduled for dispatch by ChannelProxy, so Connector's normal mode of
154 // operation would only introduce a redundant scheduling step for most
155 // messages.
156 connector_->set_force_immediate_dispatch(true);
rockot401fb2c2016-09-06 18:35:57157 }
rockot0e4de5f2016-07-22 21:18:07158
rockot10188752016-09-08 18:24:56159 void Pause() {
160 DCHECK(!paused_);
161 paused_ = true;
162 }
163
164 void Unpause() {
165 DCHECK(paused_);
166 paused_ = false;
rockot401fb2c2016-09-06 18:35:57167 }
168
169 void FlushOutgoingMessages() {
rockotc4cc691e2016-08-19 18:48:57170 std::vector<mojo::Message> outgoing_messages;
Ken Rockot2b6de982018-03-20 22:28:13171 {
172 base::AutoLock lock(outgoing_messages_lock_);
173 std::swap(outgoing_messages, outgoing_messages_);
174 }
rockot0e4de5f2016-07-22 21:18:07175 for (auto& message : outgoing_messages)
rockotc4cc691e2016-08-19 18:48:57176 SendMessage(&message);
rockot0e4de5f2016-07-22 21:18:07177 }
178
179 void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
180 mojom::ChannelAssociatedRequest* receiver) {
181 mojo::InterfaceId sender_id, receiver_id;
182 if (set_interface_id_namespace_bit_) {
183 sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
184 receiver_id = 1;
185 } else {
186 sender_id = 1;
187 receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
188 }
189
190 {
191 base::AutoLock locker(lock_);
192 Endpoint* sender_endpoint = new Endpoint(this, sender_id);
193 Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
194 endpoints_.insert({ sender_id, sender_endpoint });
195 endpoints_.insert({ receiver_id, receiver_endpoint });
yzshen0a5971312017-02-02 05:13:47196 sender_endpoint->set_handle_created();
197 receiver_endpoint->set_handle_created();
rockot0e4de5f2016-07-22 21:18:07198 }
199
200 mojo::ScopedInterfaceEndpointHandle sender_handle =
yzshen2859a2ac2017-02-14 22:24:25201 CreateScopedInterfaceEndpointHandle(sender_id);
rockot0e4de5f2016-07-22 21:18:07202 mojo::ScopedInterfaceEndpointHandle receiver_handle =
yzshen2859a2ac2017-02-14 22:24:25203 CreateScopedInterfaceEndpointHandle(receiver_id);
rockot0e4de5f2016-07-22 21:18:07204
205 sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
Ken Rockot96d1b7b52017-05-13 00:29:21206 *receiver = mojom::ChannelAssociatedRequest(std::move(receiver_handle));
rockot0e4de5f2016-07-22 21:18:07207 }
rockot02b8e182016-07-13 20:08:30208
209 void ShutDown() {
210 DCHECK(thread_checker_.CalledOnValidThread());
Ken Rockot3e7284bb2018-02-06 16:11:16211 shut_down_ = true;
rockot0e4de5f2016-07-22 21:18:07212 connector_->CloseMessagePipe();
rockot02b8e182016-07-13 20:08:30213 OnPipeError();
rockot0e4de5f2016-07-22 21:18:07214 connector_.reset();
Ken Rockot2b6de982018-03-20 22:28:13215
216 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16217 outgoing_messages_.clear();
rockot02b8e182016-07-13 20:08:30218 }
219
220 // mojo::AssociatedGroupController:
yzshen2859a2ac2017-02-14 22:24:25221 mojo::InterfaceId AssociateInterface(
222 mojo::ScopedInterfaceEndpointHandle handle_to_send) override {
223 if (!handle_to_send.pending_association())
224 return mojo::kInvalidInterfaceId;
225
rockot02b8e182016-07-13 20:08:30226 uint32_t id = 0;
yzshen2859a2ac2017-02-14 22:24:25227 {
228 base::AutoLock locker(lock_);
229 do {
230 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
231 next_interface_id_ = 2;
232 id = next_interface_id_++;
233 if (set_interface_id_namespace_bit_)
234 id |= mojo::kInterfaceIdNamespaceMask;
235 } while (ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30236
yzshen2859a2ac2017-02-14 22:24:25237 Endpoint* endpoint = new Endpoint(this, id);
238 if (encountered_error_)
239 endpoint->set_peer_closed();
240 endpoint->set_handle_created();
241 endpoints_.insert({id, endpoint});
242 }
rockot02b8e182016-07-13 20:08:30243
yzshen2859a2ac2017-02-14 22:24:25244 if (!NotifyAssociation(&handle_to_send, id)) {
245 // The peer handle of |handle_to_send|, which is supposed to join this
246 // associated group, has been closed.
247 {
248 base::AutoLock locker(lock_);
249 Endpoint* endpoint = FindEndpoint(id);
250 if (endpoint)
251 MarkClosedAndMaybeRemove(endpoint);
252 }
253
254 control_message_proxy_.NotifyPeerEndpointClosed(
255 id, handle_to_send.disconnect_reason());
256 }
257 return id;
rockot02b8e182016-07-13 20:08:30258 }
259
260 mojo::ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(
261 mojo::InterfaceId id) override {
262 if (!mojo::IsValidInterfaceId(id))
263 return mojo::ScopedInterfaceEndpointHandle();
264
Yuzhu Shen9f87fb02017-08-11 17:07:06265 // Unless it is the master ID, |id| is from the remote side and therefore
266 // its namespace bit is supposed to be different than the value that this
267 // router would use.
268 if (!mojo::IsMasterInterfaceId(id) &&
269 set_interface_id_namespace_bit_ ==
270 mojo::HasInterfaceIdNamespaceBitSet(id)) {
271 return mojo::ScopedInterfaceEndpointHandle();
272 }
273
rockot02b8e182016-07-13 20:08:30274 base::AutoLock locker(lock_);
275 bool inserted = false;
276 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
yzshenea784ea2017-01-31 21:20:20277 if (inserted) {
278 DCHECK(!endpoint->handle_created());
279 if (encountered_error_)
280 endpoint->set_peer_closed();
281 } else {
282 if (endpoint->handle_created())
283 return mojo::ScopedInterfaceEndpointHandle();
284 }
rockot02b8e182016-07-13 20:08:30285
yzshenea784ea2017-01-31 21:20:20286 endpoint->set_handle_created();
yzshen2859a2ac2017-02-14 22:24:25287 return CreateScopedInterfaceEndpointHandle(id);
rockot02b8e182016-07-13 20:08:30288 }
289
yzshen8be41d3a2017-01-23 20:40:37290 void CloseEndpointHandle(
291 mojo::InterfaceId id,
yzshen8be41d3a2017-01-23 20:40:37292 const base::Optional<mojo::DisconnectReason>& reason) override {
rockot02b8e182016-07-13 20:08:30293 if (!mojo::IsValidInterfaceId(id))
294 return;
yzshen2859a2ac2017-02-14 22:24:25295 {
296 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14297 DCHECK(ContainsKey(endpoints_, id));
yzshen2859a2ac2017-02-14 22:24:25298 Endpoint* endpoint = endpoints_[id].get();
299 DCHECK(!endpoint->client());
300 DCHECK(!endpoint->closed());
301 MarkClosedAndMaybeRemove(endpoint);
rockot02b8e182016-07-13 20:08:30302 }
303
yzshen8be41d3a2017-01-23 20:40:37304 if (!mojo::IsMasterInterfaceId(id) || reason)
305 control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
rockot02b8e182016-07-13 20:08:30306 }
307
308 mojo::InterfaceEndpointController* AttachEndpointClient(
309 const mojo::ScopedInterfaceEndpointHandle& handle,
310 mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45311 scoped_refptr<base::SequencedTaskRunner> runner) override {
rockot02b8e182016-07-13 20:08:30312 const mojo::InterfaceId id = handle.id();
313
314 DCHECK(mojo::IsValidInterfaceId(id));
315 DCHECK(client);
316
317 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14318 DCHECK(ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30319
320 Endpoint* endpoint = endpoints_[id].get();
321 endpoint->AttachClient(client, std::move(runner));
322
323 if (endpoint->peer_closed())
324 NotifyEndpointOfError(endpoint, true /* force_async */);
325
326 return endpoint;
327 }
328
329 void DetachEndpointClient(
330 const mojo::ScopedInterfaceEndpointHandle& handle) override {
331 const mojo::InterfaceId id = handle.id();
332
333 DCHECK(mojo::IsValidInterfaceId(id));
334
335 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14336 DCHECK(ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30337
338 Endpoint* endpoint = endpoints_[id].get();
339 endpoint->DetachClient();
340 }
341
342 void RaiseError() override {
Ken Rockot138153b2018-07-13 23:31:57343 // We ignore errors on channel endpoints, leaving the pipe open. There are
344 // good reasons for this:
345 //
346 // * We should never close a channel endpoint in either process as long as
347 // the child process is still alive. The child's endpoint should only be
348 // closed implicitly by process death, and the browser's endpoint should
349 // only be closed after the child process is confirmed to be dead. Crash
350 // reporting logic in Chrome relies on this behavior in order to do the
351 // right thing.
352 //
353 // * There are two interesting conditions under which RaiseError() can be
354 // implicitly reached: an incoming message fails validation, or the
355 // local endpoint drops a response callback without calling it.
356 //
357 // * In the validation case, we also report the message as bad, and this
358 // will imminently trigger the common bad-IPC path in the browser,
359 // causing the browser to kill the offending renderer.
360 //
361 // * In the dropped response callback case, the net result of ignoring the
362 // issue is generally innocuous. While indicative of programmer error,
363 // it's not a severe failure and is already covered by separate DCHECKs.
364 //
365 // See https://crbug.com/861607 for additional discussion.
rockot02b8e182016-07-13 20:08:30366 }
367
Ken Rockot474df0142017-07-12 13:28:56368 bool PrefersSerializedMessages() override { return true; }
369
rockot02b8e182016-07-13 20:08:30370 private:
371 class Endpoint;
rockot0e4de5f2016-07-22 21:18:07372 class ControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30373 friend class Endpoint;
rockot0e4de5f2016-07-22 21:18:07374 friend class ControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30375
yzshen0a5971312017-02-02 05:13:47376 // MessageWrapper objects are always destroyed under the controller's lock. On
377 // destruction, if the message it wrappers contains
378 // ScopedInterfaceEndpointHandles (which cannot be destructed under the
379 // controller's lock), the wrapper unlocks to clean them up.
380 class MessageWrapper {
yzshenea784ea2017-01-31 21:20:20381 public:
yzshen0a5971312017-02-02 05:13:47382 MessageWrapper() = default;
yzshenea784ea2017-01-31 21:20:20383
yzshen0a5971312017-02-02 05:13:47384 MessageWrapper(ChannelAssociatedGroupController* controller,
385 mojo::Message message)
386 : controller_(controller), value_(std::move(message)) {}
yzshenea784ea2017-01-31 21:20:20387
yzshen0a5971312017-02-02 05:13:47388 MessageWrapper(MessageWrapper&& other)
yzshenea784ea2017-01-31 21:20:20389 : controller_(other.controller_), value_(std::move(other.value_)) {}
390
yzshen0a5971312017-02-02 05:13:47391 ~MessageWrapper() {
392 if (value_.associated_endpoint_handles()->empty())
yzshenea784ea2017-01-31 21:20:20393 return;
394
395 controller_->lock_.AssertAcquired();
yzshen0a5971312017-02-02 05:13:47396 {
yzshenea784ea2017-01-31 21:20:20397 base::AutoUnlock unlocker(controller_->lock_);
yzshen0a5971312017-02-02 05:13:47398 value_.mutable_associated_endpoint_handles()->clear();
yzshenea784ea2017-01-31 21:20:20399 }
400 }
401
yzshen0a5971312017-02-02 05:13:47402 MessageWrapper& operator=(MessageWrapper&& other) {
yzshenea784ea2017-01-31 21:20:20403 controller_ = other.controller_;
404 value_ = std::move(other.value_);
405 return *this;
406 }
407
yzshen0a5971312017-02-02 05:13:47408 mojo::Message& value() { return value_; }
yzshenea784ea2017-01-31 21:20:20409
410 private:
411 ChannelAssociatedGroupController* controller_ = nullptr;
yzshenea784ea2017-01-31 21:20:20412 mojo::Message value_;
413
yzshen0a5971312017-02-02 05:13:47414 DISALLOW_COPY_AND_ASSIGN(MessageWrapper);
yzshenea784ea2017-01-31 21:20:20415 };
416
rockot02b8e182016-07-13 20:08:30417 class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
418 public mojo::InterfaceEndpointController {
419 public:
420 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
421 : controller_(controller), id_(id) {}
422
423 mojo::InterfaceId id() const { return id_; }
424
425 bool closed() const {
426 controller_->lock_.AssertAcquired();
427 return closed_;
428 }
429
430 void set_closed() {
431 controller_->lock_.AssertAcquired();
432 closed_ = true;
433 }
434
435 bool peer_closed() const {
436 controller_->lock_.AssertAcquired();
437 return peer_closed_;
438 }
439
440 void set_peer_closed() {
441 controller_->lock_.AssertAcquired();
442 peer_closed_ = true;
443 }
444
yzshenea784ea2017-01-31 21:20:20445 bool handle_created() const {
446 controller_->lock_.AssertAcquired();
447 return handle_created_;
448 }
449
450 void set_handle_created() {
451 controller_->lock_.AssertAcquired();
452 handle_created_ = true;
453 }
454
yzshen8be41d3a2017-01-23 20:40:37455 const base::Optional<mojo::DisconnectReason>& disconnect_reason() const {
456 return disconnect_reason_;
457 }
458
459 void set_disconnect_reason(
460 const base::Optional<mojo::DisconnectReason>& disconnect_reason) {
461 disconnect_reason_ = disconnect_reason;
462 }
463
Sam McNallyde5ae672017-06-19 23:34:45464 base::SequencedTaskRunner* task_runner() const {
rockot02b8e182016-07-13 20:08:30465 return task_runner_.get();
466 }
467
468 mojo::InterfaceEndpointClient* client() const {
469 controller_->lock_.AssertAcquired();
470 return client_;
471 }
472
473 void AttachClient(mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45474 scoped_refptr<base::SequencedTaskRunner> runner) {
rockot02b8e182016-07-13 20:08:30475 controller_->lock_.AssertAcquired();
476 DCHECK(!client_);
477 DCHECK(!closed_);
peary28cd3bd22017-06-29 02:15:28478 DCHECK(runner->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30479
480 task_runner_ = std::move(runner);
481 client_ = client;
482 }
483
484 void DetachClient() {
485 controller_->lock_.AssertAcquired();
486 DCHECK(client_);
peary28cd3bd22017-06-29 02:15:28487 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30488 DCHECK(!closed_);
489
490 task_runner_ = nullptr;
491 client_ = nullptr;
rockot9abe09b2016-08-02 20:57:34492 sync_watcher_.reset();
493 }
494
yzshen0a5971312017-02-02 05:13:47495 uint32_t EnqueueSyncMessage(MessageWrapper message) {
rockot9abe09b2016-08-02 20:57:34496 controller_->lock_.AssertAcquired();
497 uint32_t id = GenerateSyncMessageId();
498 sync_messages_.emplace(id, std::move(message));
499 SignalSyncMessageEvent();
500 return id;
501 }
502
503 void SignalSyncMessageEvent() {
504 controller_->lock_.AssertAcquired();
yzshene25b5d52017-02-28 21:56:31505
Ken Rockotaa20dcc2018-03-28 03:06:51506 if (sync_watcher_)
507 sync_watcher_->SignalEvent();
rockot9abe09b2016-08-02 20:57:34508 }
509
yzshen0a5971312017-02-02 05:13:47510 MessageWrapper PopSyncMessage(uint32_t id) {
rockot9abe09b2016-08-02 20:57:34511 controller_->lock_.AssertAcquired();
512 if (sync_messages_.empty() || sync_messages_.front().first != id)
yzshen0a5971312017-02-02 05:13:47513 return MessageWrapper();
514 MessageWrapper message = std::move(sync_messages_.front().second);
rockot9abe09b2016-08-02 20:57:34515 sync_messages_.pop();
516 return message;
rockot02b8e182016-07-13 20:08:30517 }
518
519 // mojo::InterfaceEndpointController:
520 bool SendMessage(mojo::Message* message) override {
peary28cd3bd22017-06-29 02:15:28521 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30522 message->set_interface_id(id_);
523 return controller_->SendMessage(message);
524 }
525
526 void AllowWokenUpBySyncWatchOnSameThread() override {
peary28cd3bd22017-06-29 02:15:28527 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30528
rockot9abe09b2016-08-02 20:57:34529 EnsureSyncWatcherExists();
Ken Rockotaa20dcc2018-03-28 03:06:51530 sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence();
rockot02b8e182016-07-13 20:08:30531 }
532
533 bool SyncWatch(const bool* should_stop) override {
peary28cd3bd22017-06-29 02:15:28534 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30535
536 // It's not legal to make sync calls from the master endpoint's thread,
537 // and in fact they must only happen from the proxy task runner.
rockot7604e7b72016-07-28 17:37:39538 DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
rockot02b8e182016-07-13 20:08:30539 DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
540
rockot9abe09b2016-08-02 20:57:34541 EnsureSyncWatcherExists();
542 return sync_watcher_->SyncWatch(should_stop);
rockot02b8e182016-07-13 20:08:30543 }
544
545 private:
546 friend class base::RefCountedThreadSafe<Endpoint>;
547
rockot9abe09b2016-08-02 20:57:34548 ~Endpoint() override {
549 controller_->lock_.AssertAcquired();
550 DCHECK(!client_);
551 DCHECK(closed_);
552 DCHECK(peer_closed_);
553 DCHECK(!sync_watcher_);
554 }
555
rockotb62e2e32017-03-24 18:36:44556 void OnSyncMessageEventReady() {
peary28cd3bd22017-06-29 02:15:28557 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34558
559 scoped_refptr<Endpoint> keepalive(this);
560 scoped_refptr<AssociatedGroupController> controller_keepalive(
561 controller_);
Ken Rockotaa20dcc2018-03-28 03:06:51562 base::AutoLock locker(controller_->lock_);
563 bool more_to_process = false;
564 if (!sync_messages_.empty()) {
565 MessageWrapper message_wrapper =
566 std::move(sync_messages_.front().second);
567 sync_messages_.pop();
rockot9abe09b2016-08-02 20:57:34568
Ken Rockotaa20dcc2018-03-28 03:06:51569 bool dispatch_succeeded;
570 mojo::InterfaceEndpointClient* client = client_;
571 {
572 base::AutoUnlock unlocker(controller_->lock_);
573 dispatch_succeeded =
574 client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34575 }
576
Ken Rockotaa20dcc2018-03-28 03:06:51577 if (!sync_messages_.empty())
578 more_to_process = true;
rockot9abe09b2016-08-02 20:57:34579
Ken Rockotaa20dcc2018-03-28 03:06:51580 if (!dispatch_succeeded)
581 controller_->RaiseError();
rockot9abe09b2016-08-02 20:57:34582 }
583
Ken Rockotaa20dcc2018-03-28 03:06:51584 if (!more_to_process)
585 sync_watcher_->ResetEvent();
586
587 // If there are no queued sync messages and the peer has closed, there
588 // there won't be incoming sync messages in the future. If any
589 // SyncWatch() calls are on the stack for this endpoint, resetting the
590 // watcher will allow them to exit as the stack undwinds.
591 if (!more_to_process && peer_closed_)
rockot9abe09b2016-08-02 20:57:34592 sync_watcher_.reset();
rockot9abe09b2016-08-02 20:57:34593 }
594
595 void EnsureSyncWatcherExists() {
peary28cd3bd22017-06-29 02:15:28596 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34597 if (sync_watcher_)
598 return;
599
Ken Rockotaa20dcc2018-03-28 03:06:51600 base::AutoLock locker(controller_->lock_);
601 sync_watcher_ = std::make_unique<mojo::SequenceLocalSyncEventWatcher>(
602 base::BindRepeating(&Endpoint::OnSyncMessageEventReady,
603 base::Unretained(this)));
604 if (peer_closed_ || !sync_messages_.empty())
605 SignalSyncMessageEvent();
rockot9abe09b2016-08-02 20:57:34606 }
607
608 uint32_t GenerateSyncMessageId() {
609 // Overflow is fine.
610 uint32_t id = next_sync_message_id_++;
611 DCHECK(sync_messages_.empty() || sync_messages_.front().first != id);
612 return id;
613 }
rockot02b8e182016-07-13 20:08:30614
615 ChannelAssociatedGroupController* const controller_;
616 const mojo::InterfaceId id_;
617
618 bool closed_ = false;
619 bool peer_closed_ = false;
yzshenea784ea2017-01-31 21:20:20620 bool handle_created_ = false;
yzshen8be41d3a2017-01-23 20:40:37621 base::Optional<mojo::DisconnectReason> disconnect_reason_;
rockot02b8e182016-07-13 20:08:30622 mojo::InterfaceEndpointClient* client_ = nullptr;
Sam McNallyde5ae672017-06-19 23:34:45623 scoped_refptr<base::SequencedTaskRunner> task_runner_;
Ken Rockotaa20dcc2018-03-28 03:06:51624 std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
Brett Wilsona62d9c02017-09-20 20:53:20625 base::queue<std::pair<uint32_t, MessageWrapper>> sync_messages_;
rockot9abe09b2016-08-02 20:57:34626 uint32_t next_sync_message_id_ = 0;
rockot02b8e182016-07-13 20:08:30627
628 DISALLOW_COPY_AND_ASSIGN(Endpoint);
629 };
630
rockot0e4de5f2016-07-22 21:18:07631 class ControlMessageProxyThunk : public MessageReceiver {
632 public:
633 explicit ControlMessageProxyThunk(
634 ChannelAssociatedGroupController* controller)
635 : controller_(controller) {}
636
637 private:
638 // MessageReceiver:
639 bool Accept(mojo::Message* message) override {
640 return controller_->SendMessage(message);
641 }
642
643 ChannelAssociatedGroupController* controller_;
644
645 DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
646 };
647
rockot02b8e182016-07-13 20:08:30648 ~ChannelAssociatedGroupController() override {
rockotb01ef6a2016-07-27 03:24:32649 DCHECK(!connector_);
650
rockot02b8e182016-07-13 20:08:30651 base::AutoLock locker(lock_);
rockot02b8e182016-07-13 20:08:30652 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
653 Endpoint* endpoint = iter->second.get();
654 ++iter;
655
yzshene003d592017-01-24 21:42:17656 if (!endpoint->closed()) {
657 // This happens when a NotifyPeerEndpointClosed message been received,
yzshen2859a2ac2017-02-14 22:24:25658 // but the interface ID hasn't been used to create local endpoint
659 // handle.
yzshene003d592017-01-24 21:42:17660 DCHECK(!endpoint->client());
661 DCHECK(endpoint->peer_closed());
662 MarkClosedAndMaybeRemove(endpoint);
663 } else {
664 MarkPeerClosedAndMaybeRemove(endpoint);
665 }
rockot02b8e182016-07-13 20:08:30666 }
667
668 DCHECK(endpoints_.empty());
Ken Rockot2b6de982018-03-20 22:28:13669
670 GetMemoryDumpProvider().RemoveController(this);
rockot02b8e182016-07-13 20:08:30671 }
672
673 bool SendMessage(mojo::Message* message) {
rockot7604e7b72016-07-28 17:37:39674 if (task_runner_->BelongsToCurrentThread()) {
rockot02b8e182016-07-13 20:08:30675 DCHECK(thread_checker_.CalledOnValidThread());
rockot10188752016-09-08 18:24:56676 if (!connector_ || paused_) {
Ken Rockot37ddd8152018-02-22 18:18:46677 if (!shut_down_) {
Ken Rockot2b6de982018-03-20 22:28:13678 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16679 outgoing_messages_.emplace_back(std::move(*message));
Ken Rockot37ddd8152018-02-22 18:18:46680 }
rockot0e4de5f2016-07-22 21:18:07681 return true;
682 }
683 return connector_->Accept(message);
rockot02b8e182016-07-13 20:08:30684 } else {
Ken Rockotfb81dc02018-05-15 21:59:26685 // Do a message size check here so we don't lose valuable stack
686 // information to the task scheduler.
687 CHECK_LE(message->data_num_bytes(), Channel::kMaximumMessageSize);
688
rockotbecd3f742016-11-08 20:47:00689 // We always post tasks to the master endpoint thread when called from
690 // other threads in order to simulate IPC::ChannelProxy::Send behavior.
rockot02b8e182016-07-13 20:08:30691 task_runner_->PostTask(
692 FROM_HERE,
693 base::Bind(
694 &ChannelAssociatedGroupController::SendMessageOnMasterThread,
rockotc4cc691e2016-08-19 18:48:57695 this, base::Passed(message)));
rockot02b8e182016-07-13 20:08:30696 return true;
697 }
698 }
699
rockotc4cc691e2016-08-19 18:48:57700 void SendMessageOnMasterThread(mojo::Message message) {
rockot02b8e182016-07-13 20:08:30701 DCHECK(thread_checker_.CalledOnValidThread());
rockotc4cc691e2016-08-19 18:48:57702 if (!SendMessage(&message))
rockot02b8e182016-07-13 20:08:30703 RaiseError();
704 }
705
706 void OnPipeError() {
707 DCHECK(thread_checker_.CalledOnValidThread());
708
709 // We keep |this| alive here because it's possible for the notifications
710 // below to release all other references.
711 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
712
713 base::AutoLock locker(lock_);
714 encountered_error_ = true;
715
716 std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
717 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
718 Endpoint* endpoint = iter->second.get();
719 ++iter;
720
721 if (endpoint->client())
722 endpoints_to_notify.push_back(endpoint);
723
724 MarkPeerClosedAndMaybeRemove(endpoint);
725 }
726
727 for (auto& endpoint : endpoints_to_notify) {
rockot0e4de5f2016-07-22 21:18:07728 // Because a notification may in turn detach any endpoint, we have to
rockot02b8e182016-07-13 20:08:30729 // check each client again here.
730 if (endpoint->client())
731 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
732 }
733 }
734
735 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
736 lock_.AssertAcquired();
737 DCHECK(endpoint->task_runner() && endpoint->client());
peary28cd3bd22017-06-29 02:15:28738 if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) {
rockot02b8e182016-07-13 20:08:30739 mojo::InterfaceEndpointClient* client = endpoint->client();
yzshen8be41d3a2017-01-23 20:40:37740 base::Optional<mojo::DisconnectReason> reason(
741 endpoint->disconnect_reason());
rockot02b8e182016-07-13 20:08:30742
743 base::AutoUnlock unlocker(lock_);
yzshen8be41d3a2017-01-23 20:40:37744 client->NotifyError(reason);
rockot02b8e182016-07-13 20:08:30745 } else {
746 endpoint->task_runner()->PostTask(
747 FROM_HERE,
tzik1d692a2e2017-07-03 11:01:26748 base::Bind(&ChannelAssociatedGroupController::
749 NotifyEndpointOfErrorOnEndpointThread,
750 this, endpoint->id(), base::Unretained(endpoint)));
rockot02b8e182016-07-13 20:08:30751 }
752 }
753
rockot9abe09b2016-08-02 20:57:34754 void NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,
755 Endpoint* endpoint) {
rockot02b8e182016-07-13 20:08:30756 base::AutoLock locker(lock_);
rockot9abe09b2016-08-02 20:57:34757 auto iter = endpoints_.find(id);
758 if (iter == endpoints_.end() || iter->second.get() != endpoint)
759 return;
rockot02b8e182016-07-13 20:08:30760 if (!endpoint->client())
761 return;
rockot9abe09b2016-08-02 20:57:34762
peary28cd3bd22017-06-29 02:15:28763 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34764 NotifyEndpointOfError(endpoint, false /* force_async */);
rockot02b8e182016-07-13 20:08:30765 }
766
767 void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
768 lock_.AssertAcquired();
769 endpoint->set_closed();
770 if (endpoint->closed() && endpoint->peer_closed())
771 endpoints_.erase(endpoint->id());
772 }
773
774 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
775 lock_.AssertAcquired();
776 endpoint->set_peer_closed();
rockot9abe09b2016-08-02 20:57:34777 endpoint->SignalSyncMessageEvent();
rockot02b8e182016-07-13 20:08:30778 if (endpoint->closed() && endpoint->peer_closed())
779 endpoints_.erase(endpoint->id());
780 }
781
782 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
783 lock_.AssertAcquired();
784 DCHECK(!inserted || !*inserted);
785
yzshen0a5971312017-02-02 05:13:47786 Endpoint* endpoint = FindEndpoint(id);
787 if (!endpoint) {
788 endpoint = new Endpoint(this, id);
789 endpoints_.insert({id, endpoint});
790 if (inserted)
791 *inserted = true;
792 }
rockot02b8e182016-07-13 20:08:30793 return endpoint;
794 }
795
yzshen0a5971312017-02-02 05:13:47796 Endpoint* FindEndpoint(mojo::InterfaceId id) {
797 lock_.AssertAcquired();
798 auto iter = endpoints_.find(id);
799 return iter != endpoints_.end() ? iter->second.get() : nullptr;
800 }
801
rockot02b8e182016-07-13 20:08:30802 // mojo::MessageReceiver:
803 bool Accept(mojo::Message* message) override {
804 DCHECK(thread_checker_.CalledOnValidThread());
805
yzshen0a5971312017-02-02 05:13:47806 if (!message->DeserializeAssociatedEndpointHandles(this))
807 return false;
808
809 if (mojo::PipeControlMessageHandler::IsPipeControlMessage(message))
810 return control_message_handler_.Accept(message);
rockot02b8e182016-07-13 20:08:30811
812 mojo::InterfaceId id = message->interface_id();
813 DCHECK(mojo::IsValidInterfaceId(id));
814
815 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47816 Endpoint* endpoint = FindEndpoint(id);
817 if (!endpoint)
818 return true;
819
820 mojo::InterfaceEndpointClient* client = endpoint->client();
peary28cd3bd22017-06-29 02:15:28821 if (!client || !endpoint->task_runner()->RunsTasksInCurrentSequence()) {
rockot02b8e182016-07-13 20:08:30822 // No client has been bound yet or the client runs tasks on another
823 // thread. We assume the other thread must always be the one on which
824 // |proxy_task_runner_| runs tasks, since that's the only valid scenario.
825 //
826 // If the client is not yet bound, it must be bound by the time this task
827 // runs or else it's programmer error.
828 DCHECK(proxy_task_runner_);
rockot9abe09b2016-08-02 20:57:34829
rockotc4cc691e2016-08-19 18:48:57830 if (message->has_flag(mojo::Message::kFlagIsSync)) {
yzshen0a5971312017-02-02 05:13:47831 MessageWrapper message_wrapper(this, std::move(*message));
rockot9abe09b2016-08-02 20:57:34832 // Sync messages may need to be handled by the endpoint if it's blocking
833 // on a sync reply. We pass ownership of the message to the endpoint's
834 // sync message queue. If the endpoint was blocking, it will dequeue the
835 // message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
836 // call will dequeue the message and dispatch it.
yzshenea784ea2017-01-31 21:20:20837 uint32_t message_id =
838 endpoint->EnqueueSyncMessage(std::move(message_wrapper));
rockot9abe09b2016-08-02 20:57:34839 proxy_task_runner_->PostTask(
840 FROM_HERE,
841 base::Bind(&ChannelAssociatedGroupController::AcceptSyncMessage,
842 this, id, message_id));
843 return true;
844 }
845
rockot02b8e182016-07-13 20:08:30846 proxy_task_runner_->PostTask(
847 FROM_HERE,
848 base::Bind(&ChannelAssociatedGroupController::AcceptOnProxyThread,
rockotc4cc691e2016-08-19 18:48:57849 this, base::Passed(message)));
rockot02b8e182016-07-13 20:08:30850 return true;
851 }
852
853 // We do not expect to receive sync responses on the master endpoint thread.
854 // If it's happening, it's a bug.
rockot9abe09b2016-08-02 20:57:34855 DCHECK(!message->has_flag(mojo::Message::kFlagIsSync) ||
856 !message->has_flag(mojo::Message::kFlagIsResponse));
rockot02b8e182016-07-13 20:08:30857
rockot8d890f62016-07-14 16:37:14858 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47859 return client->HandleIncomingMessage(message);
rockot02b8e182016-07-13 20:08:30860 }
861
rockotc4cc691e2016-08-19 18:48:57862 void AcceptOnProxyThread(mojo::Message message) {
rockot02b8e182016-07-13 20:08:30863 DCHECK(proxy_task_runner_->BelongsToCurrentThread());
864
rockotc4cc691e2016-08-19 18:48:57865 mojo::InterfaceId id = message.interface_id();
rockot8d890f62016-07-14 16:37:14866 DCHECK(mojo::IsValidInterfaceId(id) && !mojo::IsMasterInterfaceId(id));
867
868 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47869 Endpoint* endpoint = FindEndpoint(id);
rockot8d890f62016-07-14 16:37:14870 if (!endpoint)
871 return;
872
873 mojo::InterfaceEndpointClient* client = endpoint->client();
874 if (!client)
875 return;
876
peary28cd3bd22017-06-29 02:15:28877 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot8d890f62016-07-14 16:37:14878
rockot9abe09b2016-08-02 20:57:34879 // Sync messages should never make their way to this method.
yzshen0a5971312017-02-02 05:13:47880 DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
rockot8d890f62016-07-14 16:37:14881
882 bool result = false;
883 {
884 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47885 result = client->HandleIncomingMessage(&message);
rockot8d890f62016-07-14 16:37:14886 }
887
888 if (!result)
889 RaiseError();
890 }
891
rockot9abe09b2016-08-02 20:57:34892 void AcceptSyncMessage(mojo::InterfaceId interface_id, uint32_t message_id) {
893 DCHECK(proxy_task_runner_->BelongsToCurrentThread());
894
895 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47896 Endpoint* endpoint = FindEndpoint(interface_id);
rockot9abe09b2016-08-02 20:57:34897 if (!endpoint)
898 return;
899
csharrison1af8d6ab2017-04-21 17:47:23900 // Careful, if the endpoint is detached its members are cleared. Check for
901 // that before dereferencing.
902 mojo::InterfaceEndpointClient* client = endpoint->client();
903 if (!client)
904 return;
905
peary28cd3bd22017-06-29 02:15:28906 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
yzshen0a5971312017-02-02 05:13:47907 MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
rockot9abe09b2016-08-02 20:57:34908
909 // The message must have already been dequeued by the endpoint waking up
910 // from a sync wait. Nothing to do.
yzshenea784ea2017-01-31 21:20:20911 if (message_wrapper.value().IsNull())
rockot9abe09b2016-08-02 20:57:34912 return;
913
rockot9abe09b2016-08-02 20:57:34914 bool result = false;
915 {
916 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47917 result = client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34918 }
919
920 if (!result)
921 RaiseError();
922 }
923
rockot02b8e182016-07-13 20:08:30924 // mojo::PipeControlMessageHandlerDelegate:
yzshen8be41d3a2017-01-23 20:40:37925 bool OnPeerAssociatedEndpointClosed(
926 mojo::InterfaceId id,
927 const base::Optional<mojo::DisconnectReason>& reason) override {
rockot02b8e182016-07-13 20:08:30928 DCHECK(thread_checker_.CalledOnValidThread());
929
rockot0e4de5f2016-07-22 21:18:07930 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
rockot02b8e182016-07-13 20:08:30931 base::AutoLock locker(lock_);
932 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
yzshen8be41d3a2017-01-23 20:40:37933 if (reason)
934 endpoint->set_disconnect_reason(reason);
rockot02b8e182016-07-13 20:08:30935 if (!endpoint->peer_closed()) {
936 if (endpoint->client())
937 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
938 MarkPeerClosedAndMaybeRemove(endpoint.get());
939 }
940
941 return true;
942 }
943
rockot02b8e182016-07-13 20:08:30944 // Checked in places which must be run on the master endpoint's thread.
945 base::ThreadChecker thread_checker_;
946
947 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
rockot0e4de5f2016-07-22 21:18:07948
rockot02b8e182016-07-13 20:08:30949 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
rockot0e4de5f2016-07-22 21:18:07950 const bool set_interface_id_namespace_bit_;
rockot10188752016-09-08 18:24:56951 bool paused_ = false;
rockot0e4de5f2016-07-22 21:18:07952 std::unique_ptr<mojo::Connector> connector_;
rockot222e7dd2016-08-24 23:37:11953 mojo::FilterChain filters_;
rockot02b8e182016-07-13 20:08:30954 mojo::PipeControlMessageHandler control_message_handler_;
rockot0e4de5f2016-07-22 21:18:07955 ControlMessageProxyThunk control_message_proxy_thunk_;
rockot58909542016-11-10 20:05:45956
957 // NOTE: It is unsafe to call into this object while holding |lock_|.
rockot0e4de5f2016-07-22 21:18:07958 mojo::PipeControlMessageProxy control_message_proxy_;
959
Ken Rockot2b6de982018-03-20 22:28:13960 // Guards access to |outgoing_messages_| only. Used to support memory dumps
961 // which may be triggered from any thread.
962 base::Lock outgoing_messages_lock_;
963
rockot0e4de5f2016-07-22 21:18:07964 // Outgoing messages that were sent before this controller was bound to a
965 // real message pipe.
rockotc4cc691e2016-08-19 18:48:57966 std::vector<mojo::Message> outgoing_messages_;
rockot02b8e182016-07-13 20:08:30967
968 // Guards the fields below for thread-safe access.
969 base::Lock lock_;
970
971 bool encountered_error_ = false;
Ken Rockot3e7284bb2018-02-06 16:11:16972 bool shut_down_ = false;
rockot0e4de5f2016-07-22 21:18:07973
974 // ID #1 is reserved for the mojom::Channel interface.
975 uint32_t next_interface_id_ = 2;
976
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14977 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
rockot02b8e182016-07-13 20:08:30978
979 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
980};
981
Ken Rockot2b6de982018-03-20 22:28:13982bool ControllerMemoryDumpProvider::OnMemoryDump(
983 const base::trace_event::MemoryDumpArgs& args,
984 base::trace_event::ProcessMemoryDump* pmd) {
985 base::AutoLock lock(lock_);
986 for (auto* controller : controllers_) {
987 base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
988 base::StringPrintf("mojo/queued_ipc_channel_message/0x%" PRIxPTR,
989 reinterpret_cast<uintptr_t>(controller)));
990 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
991 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
992 controller->GetQueuedMessageCount());
Siddharthad1cfec12018-09-17 21:42:15993 auto top_message_name_and_count =
994 controller->GetTopQueuedMessageNameAndCount();
995 dump->AddScalar("top_message_name", "id", top_message_name_and_count.first);
996 dump->AddScalar("top_message_count",
997 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
998 top_message_name_and_count.second);
Ken Rockot2b6de982018-03-20 22:28:13999 }
1000
1001 return true;
1002}
1003
rockot0e4de5f2016-07-22 21:18:071004class MojoBootstrapImpl : public MojoBootstrap {
rockot02b8e182016-07-13 20:08:301005 public:
rockot0e4de5f2016-07-22 21:18:071006 MojoBootstrapImpl(
1007 mojo::ScopedMessagePipeHandle handle,
rockot0e4de5f2016-07-22 21:18:071008 const scoped_refptr<ChannelAssociatedGroupController> controller)
yzshen2859a2ac2017-02-14 22:24:251009 : controller_(controller),
1010 associated_group_(controller),
1011 handle_(std::move(handle)) {}
rockot02b8e182016-07-13 20:08:301012
rockot0e4de5f2016-07-22 21:18:071013 ~MojoBootstrapImpl() override {
1014 controller_->ShutDown();
rockot02b8e182016-07-13 20:08:301015 }
1016
1017 private:
rockota628d0b2017-02-09 08:40:151018 void Connect(mojom::ChannelAssociatedPtr* sender,
1019 mojom::ChannelAssociatedRequest* receiver) override {
rockot0e4de5f2016-07-22 21:18:071020 controller_->Bind(std::move(handle_));
rockota628d0b2017-02-09 08:40:151021 controller_->CreateChannelEndpoints(sender, receiver);
msramek5507fee2016-07-22 10:06:211022 }
1023
rockot10188752016-09-08 18:24:561024 void Pause() override {
1025 controller_->Pause();
1026 }
1027
1028 void Unpause() override {
1029 controller_->Unpause();
rockot401fb2c2016-09-06 18:35:571030 }
1031
1032 void Flush() override {
1033 controller_->FlushOutgoingMessages();
1034 }
1035
msramek5507fee2016-07-22 10:06:211036 mojo::AssociatedGroup* GetAssociatedGroup() override {
yzshen2859a2ac2017-02-14 22:24:251037 return &associated_group_;
msramek5507fee2016-07-22 10:06:211038 }
1039
rockot0e4de5f2016-07-22 21:18:071040 scoped_refptr<ChannelAssociatedGroupController> controller_;
yzshen2859a2ac2017-02-14 22:24:251041 mojo::AssociatedGroup associated_group_;
msramek5507fee2016-07-22 10:06:211042
rockot0e4de5f2016-07-22 21:18:071043 mojo::ScopedMessagePipeHandle handle_;
msramek5507fee2016-07-22 10:06:211044
rockot0e4de5f2016-07-22 21:18:071045 DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl);
msramek5507fee2016-07-22 10:06:211046};
1047
morrita54f6f80c2014-09-23 21:16:001048} // namespace
1049
morrita54f6f80c2014-09-23 21:16:001050// static
danakj03de39b22016-04-23 04:21:091051std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
sammc57ed9f982016-03-10 06:28:351052 mojo::ScopedMessagePipeHandle handle,
1053 Channel::Mode mode,
Hajime Hoshia98f1102017-11-20 06:34:351054 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
1055 const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner) {
Jeremy Roman160eb922017-08-29 17:43:431056 return std::make_unique<MojoBootstrapImpl>(
Hajime Hoshia98f1102017-11-20 06:34:351057 std::move(handle),
1058 new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER,
1059 ipc_task_runner, proxy_task_runner));
sammc57ed9f982016-03-10 06:28:351060}
1061
morrita54f6f80c2014-09-23 21:16:001062} // namespace IPC