blob: ed863ba90826d4347876af6e12ddbf8338c78d6e [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"
rockot02b8e182016-07-13 20:08:3022#include "base/single_thread_task_runner.h"
Ken Rockot2b6de982018-03-20 22:28:1323#include "base/strings/stringprintf.h"
rockot02b8e182016-07-13 20:08:3024#include "base/synchronization/lock.h"
Sam McNallyde5ae672017-06-19 23:34:4525#include "base/threading/thread_checker.h"
rockot02b8e182016-07-13 20:08:3026#include "base/threading/thread_task_runner_handle.h"
Ken Rockot2b6de982018-03-20 22:28:1327#include "base/trace_event/memory_allocator_dump.h"
28#include "base/trace_event/memory_dump_manager.h"
29#include "base/trace_event/memory_dump_provider.h"
rockot02b8e182016-07-13 20:08:3030#include "mojo/public/cpp/bindings/associated_group.h"
31#include "mojo/public/cpp/bindings/associated_group_controller.h"
rockot02b8e182016-07-13 20:08:3032#include "mojo/public/cpp/bindings/connector.h"
33#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
34#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
35#include "mojo/public/cpp/bindings/interface_id.h"
rockot0e4de5f2016-07-22 21:18:0736#include "mojo/public/cpp/bindings/message.h"
rockot02b8e182016-07-13 20:08:3037#include "mojo/public/cpp/bindings/message_header_validator.h"
38#include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
39#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
40#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
Ken Rockotaa20dcc2018-03-28 03:06:5141#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
morrita54f6f80c2014-09-23 21:16:0042
43namespace IPC {
44
45namespace {
46
Ken Rockot2b6de982018-03-20 22:28:1347class ChannelAssociatedGroupController;
48
49// Used to track some internal Channel state in pursuit of message leaks.
50//
51// TODO(https://crbug.com/813045): Remove this.
52class ControllerMemoryDumpProvider
53 : public base::trace_event::MemoryDumpProvider {
54 public:
55 ControllerMemoryDumpProvider() {
56 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
57 this, "IPCChannel", nullptr);
58 }
59
60 ~ControllerMemoryDumpProvider() override {
61 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
62 this);
63 }
64
65 void AddController(ChannelAssociatedGroupController* controller) {
66 base::AutoLock lock(lock_);
67 controllers_.insert(controller);
68 }
69
70 void RemoveController(ChannelAssociatedGroupController* controller) {
71 base::AutoLock lock(lock_);
72 controllers_.erase(controller);
73 }
74
75 // base::trace_event::MemoryDumpProvider:
76 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
77 base::trace_event::ProcessMemoryDump* pmd) override;
78
79 private:
80 base::Lock lock_;
81 std::set<ChannelAssociatedGroupController*> controllers_;
82
83 DISALLOW_COPY_AND_ASSIGN(ControllerMemoryDumpProvider);
84};
85
86ControllerMemoryDumpProvider& GetMemoryDumpProvider() {
87 static base::NoDestructor<ControllerMemoryDumpProvider> provider;
88 return *provider;
89}
90
rockot02b8e182016-07-13 20:08:3091class ChannelAssociatedGroupController
92 : public mojo::AssociatedGroupController,
93 public mojo::MessageReceiver,
94 public mojo::PipeControlMessageHandlerDelegate {
95 public:
rockot0e4de5f2016-07-22 21:18:0796 ChannelAssociatedGroupController(
97 bool set_interface_id_namespace_bit,
Hajime Hoshia98f1102017-11-20 06:34:3598 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
99 const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner)
rockotb01ef6a2016-07-27 03:24:32100 : task_runner_(ipc_task_runner),
Hajime Hoshia98f1102017-11-20 06:34:35101 proxy_task_runner_(proxy_task_runner),
rockot0e4de5f2016-07-22 21:18:07102 set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
rockot222e7dd2016-08-24 23:37:11103 filters_(this),
rockot02b8e182016-07-13 20:08:30104 control_message_handler_(this),
rockot0e4de5f2016-07-22 21:18:07105 control_message_proxy_thunk_(this),
106 control_message_proxy_(&control_message_proxy_thunk_) {
107 thread_checker_.DetachFromThread();
rockot02b8e182016-07-13 20:08:30108 control_message_handler_.SetDescription(
109 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
rockot222e7dd2016-08-24 23:37:11110 filters_.Append<mojo::MessageHeaderValidator>(
111 "IPC::mojom::Bootstrap [master] MessageHeaderValidator");
Ken Rockot2b6de982018-03-20 22:28:13112
113 GetMemoryDumpProvider().AddController(this);
114 }
115
116 size_t GetQueuedMessageCount() {
117 base::AutoLock lock(outgoing_messages_lock_);
118 return outgoing_messages_.size();
rockot02b8e182016-07-13 20:08:30119 }
120
rockot0e4de5f2016-07-22 21:18:07121 void Bind(mojo::ScopedMessagePipeHandle handle) {
122 DCHECK(thread_checker_.CalledOnValidThread());
123 DCHECK(task_runner_->BelongsToCurrentThread());
rockot90984352016-07-25 17:36:19124
rockot0e4de5f2016-07-22 21:18:07125 connector_.reset(new mojo::Connector(
126 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
127 task_runner_));
rockot222e7dd2016-08-24 23:37:11128 connector_->set_incoming_receiver(&filters_);
rockot0e4de5f2016-07-22 21:18:07129 connector_->set_connection_error_handler(
130 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
131 base::Unretained(this)));
jcivelli2207af12017-01-26 20:46:00132 connector_->SetWatcherHeapProfilerTag("IPC Channel");
rockot401fb2c2016-09-06 18:35:57133 }
rockot0e4de5f2016-07-22 21:18:07134
rockot10188752016-09-08 18:24:56135 void Pause() {
136 DCHECK(!paused_);
137 paused_ = true;
138 }
139
140 void Unpause() {
141 DCHECK(paused_);
142 paused_ = false;
rockot401fb2c2016-09-06 18:35:57143 }
144
145 void FlushOutgoingMessages() {
rockotc4cc691e2016-08-19 18:48:57146 std::vector<mojo::Message> outgoing_messages;
Ken Rockot2b6de982018-03-20 22:28:13147 {
148 base::AutoLock lock(outgoing_messages_lock_);
149 std::swap(outgoing_messages, outgoing_messages_);
150 }
rockot0e4de5f2016-07-22 21:18:07151 for (auto& message : outgoing_messages)
rockotc4cc691e2016-08-19 18:48:57152 SendMessage(&message);
rockot0e4de5f2016-07-22 21:18:07153 }
154
155 void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
156 mojom::ChannelAssociatedRequest* receiver) {
157 mojo::InterfaceId sender_id, receiver_id;
158 if (set_interface_id_namespace_bit_) {
159 sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
160 receiver_id = 1;
161 } else {
162 sender_id = 1;
163 receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
164 }
165
166 {
167 base::AutoLock locker(lock_);
168 Endpoint* sender_endpoint = new Endpoint(this, sender_id);
169 Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
170 endpoints_.insert({ sender_id, sender_endpoint });
171 endpoints_.insert({ receiver_id, receiver_endpoint });
yzshen0a5971312017-02-02 05:13:47172 sender_endpoint->set_handle_created();
173 receiver_endpoint->set_handle_created();
rockot0e4de5f2016-07-22 21:18:07174 }
175
176 mojo::ScopedInterfaceEndpointHandle sender_handle =
yzshen2859a2ac2017-02-14 22:24:25177 CreateScopedInterfaceEndpointHandle(sender_id);
rockot0e4de5f2016-07-22 21:18:07178 mojo::ScopedInterfaceEndpointHandle receiver_handle =
yzshen2859a2ac2017-02-14 22:24:25179 CreateScopedInterfaceEndpointHandle(receiver_id);
rockot0e4de5f2016-07-22 21:18:07180
181 sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
Ken Rockot96d1b7b52017-05-13 00:29:21182 *receiver = mojom::ChannelAssociatedRequest(std::move(receiver_handle));
rockot0e4de5f2016-07-22 21:18:07183 }
rockot02b8e182016-07-13 20:08:30184
185 void ShutDown() {
186 DCHECK(thread_checker_.CalledOnValidThread());
Ken Rockot3e7284bb2018-02-06 16:11:16187 shut_down_ = true;
rockot0e4de5f2016-07-22 21:18:07188 connector_->CloseMessagePipe();
rockot02b8e182016-07-13 20:08:30189 OnPipeError();
rockot0e4de5f2016-07-22 21:18:07190 connector_.reset();
Ken Rockot2b6de982018-03-20 22:28:13191
192 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16193 outgoing_messages_.clear();
rockot02b8e182016-07-13 20:08:30194 }
195
196 // mojo::AssociatedGroupController:
yzshen2859a2ac2017-02-14 22:24:25197 mojo::InterfaceId AssociateInterface(
198 mojo::ScopedInterfaceEndpointHandle handle_to_send) override {
199 if (!handle_to_send.pending_association())
200 return mojo::kInvalidInterfaceId;
201
rockot02b8e182016-07-13 20:08:30202 uint32_t id = 0;
yzshen2859a2ac2017-02-14 22:24:25203 {
204 base::AutoLock locker(lock_);
205 do {
206 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
207 next_interface_id_ = 2;
208 id = next_interface_id_++;
209 if (set_interface_id_namespace_bit_)
210 id |= mojo::kInterfaceIdNamespaceMask;
211 } while (ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30212
yzshen2859a2ac2017-02-14 22:24:25213 Endpoint* endpoint = new Endpoint(this, id);
214 if (encountered_error_)
215 endpoint->set_peer_closed();
216 endpoint->set_handle_created();
217 endpoints_.insert({id, endpoint});
218 }
rockot02b8e182016-07-13 20:08:30219
yzshen2859a2ac2017-02-14 22:24:25220 if (!NotifyAssociation(&handle_to_send, id)) {
221 // The peer handle of |handle_to_send|, which is supposed to join this
222 // associated group, has been closed.
223 {
224 base::AutoLock locker(lock_);
225 Endpoint* endpoint = FindEndpoint(id);
226 if (endpoint)
227 MarkClosedAndMaybeRemove(endpoint);
228 }
229
230 control_message_proxy_.NotifyPeerEndpointClosed(
231 id, handle_to_send.disconnect_reason());
232 }
233 return id;
rockot02b8e182016-07-13 20:08:30234 }
235
236 mojo::ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(
237 mojo::InterfaceId id) override {
238 if (!mojo::IsValidInterfaceId(id))
239 return mojo::ScopedInterfaceEndpointHandle();
240
Yuzhu Shen9f87fb02017-08-11 17:07:06241 // Unless it is the master ID, |id| is from the remote side and therefore
242 // its namespace bit is supposed to be different than the value that this
243 // router would use.
244 if (!mojo::IsMasterInterfaceId(id) &&
245 set_interface_id_namespace_bit_ ==
246 mojo::HasInterfaceIdNamespaceBitSet(id)) {
247 return mojo::ScopedInterfaceEndpointHandle();
248 }
249
rockot02b8e182016-07-13 20:08:30250 base::AutoLock locker(lock_);
251 bool inserted = false;
252 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
yzshenea784ea2017-01-31 21:20:20253 if (inserted) {
254 DCHECK(!endpoint->handle_created());
255 if (encountered_error_)
256 endpoint->set_peer_closed();
257 } else {
258 if (endpoint->handle_created())
259 return mojo::ScopedInterfaceEndpointHandle();
260 }
rockot02b8e182016-07-13 20:08:30261
yzshenea784ea2017-01-31 21:20:20262 endpoint->set_handle_created();
yzshen2859a2ac2017-02-14 22:24:25263 return CreateScopedInterfaceEndpointHandle(id);
rockot02b8e182016-07-13 20:08:30264 }
265
yzshen8be41d3a2017-01-23 20:40:37266 void CloseEndpointHandle(
267 mojo::InterfaceId id,
yzshen8be41d3a2017-01-23 20:40:37268 const base::Optional<mojo::DisconnectReason>& reason) override {
rockot02b8e182016-07-13 20:08:30269 if (!mojo::IsValidInterfaceId(id))
270 return;
yzshen2859a2ac2017-02-14 22:24:25271 {
272 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14273 DCHECK(ContainsKey(endpoints_, id));
yzshen2859a2ac2017-02-14 22:24:25274 Endpoint* endpoint = endpoints_[id].get();
275 DCHECK(!endpoint->client());
276 DCHECK(!endpoint->closed());
277 MarkClosedAndMaybeRemove(endpoint);
rockot02b8e182016-07-13 20:08:30278 }
279
yzshen8be41d3a2017-01-23 20:40:37280 if (!mojo::IsMasterInterfaceId(id) || reason)
281 control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
rockot02b8e182016-07-13 20:08:30282 }
283
284 mojo::InterfaceEndpointController* AttachEndpointClient(
285 const mojo::ScopedInterfaceEndpointHandle& handle,
286 mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45287 scoped_refptr<base::SequencedTaskRunner> runner) override {
rockot02b8e182016-07-13 20:08:30288 const mojo::InterfaceId id = handle.id();
289
290 DCHECK(mojo::IsValidInterfaceId(id));
291 DCHECK(client);
292
293 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14294 DCHECK(ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30295
296 Endpoint* endpoint = endpoints_[id].get();
297 endpoint->AttachClient(client, std::move(runner));
298
299 if (endpoint->peer_closed())
300 NotifyEndpointOfError(endpoint, true /* force_async */);
301
302 return endpoint;
303 }
304
305 void DetachEndpointClient(
306 const mojo::ScopedInterfaceEndpointHandle& handle) override {
307 const mojo::InterfaceId id = handle.id();
308
309 DCHECK(mojo::IsValidInterfaceId(id));
310
311 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14312 DCHECK(ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30313
314 Endpoint* endpoint = endpoints_[id].get();
315 endpoint->DetachClient();
316 }
317
318 void RaiseError() override {
rockot7604e7b72016-07-28 17:37:39319 if (task_runner_->BelongsToCurrentThread()) {
rockot0e4de5f2016-07-22 21:18:07320 connector_->RaiseError();
rockot02b8e182016-07-13 20:08:30321 } else {
322 task_runner_->PostTask(
323 FROM_HERE,
324 base::Bind(&ChannelAssociatedGroupController::RaiseError, this));
325 }
326 }
327
Ken Rockot474df0142017-07-12 13:28:56328 bool PrefersSerializedMessages() override { return true; }
329
rockot02b8e182016-07-13 20:08:30330 private:
331 class Endpoint;
rockot0e4de5f2016-07-22 21:18:07332 class ControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30333 friend class Endpoint;
rockot0e4de5f2016-07-22 21:18:07334 friend class ControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30335
yzshen0a5971312017-02-02 05:13:47336 // MessageWrapper objects are always destroyed under the controller's lock. On
337 // destruction, if the message it wrappers contains
338 // ScopedInterfaceEndpointHandles (which cannot be destructed under the
339 // controller's lock), the wrapper unlocks to clean them up.
340 class MessageWrapper {
yzshenea784ea2017-01-31 21:20:20341 public:
yzshen0a5971312017-02-02 05:13:47342 MessageWrapper() = default;
yzshenea784ea2017-01-31 21:20:20343
yzshen0a5971312017-02-02 05:13:47344 MessageWrapper(ChannelAssociatedGroupController* controller,
345 mojo::Message message)
346 : controller_(controller), value_(std::move(message)) {}
yzshenea784ea2017-01-31 21:20:20347
yzshen0a5971312017-02-02 05:13:47348 MessageWrapper(MessageWrapper&& other)
yzshenea784ea2017-01-31 21:20:20349 : controller_(other.controller_), value_(std::move(other.value_)) {}
350
yzshen0a5971312017-02-02 05:13:47351 ~MessageWrapper() {
352 if (value_.associated_endpoint_handles()->empty())
yzshenea784ea2017-01-31 21:20:20353 return;
354
355 controller_->lock_.AssertAcquired();
yzshen0a5971312017-02-02 05:13:47356 {
yzshenea784ea2017-01-31 21:20:20357 base::AutoUnlock unlocker(controller_->lock_);
yzshen0a5971312017-02-02 05:13:47358 value_.mutable_associated_endpoint_handles()->clear();
yzshenea784ea2017-01-31 21:20:20359 }
360 }
361
yzshen0a5971312017-02-02 05:13:47362 MessageWrapper& operator=(MessageWrapper&& other) {
yzshenea784ea2017-01-31 21:20:20363 controller_ = other.controller_;
364 value_ = std::move(other.value_);
365 return *this;
366 }
367
yzshen0a5971312017-02-02 05:13:47368 mojo::Message& value() { return value_; }
yzshenea784ea2017-01-31 21:20:20369
370 private:
371 ChannelAssociatedGroupController* controller_ = nullptr;
yzshenea784ea2017-01-31 21:20:20372 mojo::Message value_;
373
yzshen0a5971312017-02-02 05:13:47374 DISALLOW_COPY_AND_ASSIGN(MessageWrapper);
yzshenea784ea2017-01-31 21:20:20375 };
376
rockot02b8e182016-07-13 20:08:30377 class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
378 public mojo::InterfaceEndpointController {
379 public:
380 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
381 : controller_(controller), id_(id) {}
382
383 mojo::InterfaceId id() const { return id_; }
384
385 bool closed() const {
386 controller_->lock_.AssertAcquired();
387 return closed_;
388 }
389
390 void set_closed() {
391 controller_->lock_.AssertAcquired();
392 closed_ = true;
393 }
394
395 bool peer_closed() const {
396 controller_->lock_.AssertAcquired();
397 return peer_closed_;
398 }
399
400 void set_peer_closed() {
401 controller_->lock_.AssertAcquired();
402 peer_closed_ = true;
403 }
404
yzshenea784ea2017-01-31 21:20:20405 bool handle_created() const {
406 controller_->lock_.AssertAcquired();
407 return handle_created_;
408 }
409
410 void set_handle_created() {
411 controller_->lock_.AssertAcquired();
412 handle_created_ = true;
413 }
414
yzshen8be41d3a2017-01-23 20:40:37415 const base::Optional<mojo::DisconnectReason>& disconnect_reason() const {
416 return disconnect_reason_;
417 }
418
419 void set_disconnect_reason(
420 const base::Optional<mojo::DisconnectReason>& disconnect_reason) {
421 disconnect_reason_ = disconnect_reason;
422 }
423
Sam McNallyde5ae672017-06-19 23:34:45424 base::SequencedTaskRunner* task_runner() const {
rockot02b8e182016-07-13 20:08:30425 return task_runner_.get();
426 }
427
428 mojo::InterfaceEndpointClient* client() const {
429 controller_->lock_.AssertAcquired();
430 return client_;
431 }
432
433 void AttachClient(mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45434 scoped_refptr<base::SequencedTaskRunner> runner) {
rockot02b8e182016-07-13 20:08:30435 controller_->lock_.AssertAcquired();
436 DCHECK(!client_);
437 DCHECK(!closed_);
peary28cd3bd22017-06-29 02:15:28438 DCHECK(runner->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30439
440 task_runner_ = std::move(runner);
441 client_ = client;
442 }
443
444 void DetachClient() {
445 controller_->lock_.AssertAcquired();
446 DCHECK(client_);
peary28cd3bd22017-06-29 02:15:28447 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30448 DCHECK(!closed_);
449
450 task_runner_ = nullptr;
451 client_ = nullptr;
rockot9abe09b2016-08-02 20:57:34452 sync_watcher_.reset();
453 }
454
yzshen0a5971312017-02-02 05:13:47455 uint32_t EnqueueSyncMessage(MessageWrapper message) {
rockot9abe09b2016-08-02 20:57:34456 controller_->lock_.AssertAcquired();
457 uint32_t id = GenerateSyncMessageId();
458 sync_messages_.emplace(id, std::move(message));
459 SignalSyncMessageEvent();
460 return id;
461 }
462
463 void SignalSyncMessageEvent() {
464 controller_->lock_.AssertAcquired();
yzshene25b5d52017-02-28 21:56:31465
Ken Rockotaa20dcc2018-03-28 03:06:51466 if (sync_watcher_)
467 sync_watcher_->SignalEvent();
rockot9abe09b2016-08-02 20:57:34468 }
469
yzshen0a5971312017-02-02 05:13:47470 MessageWrapper PopSyncMessage(uint32_t id) {
rockot9abe09b2016-08-02 20:57:34471 controller_->lock_.AssertAcquired();
472 if (sync_messages_.empty() || sync_messages_.front().first != id)
yzshen0a5971312017-02-02 05:13:47473 return MessageWrapper();
474 MessageWrapper message = std::move(sync_messages_.front().second);
rockot9abe09b2016-08-02 20:57:34475 sync_messages_.pop();
476 return message;
rockot02b8e182016-07-13 20:08:30477 }
478
479 // mojo::InterfaceEndpointController:
480 bool SendMessage(mojo::Message* message) override {
peary28cd3bd22017-06-29 02:15:28481 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30482 message->set_interface_id(id_);
483 return controller_->SendMessage(message);
484 }
485
486 void AllowWokenUpBySyncWatchOnSameThread() override {
peary28cd3bd22017-06-29 02:15:28487 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30488
rockot9abe09b2016-08-02 20:57:34489 EnsureSyncWatcherExists();
Ken Rockotaa20dcc2018-03-28 03:06:51490 sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence();
rockot02b8e182016-07-13 20:08:30491 }
492
493 bool SyncWatch(const bool* should_stop) override {
peary28cd3bd22017-06-29 02:15:28494 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30495
496 // It's not legal to make sync calls from the master endpoint's thread,
497 // and in fact they must only happen from the proxy task runner.
rockot7604e7b72016-07-28 17:37:39498 DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
rockot02b8e182016-07-13 20:08:30499 DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
500
rockot9abe09b2016-08-02 20:57:34501 EnsureSyncWatcherExists();
502 return sync_watcher_->SyncWatch(should_stop);
rockot02b8e182016-07-13 20:08:30503 }
504
505 private:
506 friend class base::RefCountedThreadSafe<Endpoint>;
507
rockot9abe09b2016-08-02 20:57:34508 ~Endpoint() override {
509 controller_->lock_.AssertAcquired();
510 DCHECK(!client_);
511 DCHECK(closed_);
512 DCHECK(peer_closed_);
513 DCHECK(!sync_watcher_);
514 }
515
rockotb62e2e32017-03-24 18:36:44516 void OnSyncMessageEventReady() {
peary28cd3bd22017-06-29 02:15:28517 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34518
519 scoped_refptr<Endpoint> keepalive(this);
520 scoped_refptr<AssociatedGroupController> controller_keepalive(
521 controller_);
Ken Rockotaa20dcc2018-03-28 03:06:51522 base::AutoLock locker(controller_->lock_);
523 bool more_to_process = false;
524 if (!sync_messages_.empty()) {
525 MessageWrapper message_wrapper =
526 std::move(sync_messages_.front().second);
527 sync_messages_.pop();
rockot9abe09b2016-08-02 20:57:34528
Ken Rockotaa20dcc2018-03-28 03:06:51529 bool dispatch_succeeded;
530 mojo::InterfaceEndpointClient* client = client_;
531 {
532 base::AutoUnlock unlocker(controller_->lock_);
533 dispatch_succeeded =
534 client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34535 }
536
Ken Rockotaa20dcc2018-03-28 03:06:51537 if (!sync_messages_.empty())
538 more_to_process = true;
rockot9abe09b2016-08-02 20:57:34539
Ken Rockotaa20dcc2018-03-28 03:06:51540 if (!dispatch_succeeded)
541 controller_->RaiseError();
rockot9abe09b2016-08-02 20:57:34542 }
543
Ken Rockotaa20dcc2018-03-28 03:06:51544 if (!more_to_process)
545 sync_watcher_->ResetEvent();
546
547 // If there are no queued sync messages and the peer has closed, there
548 // there won't be incoming sync messages in the future. If any
549 // SyncWatch() calls are on the stack for this endpoint, resetting the
550 // watcher will allow them to exit as the stack undwinds.
551 if (!more_to_process && peer_closed_)
rockot9abe09b2016-08-02 20:57:34552 sync_watcher_.reset();
rockot9abe09b2016-08-02 20:57:34553 }
554
555 void EnsureSyncWatcherExists() {
peary28cd3bd22017-06-29 02:15:28556 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34557 if (sync_watcher_)
558 return;
559
Ken Rockotaa20dcc2018-03-28 03:06:51560 base::AutoLock locker(controller_->lock_);
561 sync_watcher_ = std::make_unique<mojo::SequenceLocalSyncEventWatcher>(
562 base::BindRepeating(&Endpoint::OnSyncMessageEventReady,
563 base::Unretained(this)));
564 if (peer_closed_ || !sync_messages_.empty())
565 SignalSyncMessageEvent();
rockot9abe09b2016-08-02 20:57:34566 }
567
568 uint32_t GenerateSyncMessageId() {
569 // Overflow is fine.
570 uint32_t id = next_sync_message_id_++;
571 DCHECK(sync_messages_.empty() || sync_messages_.front().first != id);
572 return id;
573 }
rockot02b8e182016-07-13 20:08:30574
575 ChannelAssociatedGroupController* const controller_;
576 const mojo::InterfaceId id_;
577
578 bool closed_ = false;
579 bool peer_closed_ = false;
yzshenea784ea2017-01-31 21:20:20580 bool handle_created_ = false;
yzshen8be41d3a2017-01-23 20:40:37581 base::Optional<mojo::DisconnectReason> disconnect_reason_;
rockot02b8e182016-07-13 20:08:30582 mojo::InterfaceEndpointClient* client_ = nullptr;
Sam McNallyde5ae672017-06-19 23:34:45583 scoped_refptr<base::SequencedTaskRunner> task_runner_;
Ken Rockotaa20dcc2018-03-28 03:06:51584 std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
Brett Wilsona62d9c02017-09-20 20:53:20585 base::queue<std::pair<uint32_t, MessageWrapper>> sync_messages_;
rockot9abe09b2016-08-02 20:57:34586 uint32_t next_sync_message_id_ = 0;
rockot02b8e182016-07-13 20:08:30587
588 DISALLOW_COPY_AND_ASSIGN(Endpoint);
589 };
590
rockot0e4de5f2016-07-22 21:18:07591 class ControlMessageProxyThunk : public MessageReceiver {
592 public:
593 explicit ControlMessageProxyThunk(
594 ChannelAssociatedGroupController* controller)
595 : controller_(controller) {}
596
597 private:
598 // MessageReceiver:
599 bool Accept(mojo::Message* message) override {
600 return controller_->SendMessage(message);
601 }
602
603 ChannelAssociatedGroupController* controller_;
604
605 DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
606 };
607
rockot02b8e182016-07-13 20:08:30608 ~ChannelAssociatedGroupController() override {
rockotb01ef6a2016-07-27 03:24:32609 DCHECK(!connector_);
610
rockot02b8e182016-07-13 20:08:30611 base::AutoLock locker(lock_);
rockot02b8e182016-07-13 20:08:30612 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
613 Endpoint* endpoint = iter->second.get();
614 ++iter;
615
yzshene003d592017-01-24 21:42:17616 if (!endpoint->closed()) {
617 // This happens when a NotifyPeerEndpointClosed message been received,
yzshen2859a2ac2017-02-14 22:24:25618 // but the interface ID hasn't been used to create local endpoint
619 // handle.
yzshene003d592017-01-24 21:42:17620 DCHECK(!endpoint->client());
621 DCHECK(endpoint->peer_closed());
622 MarkClosedAndMaybeRemove(endpoint);
623 } else {
624 MarkPeerClosedAndMaybeRemove(endpoint);
625 }
rockot02b8e182016-07-13 20:08:30626 }
627
628 DCHECK(endpoints_.empty());
Ken Rockot2b6de982018-03-20 22:28:13629
630 GetMemoryDumpProvider().RemoveController(this);
rockot02b8e182016-07-13 20:08:30631 }
632
633 bool SendMessage(mojo::Message* message) {
rockot7604e7b72016-07-28 17:37:39634 if (task_runner_->BelongsToCurrentThread()) {
rockot02b8e182016-07-13 20:08:30635 DCHECK(thread_checker_.CalledOnValidThread());
rockot10188752016-09-08 18:24:56636 if (!connector_ || paused_) {
Ken Rockot37ddd8152018-02-22 18:18:46637 if (!shut_down_) {
Ken Rockot2b6de982018-03-20 22:28:13638 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16639 outgoing_messages_.emplace_back(std::move(*message));
Ken Rockot37ddd8152018-02-22 18:18:46640
641 // TODO(https://crbug.com/813045): Remove this. Typically this queue
642 // won't exceed something like 50 messages even on slow devices. If
643 // the massive leaks we see can be attributed to this queue, it would
644 // have to be quite a bit larger.
645 CHECK_LE(outgoing_messages_.size(), 100000u);
646 }
rockot0e4de5f2016-07-22 21:18:07647 return true;
648 }
649 return connector_->Accept(message);
rockot02b8e182016-07-13 20:08:30650 } else {
rockotbecd3f742016-11-08 20:47:00651 // We always post tasks to the master endpoint thread when called from
652 // other threads in order to simulate IPC::ChannelProxy::Send behavior.
rockot02b8e182016-07-13 20:08:30653 task_runner_->PostTask(
654 FROM_HERE,
655 base::Bind(
656 &ChannelAssociatedGroupController::SendMessageOnMasterThread,
rockotc4cc691e2016-08-19 18:48:57657 this, base::Passed(message)));
rockot02b8e182016-07-13 20:08:30658 return true;
659 }
660 }
661
rockotc4cc691e2016-08-19 18:48:57662 void SendMessageOnMasterThread(mojo::Message message) {
rockot02b8e182016-07-13 20:08:30663 DCHECK(thread_checker_.CalledOnValidThread());
rockotc4cc691e2016-08-19 18:48:57664 if (!SendMessage(&message))
rockot02b8e182016-07-13 20:08:30665 RaiseError();
666 }
667
668 void OnPipeError() {
669 DCHECK(thread_checker_.CalledOnValidThread());
670
671 // We keep |this| alive here because it's possible for the notifications
672 // below to release all other references.
673 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
674
675 base::AutoLock locker(lock_);
676 encountered_error_ = true;
677
678 std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
679 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
680 Endpoint* endpoint = iter->second.get();
681 ++iter;
682
683 if (endpoint->client())
684 endpoints_to_notify.push_back(endpoint);
685
686 MarkPeerClosedAndMaybeRemove(endpoint);
687 }
688
689 for (auto& endpoint : endpoints_to_notify) {
rockot0e4de5f2016-07-22 21:18:07690 // Because a notification may in turn detach any endpoint, we have to
rockot02b8e182016-07-13 20:08:30691 // check each client again here.
692 if (endpoint->client())
693 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
694 }
695 }
696
697 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
698 lock_.AssertAcquired();
699 DCHECK(endpoint->task_runner() && endpoint->client());
peary28cd3bd22017-06-29 02:15:28700 if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) {
rockot02b8e182016-07-13 20:08:30701 mojo::InterfaceEndpointClient* client = endpoint->client();
yzshen8be41d3a2017-01-23 20:40:37702 base::Optional<mojo::DisconnectReason> reason(
703 endpoint->disconnect_reason());
rockot02b8e182016-07-13 20:08:30704
705 base::AutoUnlock unlocker(lock_);
yzshen8be41d3a2017-01-23 20:40:37706 client->NotifyError(reason);
rockot02b8e182016-07-13 20:08:30707 } else {
708 endpoint->task_runner()->PostTask(
709 FROM_HERE,
tzik1d692a2e2017-07-03 11:01:26710 base::Bind(&ChannelAssociatedGroupController::
711 NotifyEndpointOfErrorOnEndpointThread,
712 this, endpoint->id(), base::Unretained(endpoint)));
rockot02b8e182016-07-13 20:08:30713 }
714 }
715
rockot9abe09b2016-08-02 20:57:34716 void NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,
717 Endpoint* endpoint) {
rockot02b8e182016-07-13 20:08:30718 base::AutoLock locker(lock_);
rockot9abe09b2016-08-02 20:57:34719 auto iter = endpoints_.find(id);
720 if (iter == endpoints_.end() || iter->second.get() != endpoint)
721 return;
rockot02b8e182016-07-13 20:08:30722 if (!endpoint->client())
723 return;
rockot9abe09b2016-08-02 20:57:34724
peary28cd3bd22017-06-29 02:15:28725 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34726 NotifyEndpointOfError(endpoint, false /* force_async */);
rockot02b8e182016-07-13 20:08:30727 }
728
729 void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
730 lock_.AssertAcquired();
731 endpoint->set_closed();
732 if (endpoint->closed() && endpoint->peer_closed())
733 endpoints_.erase(endpoint->id());
734 }
735
736 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
737 lock_.AssertAcquired();
738 endpoint->set_peer_closed();
rockot9abe09b2016-08-02 20:57:34739 endpoint->SignalSyncMessageEvent();
rockot02b8e182016-07-13 20:08:30740 if (endpoint->closed() && endpoint->peer_closed())
741 endpoints_.erase(endpoint->id());
742 }
743
744 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
745 lock_.AssertAcquired();
746 DCHECK(!inserted || !*inserted);
747
yzshen0a5971312017-02-02 05:13:47748 Endpoint* endpoint = FindEndpoint(id);
749 if (!endpoint) {
750 endpoint = new Endpoint(this, id);
751 endpoints_.insert({id, endpoint});
752 if (inserted)
753 *inserted = true;
754 }
rockot02b8e182016-07-13 20:08:30755 return endpoint;
756 }
757
yzshen0a5971312017-02-02 05:13:47758 Endpoint* FindEndpoint(mojo::InterfaceId id) {
759 lock_.AssertAcquired();
760 auto iter = endpoints_.find(id);
761 return iter != endpoints_.end() ? iter->second.get() : nullptr;
762 }
763
rockot02b8e182016-07-13 20:08:30764 // mojo::MessageReceiver:
765 bool Accept(mojo::Message* message) override {
766 DCHECK(thread_checker_.CalledOnValidThread());
767
yzshen0a5971312017-02-02 05:13:47768 if (!message->DeserializeAssociatedEndpointHandles(this))
769 return false;
770
771 if (mojo::PipeControlMessageHandler::IsPipeControlMessage(message))
772 return control_message_handler_.Accept(message);
rockot02b8e182016-07-13 20:08:30773
774 mojo::InterfaceId id = message->interface_id();
775 DCHECK(mojo::IsValidInterfaceId(id));
776
777 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47778 Endpoint* endpoint = FindEndpoint(id);
779 if (!endpoint)
780 return true;
781
782 mojo::InterfaceEndpointClient* client = endpoint->client();
peary28cd3bd22017-06-29 02:15:28783 if (!client || !endpoint->task_runner()->RunsTasksInCurrentSequence()) {
rockot02b8e182016-07-13 20:08:30784 // No client has been bound yet or the client runs tasks on another
785 // thread. We assume the other thread must always be the one on which
786 // |proxy_task_runner_| runs tasks, since that's the only valid scenario.
787 //
788 // If the client is not yet bound, it must be bound by the time this task
789 // runs or else it's programmer error.
790 DCHECK(proxy_task_runner_);
rockot9abe09b2016-08-02 20:57:34791
rockotc4cc691e2016-08-19 18:48:57792 if (message->has_flag(mojo::Message::kFlagIsSync)) {
yzshen0a5971312017-02-02 05:13:47793 MessageWrapper message_wrapper(this, std::move(*message));
rockot9abe09b2016-08-02 20:57:34794 // Sync messages may need to be handled by the endpoint if it's blocking
795 // on a sync reply. We pass ownership of the message to the endpoint's
796 // sync message queue. If the endpoint was blocking, it will dequeue the
797 // message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
798 // call will dequeue the message and dispatch it.
yzshenea784ea2017-01-31 21:20:20799 uint32_t message_id =
800 endpoint->EnqueueSyncMessage(std::move(message_wrapper));
rockot9abe09b2016-08-02 20:57:34801 proxy_task_runner_->PostTask(
802 FROM_HERE,
803 base::Bind(&ChannelAssociatedGroupController::AcceptSyncMessage,
804 this, id, message_id));
805 return true;
806 }
807
rockot02b8e182016-07-13 20:08:30808 proxy_task_runner_->PostTask(
809 FROM_HERE,
810 base::Bind(&ChannelAssociatedGroupController::AcceptOnProxyThread,
rockotc4cc691e2016-08-19 18:48:57811 this, base::Passed(message)));
rockot02b8e182016-07-13 20:08:30812 return true;
813 }
814
815 // We do not expect to receive sync responses on the master endpoint thread.
816 // If it's happening, it's a bug.
rockot9abe09b2016-08-02 20:57:34817 DCHECK(!message->has_flag(mojo::Message::kFlagIsSync) ||
818 !message->has_flag(mojo::Message::kFlagIsResponse));
rockot02b8e182016-07-13 20:08:30819
rockot8d890f62016-07-14 16:37:14820 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47821 return client->HandleIncomingMessage(message);
rockot02b8e182016-07-13 20:08:30822 }
823
rockotc4cc691e2016-08-19 18:48:57824 void AcceptOnProxyThread(mojo::Message message) {
rockot02b8e182016-07-13 20:08:30825 DCHECK(proxy_task_runner_->BelongsToCurrentThread());
826
rockotc4cc691e2016-08-19 18:48:57827 mojo::InterfaceId id = message.interface_id();
rockot8d890f62016-07-14 16:37:14828 DCHECK(mojo::IsValidInterfaceId(id) && !mojo::IsMasterInterfaceId(id));
829
830 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47831 Endpoint* endpoint = FindEndpoint(id);
rockot8d890f62016-07-14 16:37:14832 if (!endpoint)
833 return;
834
835 mojo::InterfaceEndpointClient* client = endpoint->client();
836 if (!client)
837 return;
838
peary28cd3bd22017-06-29 02:15:28839 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot8d890f62016-07-14 16:37:14840
rockot9abe09b2016-08-02 20:57:34841 // Sync messages should never make their way to this method.
yzshen0a5971312017-02-02 05:13:47842 DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
rockot8d890f62016-07-14 16:37:14843
844 bool result = false;
845 {
846 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47847 result = client->HandleIncomingMessage(&message);
rockot8d890f62016-07-14 16:37:14848 }
849
850 if (!result)
851 RaiseError();
852 }
853
rockot9abe09b2016-08-02 20:57:34854 void AcceptSyncMessage(mojo::InterfaceId interface_id, uint32_t message_id) {
855 DCHECK(proxy_task_runner_->BelongsToCurrentThread());
856
857 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47858 Endpoint* endpoint = FindEndpoint(interface_id);
rockot9abe09b2016-08-02 20:57:34859 if (!endpoint)
860 return;
861
csharrison1af8d6ab2017-04-21 17:47:23862 // Careful, if the endpoint is detached its members are cleared. Check for
863 // that before dereferencing.
864 mojo::InterfaceEndpointClient* client = endpoint->client();
865 if (!client)
866 return;
867
peary28cd3bd22017-06-29 02:15:28868 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
yzshen0a5971312017-02-02 05:13:47869 MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
rockot9abe09b2016-08-02 20:57:34870
871 // The message must have already been dequeued by the endpoint waking up
872 // from a sync wait. Nothing to do.
yzshenea784ea2017-01-31 21:20:20873 if (message_wrapper.value().IsNull())
rockot9abe09b2016-08-02 20:57:34874 return;
875
rockot9abe09b2016-08-02 20:57:34876 bool result = false;
877 {
878 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47879 result = client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34880 }
881
882 if (!result)
883 RaiseError();
884 }
885
rockot02b8e182016-07-13 20:08:30886 // mojo::PipeControlMessageHandlerDelegate:
yzshen8be41d3a2017-01-23 20:40:37887 bool OnPeerAssociatedEndpointClosed(
888 mojo::InterfaceId id,
889 const base::Optional<mojo::DisconnectReason>& reason) override {
rockot02b8e182016-07-13 20:08:30890 DCHECK(thread_checker_.CalledOnValidThread());
891
rockot0e4de5f2016-07-22 21:18:07892 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
rockot02b8e182016-07-13 20:08:30893 base::AutoLock locker(lock_);
894 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
yzshen8be41d3a2017-01-23 20:40:37895 if (reason)
896 endpoint->set_disconnect_reason(reason);
rockot02b8e182016-07-13 20:08:30897 if (!endpoint->peer_closed()) {
898 if (endpoint->client())
899 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
900 MarkPeerClosedAndMaybeRemove(endpoint.get());
901 }
902
903 return true;
904 }
905
rockot02b8e182016-07-13 20:08:30906 // Checked in places which must be run on the master endpoint's thread.
907 base::ThreadChecker thread_checker_;
908
909 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
rockot0e4de5f2016-07-22 21:18:07910
rockot02b8e182016-07-13 20:08:30911 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
rockot0e4de5f2016-07-22 21:18:07912 const bool set_interface_id_namespace_bit_;
rockot10188752016-09-08 18:24:56913 bool paused_ = false;
rockot0e4de5f2016-07-22 21:18:07914 std::unique_ptr<mojo::Connector> connector_;
rockot222e7dd2016-08-24 23:37:11915 mojo::FilterChain filters_;
rockot02b8e182016-07-13 20:08:30916 mojo::PipeControlMessageHandler control_message_handler_;
rockot0e4de5f2016-07-22 21:18:07917 ControlMessageProxyThunk control_message_proxy_thunk_;
rockot58909542016-11-10 20:05:45918
919 // NOTE: It is unsafe to call into this object while holding |lock_|.
rockot0e4de5f2016-07-22 21:18:07920 mojo::PipeControlMessageProxy control_message_proxy_;
921
Ken Rockot2b6de982018-03-20 22:28:13922 // Guards access to |outgoing_messages_| only. Used to support memory dumps
923 // which may be triggered from any thread.
924 base::Lock outgoing_messages_lock_;
925
rockot0e4de5f2016-07-22 21:18:07926 // Outgoing messages that were sent before this controller was bound to a
927 // real message pipe.
rockotc4cc691e2016-08-19 18:48:57928 std::vector<mojo::Message> outgoing_messages_;
rockot02b8e182016-07-13 20:08:30929
930 // Guards the fields below for thread-safe access.
931 base::Lock lock_;
932
933 bool encountered_error_ = false;
Ken Rockot3e7284bb2018-02-06 16:11:16934 bool shut_down_ = false;
rockot0e4de5f2016-07-22 21:18:07935
936 // ID #1 is reserved for the mojom::Channel interface.
937 uint32_t next_interface_id_ = 2;
938
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14939 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
rockot02b8e182016-07-13 20:08:30940
941 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
942};
943
Ken Rockot2b6de982018-03-20 22:28:13944bool ControllerMemoryDumpProvider::OnMemoryDump(
945 const base::trace_event::MemoryDumpArgs& args,
946 base::trace_event::ProcessMemoryDump* pmd) {
947 base::AutoLock lock(lock_);
948 for (auto* controller : controllers_) {
949 base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
950 base::StringPrintf("mojo/queued_ipc_channel_message/0x%" PRIxPTR,
951 reinterpret_cast<uintptr_t>(controller)));
952 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
953 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
954 controller->GetQueuedMessageCount());
955 }
956
957 return true;
958}
959
rockot0e4de5f2016-07-22 21:18:07960class MojoBootstrapImpl : public MojoBootstrap {
rockot02b8e182016-07-13 20:08:30961 public:
rockot0e4de5f2016-07-22 21:18:07962 MojoBootstrapImpl(
963 mojo::ScopedMessagePipeHandle handle,
rockot0e4de5f2016-07-22 21:18:07964 const scoped_refptr<ChannelAssociatedGroupController> controller)
yzshen2859a2ac2017-02-14 22:24:25965 : controller_(controller),
966 associated_group_(controller),
967 handle_(std::move(handle)) {}
rockot02b8e182016-07-13 20:08:30968
rockot0e4de5f2016-07-22 21:18:07969 ~MojoBootstrapImpl() override {
970 controller_->ShutDown();
rockot02b8e182016-07-13 20:08:30971 }
972
973 private:
rockota628d0b2017-02-09 08:40:15974 void Connect(mojom::ChannelAssociatedPtr* sender,
975 mojom::ChannelAssociatedRequest* receiver) override {
rockot0e4de5f2016-07-22 21:18:07976 controller_->Bind(std::move(handle_));
rockota628d0b2017-02-09 08:40:15977 controller_->CreateChannelEndpoints(sender, receiver);
msramek5507fee2016-07-22 10:06:21978 }
979
rockot10188752016-09-08 18:24:56980 void Pause() override {
981 controller_->Pause();
982 }
983
984 void Unpause() override {
985 controller_->Unpause();
rockot401fb2c2016-09-06 18:35:57986 }
987
988 void Flush() override {
989 controller_->FlushOutgoingMessages();
990 }
991
msramek5507fee2016-07-22 10:06:21992 mojo::AssociatedGroup* GetAssociatedGroup() override {
yzshen2859a2ac2017-02-14 22:24:25993 return &associated_group_;
msramek5507fee2016-07-22 10:06:21994 }
995
rockot0e4de5f2016-07-22 21:18:07996 scoped_refptr<ChannelAssociatedGroupController> controller_;
yzshen2859a2ac2017-02-14 22:24:25997 mojo::AssociatedGroup associated_group_;
msramek5507fee2016-07-22 10:06:21998
rockot0e4de5f2016-07-22 21:18:07999 mojo::ScopedMessagePipeHandle handle_;
msramek5507fee2016-07-22 10:06:211000
rockot0e4de5f2016-07-22 21:18:071001 DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl);
msramek5507fee2016-07-22 10:06:211002};
1003
morrita54f6f80c2014-09-23 21:16:001004} // namespace
1005
morrita54f6f80c2014-09-23 21:16:001006// static
danakj03de39b22016-04-23 04:21:091007std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
sammc57ed9f982016-03-10 06:28:351008 mojo::ScopedMessagePipeHandle handle,
1009 Channel::Mode mode,
Hajime Hoshia98f1102017-11-20 06:34:351010 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
1011 const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner) {
Jeremy Roman160eb922017-08-29 17:43:431012 return std::make_unique<MojoBootstrapImpl>(
Hajime Hoshia98f1102017-11-20 06:34:351013 std::move(handle),
1014 new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER,
1015 ipc_task_runner, proxy_task_runner));
sammc57ed9f982016-03-10 06:28:351016}
1017
morrita54f6f80c2014-09-23 21:16:001018} // namespace IPC