blob: 96093eb2c39e86e4fdbf0cc4e326baeb2aa36d44 [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
rockot0e4de5f2016-07-22 21:18:07123 void Bind(mojo::ScopedMessagePipeHandle handle) {
124 DCHECK(thread_checker_.CalledOnValidThread());
125 DCHECK(task_runner_->BelongsToCurrentThread());
rockot90984352016-07-25 17:36:19126
rockot0e4de5f2016-07-22 21:18:07127 connector_.reset(new mojo::Connector(
128 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
129 task_runner_));
rockot222e7dd2016-08-24 23:37:11130 connector_->set_incoming_receiver(&filters_);
rockot0e4de5f2016-07-22 21:18:07131 connector_->set_connection_error_handler(
132 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
133 base::Unretained(this)));
jcivelli2207af12017-01-26 20:46:00134 connector_->SetWatcherHeapProfilerTag("IPC Channel");
rockot401fb2c2016-09-06 18:35:57135 }
rockot0e4de5f2016-07-22 21:18:07136
rockot10188752016-09-08 18:24:56137 void Pause() {
138 DCHECK(!paused_);
139 paused_ = true;
140 }
141
142 void Unpause() {
143 DCHECK(paused_);
144 paused_ = false;
rockot401fb2c2016-09-06 18:35:57145 }
146
147 void FlushOutgoingMessages() {
rockotc4cc691e2016-08-19 18:48:57148 std::vector<mojo::Message> outgoing_messages;
Ken Rockot2b6de982018-03-20 22:28:13149 {
150 base::AutoLock lock(outgoing_messages_lock_);
151 std::swap(outgoing_messages, outgoing_messages_);
152 }
rockot0e4de5f2016-07-22 21:18:07153 for (auto& message : outgoing_messages)
rockotc4cc691e2016-08-19 18:48:57154 SendMessage(&message);
rockot0e4de5f2016-07-22 21:18:07155 }
156
157 void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
158 mojom::ChannelAssociatedRequest* receiver) {
159 mojo::InterfaceId sender_id, receiver_id;
160 if (set_interface_id_namespace_bit_) {
161 sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
162 receiver_id = 1;
163 } else {
164 sender_id = 1;
165 receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
166 }
167
168 {
169 base::AutoLock locker(lock_);
170 Endpoint* sender_endpoint = new Endpoint(this, sender_id);
171 Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
172 endpoints_.insert({ sender_id, sender_endpoint });
173 endpoints_.insert({ receiver_id, receiver_endpoint });
yzshen0a5971312017-02-02 05:13:47174 sender_endpoint->set_handle_created();
175 receiver_endpoint->set_handle_created();
rockot0e4de5f2016-07-22 21:18:07176 }
177
178 mojo::ScopedInterfaceEndpointHandle sender_handle =
yzshen2859a2ac2017-02-14 22:24:25179 CreateScopedInterfaceEndpointHandle(sender_id);
rockot0e4de5f2016-07-22 21:18:07180 mojo::ScopedInterfaceEndpointHandle receiver_handle =
yzshen2859a2ac2017-02-14 22:24:25181 CreateScopedInterfaceEndpointHandle(receiver_id);
rockot0e4de5f2016-07-22 21:18:07182
183 sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
Ken Rockot96d1b7b52017-05-13 00:29:21184 *receiver = mojom::ChannelAssociatedRequest(std::move(receiver_handle));
rockot0e4de5f2016-07-22 21:18:07185 }
rockot02b8e182016-07-13 20:08:30186
187 void ShutDown() {
188 DCHECK(thread_checker_.CalledOnValidThread());
Ken Rockot3e7284bb2018-02-06 16:11:16189 shut_down_ = true;
rockot0e4de5f2016-07-22 21:18:07190 connector_->CloseMessagePipe();
rockot02b8e182016-07-13 20:08:30191 OnPipeError();
rockot0e4de5f2016-07-22 21:18:07192 connector_.reset();
Ken Rockot2b6de982018-03-20 22:28:13193
194 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16195 outgoing_messages_.clear();
rockot02b8e182016-07-13 20:08:30196 }
197
198 // mojo::AssociatedGroupController:
yzshen2859a2ac2017-02-14 22:24:25199 mojo::InterfaceId AssociateInterface(
200 mojo::ScopedInterfaceEndpointHandle handle_to_send) override {
201 if (!handle_to_send.pending_association())
202 return mojo::kInvalidInterfaceId;
203
rockot02b8e182016-07-13 20:08:30204 uint32_t id = 0;
yzshen2859a2ac2017-02-14 22:24:25205 {
206 base::AutoLock locker(lock_);
207 do {
208 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
209 next_interface_id_ = 2;
210 id = next_interface_id_++;
211 if (set_interface_id_namespace_bit_)
212 id |= mojo::kInterfaceIdNamespaceMask;
213 } while (ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30214
yzshen2859a2ac2017-02-14 22:24:25215 Endpoint* endpoint = new Endpoint(this, id);
216 if (encountered_error_)
217 endpoint->set_peer_closed();
218 endpoint->set_handle_created();
219 endpoints_.insert({id, endpoint});
220 }
rockot02b8e182016-07-13 20:08:30221
yzshen2859a2ac2017-02-14 22:24:25222 if (!NotifyAssociation(&handle_to_send, id)) {
223 // The peer handle of |handle_to_send|, which is supposed to join this
224 // associated group, has been closed.
225 {
226 base::AutoLock locker(lock_);
227 Endpoint* endpoint = FindEndpoint(id);
228 if (endpoint)
229 MarkClosedAndMaybeRemove(endpoint);
230 }
231
232 control_message_proxy_.NotifyPeerEndpointClosed(
233 id, handle_to_send.disconnect_reason());
234 }
235 return id;
rockot02b8e182016-07-13 20:08:30236 }
237
238 mojo::ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(
239 mojo::InterfaceId id) override {
240 if (!mojo::IsValidInterfaceId(id))
241 return mojo::ScopedInterfaceEndpointHandle();
242
Yuzhu Shen9f87fb02017-08-11 17:07:06243 // Unless it is the master ID, |id| is from the remote side and therefore
244 // its namespace bit is supposed to be different than the value that this
245 // router would use.
246 if (!mojo::IsMasterInterfaceId(id) &&
247 set_interface_id_namespace_bit_ ==
248 mojo::HasInterfaceIdNamespaceBitSet(id)) {
249 return mojo::ScopedInterfaceEndpointHandle();
250 }
251
rockot02b8e182016-07-13 20:08:30252 base::AutoLock locker(lock_);
253 bool inserted = false;
254 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
yzshenea784ea2017-01-31 21:20:20255 if (inserted) {
256 DCHECK(!endpoint->handle_created());
257 if (encountered_error_)
258 endpoint->set_peer_closed();
259 } else {
260 if (endpoint->handle_created())
261 return mojo::ScopedInterfaceEndpointHandle();
262 }
rockot02b8e182016-07-13 20:08:30263
yzshenea784ea2017-01-31 21:20:20264 endpoint->set_handle_created();
yzshen2859a2ac2017-02-14 22:24:25265 return CreateScopedInterfaceEndpointHandle(id);
rockot02b8e182016-07-13 20:08:30266 }
267
yzshen8be41d3a2017-01-23 20:40:37268 void CloseEndpointHandle(
269 mojo::InterfaceId id,
yzshen8be41d3a2017-01-23 20:40:37270 const base::Optional<mojo::DisconnectReason>& reason) override {
rockot02b8e182016-07-13 20:08:30271 if (!mojo::IsValidInterfaceId(id))
272 return;
yzshen2859a2ac2017-02-14 22:24:25273 {
274 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14275 DCHECK(ContainsKey(endpoints_, id));
yzshen2859a2ac2017-02-14 22:24:25276 Endpoint* endpoint = endpoints_[id].get();
277 DCHECK(!endpoint->client());
278 DCHECK(!endpoint->closed());
279 MarkClosedAndMaybeRemove(endpoint);
rockot02b8e182016-07-13 20:08:30280 }
281
yzshen8be41d3a2017-01-23 20:40:37282 if (!mojo::IsMasterInterfaceId(id) || reason)
283 control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
rockot02b8e182016-07-13 20:08:30284 }
285
286 mojo::InterfaceEndpointController* AttachEndpointClient(
287 const mojo::ScopedInterfaceEndpointHandle& handle,
288 mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45289 scoped_refptr<base::SequencedTaskRunner> runner) override {
rockot02b8e182016-07-13 20:08:30290 const mojo::InterfaceId id = handle.id();
291
292 DCHECK(mojo::IsValidInterfaceId(id));
293 DCHECK(client);
294
295 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14296 DCHECK(ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30297
298 Endpoint* endpoint = endpoints_[id].get();
299 endpoint->AttachClient(client, std::move(runner));
300
301 if (endpoint->peer_closed())
302 NotifyEndpointOfError(endpoint, true /* force_async */);
303
304 return endpoint;
305 }
306
307 void DetachEndpointClient(
308 const mojo::ScopedInterfaceEndpointHandle& handle) override {
309 const mojo::InterfaceId id = handle.id();
310
311 DCHECK(mojo::IsValidInterfaceId(id));
312
313 base::AutoLock locker(lock_);
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14314 DCHECK(ContainsKey(endpoints_, id));
rockot02b8e182016-07-13 20:08:30315
316 Endpoint* endpoint = endpoints_[id].get();
317 endpoint->DetachClient();
318 }
319
320 void RaiseError() override {
rockot7604e7b72016-07-28 17:37:39321 if (task_runner_->BelongsToCurrentThread()) {
rockot0e4de5f2016-07-22 21:18:07322 connector_->RaiseError();
rockot02b8e182016-07-13 20:08:30323 } else {
324 task_runner_->PostTask(
325 FROM_HERE,
326 base::Bind(&ChannelAssociatedGroupController::RaiseError, this));
327 }
328 }
329
Ken Rockot474df0142017-07-12 13:28:56330 bool PrefersSerializedMessages() override { return true; }
331
rockot02b8e182016-07-13 20:08:30332 private:
333 class Endpoint;
rockot0e4de5f2016-07-22 21:18:07334 class ControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30335 friend class Endpoint;
rockot0e4de5f2016-07-22 21:18:07336 friend class ControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30337
yzshen0a5971312017-02-02 05:13:47338 // MessageWrapper objects are always destroyed under the controller's lock. On
339 // destruction, if the message it wrappers contains
340 // ScopedInterfaceEndpointHandles (which cannot be destructed under the
341 // controller's lock), the wrapper unlocks to clean them up.
342 class MessageWrapper {
yzshenea784ea2017-01-31 21:20:20343 public:
yzshen0a5971312017-02-02 05:13:47344 MessageWrapper() = default;
yzshenea784ea2017-01-31 21:20:20345
yzshen0a5971312017-02-02 05:13:47346 MessageWrapper(ChannelAssociatedGroupController* controller,
347 mojo::Message message)
348 : controller_(controller), value_(std::move(message)) {}
yzshenea784ea2017-01-31 21:20:20349
yzshen0a5971312017-02-02 05:13:47350 MessageWrapper(MessageWrapper&& other)
yzshenea784ea2017-01-31 21:20:20351 : controller_(other.controller_), value_(std::move(other.value_)) {}
352
yzshen0a5971312017-02-02 05:13:47353 ~MessageWrapper() {
354 if (value_.associated_endpoint_handles()->empty())
yzshenea784ea2017-01-31 21:20:20355 return;
356
357 controller_->lock_.AssertAcquired();
yzshen0a5971312017-02-02 05:13:47358 {
yzshenea784ea2017-01-31 21:20:20359 base::AutoUnlock unlocker(controller_->lock_);
yzshen0a5971312017-02-02 05:13:47360 value_.mutable_associated_endpoint_handles()->clear();
yzshenea784ea2017-01-31 21:20:20361 }
362 }
363
yzshen0a5971312017-02-02 05:13:47364 MessageWrapper& operator=(MessageWrapper&& other) {
yzshenea784ea2017-01-31 21:20:20365 controller_ = other.controller_;
366 value_ = std::move(other.value_);
367 return *this;
368 }
369
yzshen0a5971312017-02-02 05:13:47370 mojo::Message& value() { return value_; }
yzshenea784ea2017-01-31 21:20:20371
372 private:
373 ChannelAssociatedGroupController* controller_ = nullptr;
yzshenea784ea2017-01-31 21:20:20374 mojo::Message value_;
375
yzshen0a5971312017-02-02 05:13:47376 DISALLOW_COPY_AND_ASSIGN(MessageWrapper);
yzshenea784ea2017-01-31 21:20:20377 };
378
rockot02b8e182016-07-13 20:08:30379 class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
380 public mojo::InterfaceEndpointController {
381 public:
382 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
383 : controller_(controller), id_(id) {}
384
385 mojo::InterfaceId id() const { return id_; }
386
387 bool closed() const {
388 controller_->lock_.AssertAcquired();
389 return closed_;
390 }
391
392 void set_closed() {
393 controller_->lock_.AssertAcquired();
394 closed_ = true;
395 }
396
397 bool peer_closed() const {
398 controller_->lock_.AssertAcquired();
399 return peer_closed_;
400 }
401
402 void set_peer_closed() {
403 controller_->lock_.AssertAcquired();
404 peer_closed_ = true;
405 }
406
yzshenea784ea2017-01-31 21:20:20407 bool handle_created() const {
408 controller_->lock_.AssertAcquired();
409 return handle_created_;
410 }
411
412 void set_handle_created() {
413 controller_->lock_.AssertAcquired();
414 handle_created_ = true;
415 }
416
yzshen8be41d3a2017-01-23 20:40:37417 const base::Optional<mojo::DisconnectReason>& disconnect_reason() const {
418 return disconnect_reason_;
419 }
420
421 void set_disconnect_reason(
422 const base::Optional<mojo::DisconnectReason>& disconnect_reason) {
423 disconnect_reason_ = disconnect_reason;
424 }
425
Sam McNallyde5ae672017-06-19 23:34:45426 base::SequencedTaskRunner* task_runner() const {
rockot02b8e182016-07-13 20:08:30427 return task_runner_.get();
428 }
429
430 mojo::InterfaceEndpointClient* client() const {
431 controller_->lock_.AssertAcquired();
432 return client_;
433 }
434
435 void AttachClient(mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45436 scoped_refptr<base::SequencedTaskRunner> runner) {
rockot02b8e182016-07-13 20:08:30437 controller_->lock_.AssertAcquired();
438 DCHECK(!client_);
439 DCHECK(!closed_);
peary28cd3bd22017-06-29 02:15:28440 DCHECK(runner->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30441
442 task_runner_ = std::move(runner);
443 client_ = client;
444 }
445
446 void DetachClient() {
447 controller_->lock_.AssertAcquired();
448 DCHECK(client_);
peary28cd3bd22017-06-29 02:15:28449 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30450 DCHECK(!closed_);
451
452 task_runner_ = nullptr;
453 client_ = nullptr;
rockot9abe09b2016-08-02 20:57:34454 sync_watcher_.reset();
455 }
456
yzshen0a5971312017-02-02 05:13:47457 uint32_t EnqueueSyncMessage(MessageWrapper message) {
rockot9abe09b2016-08-02 20:57:34458 controller_->lock_.AssertAcquired();
459 uint32_t id = GenerateSyncMessageId();
460 sync_messages_.emplace(id, std::move(message));
461 SignalSyncMessageEvent();
462 return id;
463 }
464
465 void SignalSyncMessageEvent() {
466 controller_->lock_.AssertAcquired();
yzshene25b5d52017-02-28 21:56:31467
Ken Rockotaa20dcc2018-03-28 03:06:51468 if (sync_watcher_)
469 sync_watcher_->SignalEvent();
rockot9abe09b2016-08-02 20:57:34470 }
471
yzshen0a5971312017-02-02 05:13:47472 MessageWrapper PopSyncMessage(uint32_t id) {
rockot9abe09b2016-08-02 20:57:34473 controller_->lock_.AssertAcquired();
474 if (sync_messages_.empty() || sync_messages_.front().first != id)
yzshen0a5971312017-02-02 05:13:47475 return MessageWrapper();
476 MessageWrapper message = std::move(sync_messages_.front().second);
rockot9abe09b2016-08-02 20:57:34477 sync_messages_.pop();
478 return message;
rockot02b8e182016-07-13 20:08:30479 }
480
481 // mojo::InterfaceEndpointController:
482 bool SendMessage(mojo::Message* message) override {
peary28cd3bd22017-06-29 02:15:28483 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30484 message->set_interface_id(id_);
485 return controller_->SendMessage(message);
486 }
487
488 void AllowWokenUpBySyncWatchOnSameThread() override {
peary28cd3bd22017-06-29 02:15:28489 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30490
rockot9abe09b2016-08-02 20:57:34491 EnsureSyncWatcherExists();
Ken Rockotaa20dcc2018-03-28 03:06:51492 sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence();
rockot02b8e182016-07-13 20:08:30493 }
494
495 bool SyncWatch(const bool* should_stop) override {
peary28cd3bd22017-06-29 02:15:28496 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30497
498 // It's not legal to make sync calls from the master endpoint's thread,
499 // and in fact they must only happen from the proxy task runner.
rockot7604e7b72016-07-28 17:37:39500 DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
rockot02b8e182016-07-13 20:08:30501 DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
502
rockot9abe09b2016-08-02 20:57:34503 EnsureSyncWatcherExists();
504 return sync_watcher_->SyncWatch(should_stop);
rockot02b8e182016-07-13 20:08:30505 }
506
507 private:
508 friend class base::RefCountedThreadSafe<Endpoint>;
509
rockot9abe09b2016-08-02 20:57:34510 ~Endpoint() override {
511 controller_->lock_.AssertAcquired();
512 DCHECK(!client_);
513 DCHECK(closed_);
514 DCHECK(peer_closed_);
515 DCHECK(!sync_watcher_);
516 }
517
rockotb62e2e32017-03-24 18:36:44518 void OnSyncMessageEventReady() {
peary28cd3bd22017-06-29 02:15:28519 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34520
521 scoped_refptr<Endpoint> keepalive(this);
522 scoped_refptr<AssociatedGroupController> controller_keepalive(
523 controller_);
Ken Rockotaa20dcc2018-03-28 03:06:51524 base::AutoLock locker(controller_->lock_);
525 bool more_to_process = false;
526 if (!sync_messages_.empty()) {
527 MessageWrapper message_wrapper =
528 std::move(sync_messages_.front().second);
529 sync_messages_.pop();
rockot9abe09b2016-08-02 20:57:34530
Ken Rockotaa20dcc2018-03-28 03:06:51531 bool dispatch_succeeded;
532 mojo::InterfaceEndpointClient* client = client_;
533 {
534 base::AutoUnlock unlocker(controller_->lock_);
535 dispatch_succeeded =
536 client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34537 }
538
Ken Rockotaa20dcc2018-03-28 03:06:51539 if (!sync_messages_.empty())
540 more_to_process = true;
rockot9abe09b2016-08-02 20:57:34541
Ken Rockotaa20dcc2018-03-28 03:06:51542 if (!dispatch_succeeded)
543 controller_->RaiseError();
rockot9abe09b2016-08-02 20:57:34544 }
545
Ken Rockotaa20dcc2018-03-28 03:06:51546 if (!more_to_process)
547 sync_watcher_->ResetEvent();
548
549 // If there are no queued sync messages and the peer has closed, there
550 // there won't be incoming sync messages in the future. If any
551 // SyncWatch() calls are on the stack for this endpoint, resetting the
552 // watcher will allow them to exit as the stack undwinds.
553 if (!more_to_process && peer_closed_)
rockot9abe09b2016-08-02 20:57:34554 sync_watcher_.reset();
rockot9abe09b2016-08-02 20:57:34555 }
556
557 void EnsureSyncWatcherExists() {
peary28cd3bd22017-06-29 02:15:28558 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34559 if (sync_watcher_)
560 return;
561
Ken Rockotaa20dcc2018-03-28 03:06:51562 base::AutoLock locker(controller_->lock_);
563 sync_watcher_ = std::make_unique<mojo::SequenceLocalSyncEventWatcher>(
564 base::BindRepeating(&Endpoint::OnSyncMessageEventReady,
565 base::Unretained(this)));
566 if (peer_closed_ || !sync_messages_.empty())
567 SignalSyncMessageEvent();
rockot9abe09b2016-08-02 20:57:34568 }
569
570 uint32_t GenerateSyncMessageId() {
571 // Overflow is fine.
572 uint32_t id = next_sync_message_id_++;
573 DCHECK(sync_messages_.empty() || sync_messages_.front().first != id);
574 return id;
575 }
rockot02b8e182016-07-13 20:08:30576
577 ChannelAssociatedGroupController* const controller_;
578 const mojo::InterfaceId id_;
579
580 bool closed_ = false;
581 bool peer_closed_ = false;
yzshenea784ea2017-01-31 21:20:20582 bool handle_created_ = false;
yzshen8be41d3a2017-01-23 20:40:37583 base::Optional<mojo::DisconnectReason> disconnect_reason_;
rockot02b8e182016-07-13 20:08:30584 mojo::InterfaceEndpointClient* client_ = nullptr;
Sam McNallyde5ae672017-06-19 23:34:45585 scoped_refptr<base::SequencedTaskRunner> task_runner_;
Ken Rockotaa20dcc2018-03-28 03:06:51586 std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
Brett Wilsona62d9c02017-09-20 20:53:20587 base::queue<std::pair<uint32_t, MessageWrapper>> sync_messages_;
rockot9abe09b2016-08-02 20:57:34588 uint32_t next_sync_message_id_ = 0;
rockot02b8e182016-07-13 20:08:30589
590 DISALLOW_COPY_AND_ASSIGN(Endpoint);
591 };
592
rockot0e4de5f2016-07-22 21:18:07593 class ControlMessageProxyThunk : public MessageReceiver {
594 public:
595 explicit ControlMessageProxyThunk(
596 ChannelAssociatedGroupController* controller)
597 : controller_(controller) {}
598
599 private:
600 // MessageReceiver:
601 bool Accept(mojo::Message* message) override {
602 return controller_->SendMessage(message);
603 }
604
605 ChannelAssociatedGroupController* controller_;
606
607 DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
608 };
609
rockot02b8e182016-07-13 20:08:30610 ~ChannelAssociatedGroupController() override {
rockotb01ef6a2016-07-27 03:24:32611 DCHECK(!connector_);
612
rockot02b8e182016-07-13 20:08:30613 base::AutoLock locker(lock_);
rockot02b8e182016-07-13 20:08:30614 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
615 Endpoint* endpoint = iter->second.get();
616 ++iter;
617
yzshene003d592017-01-24 21:42:17618 if (!endpoint->closed()) {
619 // This happens when a NotifyPeerEndpointClosed message been received,
yzshen2859a2ac2017-02-14 22:24:25620 // but the interface ID hasn't been used to create local endpoint
621 // handle.
yzshene003d592017-01-24 21:42:17622 DCHECK(!endpoint->client());
623 DCHECK(endpoint->peer_closed());
624 MarkClosedAndMaybeRemove(endpoint);
625 } else {
626 MarkPeerClosedAndMaybeRemove(endpoint);
627 }
rockot02b8e182016-07-13 20:08:30628 }
629
630 DCHECK(endpoints_.empty());
Ken Rockot2b6de982018-03-20 22:28:13631
632 GetMemoryDumpProvider().RemoveController(this);
rockot02b8e182016-07-13 20:08:30633 }
634
635 bool SendMessage(mojo::Message* message) {
rockot7604e7b72016-07-28 17:37:39636 if (task_runner_->BelongsToCurrentThread()) {
rockot02b8e182016-07-13 20:08:30637 DCHECK(thread_checker_.CalledOnValidThread());
rockot10188752016-09-08 18:24:56638 if (!connector_ || paused_) {
Ken Rockot37ddd8152018-02-22 18:18:46639 if (!shut_down_) {
Ken Rockot2b6de982018-03-20 22:28:13640 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16641 outgoing_messages_.emplace_back(std::move(*message));
Ken Rockot37ddd8152018-02-22 18:18:46642
Lukasz Anforowiczb29fffc22018-05-29 17:37:33643 // TODO(https://crbug.com/813045): Change this to a DCHECK. Typically
644 // this queue won't exceed something like 50 messages even on slow
645 // devices - higher numbers probably indicate that IPC messages are
646 // leaked.
647 CHECK_LE(outgoing_messages_.size(),
648 MojoBootstrap::kMaxOutgoingMessagesSizeForTesting);
Ken Rockot37ddd8152018-02-22 18:18:46649 }
rockot0e4de5f2016-07-22 21:18:07650 return true;
651 }
652 return connector_->Accept(message);
rockot02b8e182016-07-13 20:08:30653 } else {
Ken Rockotfb81dc02018-05-15 21:59:26654 // Do a message size check here so we don't lose valuable stack
655 // information to the task scheduler.
656 CHECK_LE(message->data_num_bytes(), Channel::kMaximumMessageSize);
657
rockotbecd3f742016-11-08 20:47:00658 // We always post tasks to the master endpoint thread when called from
659 // other threads in order to simulate IPC::ChannelProxy::Send behavior.
rockot02b8e182016-07-13 20:08:30660 task_runner_->PostTask(
661 FROM_HERE,
662 base::Bind(
663 &ChannelAssociatedGroupController::SendMessageOnMasterThread,
rockotc4cc691e2016-08-19 18:48:57664 this, base::Passed(message)));
rockot02b8e182016-07-13 20:08:30665 return true;
666 }
667 }
668
rockotc4cc691e2016-08-19 18:48:57669 void SendMessageOnMasterThread(mojo::Message message) {
rockot02b8e182016-07-13 20:08:30670 DCHECK(thread_checker_.CalledOnValidThread());
rockotc4cc691e2016-08-19 18:48:57671 if (!SendMessage(&message))
rockot02b8e182016-07-13 20:08:30672 RaiseError();
673 }
674
675 void OnPipeError() {
676 DCHECK(thread_checker_.CalledOnValidThread());
677
678 // We keep |this| alive here because it's possible for the notifications
679 // below to release all other references.
680 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
681
682 base::AutoLock locker(lock_);
683 encountered_error_ = true;
684
685 std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
686 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
687 Endpoint* endpoint = iter->second.get();
688 ++iter;
689
690 if (endpoint->client())
691 endpoints_to_notify.push_back(endpoint);
692
693 MarkPeerClosedAndMaybeRemove(endpoint);
694 }
695
696 for (auto& endpoint : endpoints_to_notify) {
rockot0e4de5f2016-07-22 21:18:07697 // Because a notification may in turn detach any endpoint, we have to
rockot02b8e182016-07-13 20:08:30698 // check each client again here.
699 if (endpoint->client())
700 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
701 }
702 }
703
704 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
705 lock_.AssertAcquired();
706 DCHECK(endpoint->task_runner() && endpoint->client());
peary28cd3bd22017-06-29 02:15:28707 if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) {
rockot02b8e182016-07-13 20:08:30708 mojo::InterfaceEndpointClient* client = endpoint->client();
yzshen8be41d3a2017-01-23 20:40:37709 base::Optional<mojo::DisconnectReason> reason(
710 endpoint->disconnect_reason());
rockot02b8e182016-07-13 20:08:30711
712 base::AutoUnlock unlocker(lock_);
yzshen8be41d3a2017-01-23 20:40:37713 client->NotifyError(reason);
rockot02b8e182016-07-13 20:08:30714 } else {
715 endpoint->task_runner()->PostTask(
716 FROM_HERE,
tzik1d692a2e2017-07-03 11:01:26717 base::Bind(&ChannelAssociatedGroupController::
718 NotifyEndpointOfErrorOnEndpointThread,
719 this, endpoint->id(), base::Unretained(endpoint)));
rockot02b8e182016-07-13 20:08:30720 }
721 }
722
rockot9abe09b2016-08-02 20:57:34723 void NotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,
724 Endpoint* endpoint) {
rockot02b8e182016-07-13 20:08:30725 base::AutoLock locker(lock_);
rockot9abe09b2016-08-02 20:57:34726 auto iter = endpoints_.find(id);
727 if (iter == endpoints_.end() || iter->second.get() != endpoint)
728 return;
rockot02b8e182016-07-13 20:08:30729 if (!endpoint->client())
730 return;
rockot9abe09b2016-08-02 20:57:34731
peary28cd3bd22017-06-29 02:15:28732 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34733 NotifyEndpointOfError(endpoint, false /* force_async */);
rockot02b8e182016-07-13 20:08:30734 }
735
736 void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
737 lock_.AssertAcquired();
738 endpoint->set_closed();
739 if (endpoint->closed() && endpoint->peer_closed())
740 endpoints_.erase(endpoint->id());
741 }
742
743 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
744 lock_.AssertAcquired();
745 endpoint->set_peer_closed();
rockot9abe09b2016-08-02 20:57:34746 endpoint->SignalSyncMessageEvent();
rockot02b8e182016-07-13 20:08:30747 if (endpoint->closed() && endpoint->peer_closed())
748 endpoints_.erase(endpoint->id());
749 }
750
751 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
752 lock_.AssertAcquired();
753 DCHECK(!inserted || !*inserted);
754
yzshen0a5971312017-02-02 05:13:47755 Endpoint* endpoint = FindEndpoint(id);
756 if (!endpoint) {
757 endpoint = new Endpoint(this, id);
758 endpoints_.insert({id, endpoint});
759 if (inserted)
760 *inserted = true;
761 }
rockot02b8e182016-07-13 20:08:30762 return endpoint;
763 }
764
yzshen0a5971312017-02-02 05:13:47765 Endpoint* FindEndpoint(mojo::InterfaceId id) {
766 lock_.AssertAcquired();
767 auto iter = endpoints_.find(id);
768 return iter != endpoints_.end() ? iter->second.get() : nullptr;
769 }
770
rockot02b8e182016-07-13 20:08:30771 // mojo::MessageReceiver:
772 bool Accept(mojo::Message* message) override {
773 DCHECK(thread_checker_.CalledOnValidThread());
774
yzshen0a5971312017-02-02 05:13:47775 if (!message->DeserializeAssociatedEndpointHandles(this))
776 return false;
777
778 if (mojo::PipeControlMessageHandler::IsPipeControlMessage(message))
779 return control_message_handler_.Accept(message);
rockot02b8e182016-07-13 20:08:30780
781 mojo::InterfaceId id = message->interface_id();
782 DCHECK(mojo::IsValidInterfaceId(id));
783
784 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47785 Endpoint* endpoint = FindEndpoint(id);
786 if (!endpoint)
787 return true;
788
789 mojo::InterfaceEndpointClient* client = endpoint->client();
peary28cd3bd22017-06-29 02:15:28790 if (!client || !endpoint->task_runner()->RunsTasksInCurrentSequence()) {
rockot02b8e182016-07-13 20:08:30791 // No client has been bound yet or the client runs tasks on another
792 // thread. We assume the other thread must always be the one on which
793 // |proxy_task_runner_| runs tasks, since that's the only valid scenario.
794 //
795 // If the client is not yet bound, it must be bound by the time this task
796 // runs or else it's programmer error.
797 DCHECK(proxy_task_runner_);
rockot9abe09b2016-08-02 20:57:34798
rockotc4cc691e2016-08-19 18:48:57799 if (message->has_flag(mojo::Message::kFlagIsSync)) {
yzshen0a5971312017-02-02 05:13:47800 MessageWrapper message_wrapper(this, std::move(*message));
rockot9abe09b2016-08-02 20:57:34801 // Sync messages may need to be handled by the endpoint if it's blocking
802 // on a sync reply. We pass ownership of the message to the endpoint's
803 // sync message queue. If the endpoint was blocking, it will dequeue the
804 // message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
805 // call will dequeue the message and dispatch it.
yzshenea784ea2017-01-31 21:20:20806 uint32_t message_id =
807 endpoint->EnqueueSyncMessage(std::move(message_wrapper));
rockot9abe09b2016-08-02 20:57:34808 proxy_task_runner_->PostTask(
809 FROM_HERE,
810 base::Bind(&ChannelAssociatedGroupController::AcceptSyncMessage,
811 this, id, message_id));
812 return true;
813 }
814
rockot02b8e182016-07-13 20:08:30815 proxy_task_runner_->PostTask(
816 FROM_HERE,
817 base::Bind(&ChannelAssociatedGroupController::AcceptOnProxyThread,
rockotc4cc691e2016-08-19 18:48:57818 this, base::Passed(message)));
rockot02b8e182016-07-13 20:08:30819 return true;
820 }
821
822 // We do not expect to receive sync responses on the master endpoint thread.
823 // If it's happening, it's a bug.
rockot9abe09b2016-08-02 20:57:34824 DCHECK(!message->has_flag(mojo::Message::kFlagIsSync) ||
825 !message->has_flag(mojo::Message::kFlagIsResponse));
rockot02b8e182016-07-13 20:08:30826
rockot8d890f62016-07-14 16:37:14827 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47828 return client->HandleIncomingMessage(message);
rockot02b8e182016-07-13 20:08:30829 }
830
rockotc4cc691e2016-08-19 18:48:57831 void AcceptOnProxyThread(mojo::Message message) {
rockot02b8e182016-07-13 20:08:30832 DCHECK(proxy_task_runner_->BelongsToCurrentThread());
833
rockotc4cc691e2016-08-19 18:48:57834 mojo::InterfaceId id = message.interface_id();
rockot8d890f62016-07-14 16:37:14835 DCHECK(mojo::IsValidInterfaceId(id) && !mojo::IsMasterInterfaceId(id));
836
837 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47838 Endpoint* endpoint = FindEndpoint(id);
rockot8d890f62016-07-14 16:37:14839 if (!endpoint)
840 return;
841
842 mojo::InterfaceEndpointClient* client = endpoint->client();
843 if (!client)
844 return;
845
peary28cd3bd22017-06-29 02:15:28846 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot8d890f62016-07-14 16:37:14847
rockot9abe09b2016-08-02 20:57:34848 // Sync messages should never make their way to this method.
yzshen0a5971312017-02-02 05:13:47849 DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
rockot8d890f62016-07-14 16:37:14850
851 bool result = false;
852 {
853 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47854 result = client->HandleIncomingMessage(&message);
rockot8d890f62016-07-14 16:37:14855 }
856
857 if (!result)
858 RaiseError();
859 }
860
rockot9abe09b2016-08-02 20:57:34861 void AcceptSyncMessage(mojo::InterfaceId interface_id, uint32_t message_id) {
862 DCHECK(proxy_task_runner_->BelongsToCurrentThread());
863
864 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47865 Endpoint* endpoint = FindEndpoint(interface_id);
rockot9abe09b2016-08-02 20:57:34866 if (!endpoint)
867 return;
868
csharrison1af8d6ab2017-04-21 17:47:23869 // Careful, if the endpoint is detached its members are cleared. Check for
870 // that before dereferencing.
871 mojo::InterfaceEndpointClient* client = endpoint->client();
872 if (!client)
873 return;
874
peary28cd3bd22017-06-29 02:15:28875 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
yzshen0a5971312017-02-02 05:13:47876 MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
rockot9abe09b2016-08-02 20:57:34877
878 // The message must have already been dequeued by the endpoint waking up
879 // from a sync wait. Nothing to do.
yzshenea784ea2017-01-31 21:20:20880 if (message_wrapper.value().IsNull())
rockot9abe09b2016-08-02 20:57:34881 return;
882
rockot9abe09b2016-08-02 20:57:34883 bool result = false;
884 {
885 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47886 result = client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34887 }
888
889 if (!result)
890 RaiseError();
891 }
892
rockot02b8e182016-07-13 20:08:30893 // mojo::PipeControlMessageHandlerDelegate:
yzshen8be41d3a2017-01-23 20:40:37894 bool OnPeerAssociatedEndpointClosed(
895 mojo::InterfaceId id,
896 const base::Optional<mojo::DisconnectReason>& reason) override {
rockot02b8e182016-07-13 20:08:30897 DCHECK(thread_checker_.CalledOnValidThread());
898
rockot0e4de5f2016-07-22 21:18:07899 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
rockot02b8e182016-07-13 20:08:30900 base::AutoLock locker(lock_);
901 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
yzshen8be41d3a2017-01-23 20:40:37902 if (reason)
903 endpoint->set_disconnect_reason(reason);
rockot02b8e182016-07-13 20:08:30904 if (!endpoint->peer_closed()) {
905 if (endpoint->client())
906 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
907 MarkPeerClosedAndMaybeRemove(endpoint.get());
908 }
909
910 return true;
911 }
912
rockot02b8e182016-07-13 20:08:30913 // Checked in places which must be run on the master endpoint's thread.
914 base::ThreadChecker thread_checker_;
915
916 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
rockot0e4de5f2016-07-22 21:18:07917
rockot02b8e182016-07-13 20:08:30918 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
rockot0e4de5f2016-07-22 21:18:07919 const bool set_interface_id_namespace_bit_;
rockot10188752016-09-08 18:24:56920 bool paused_ = false;
rockot0e4de5f2016-07-22 21:18:07921 std::unique_ptr<mojo::Connector> connector_;
rockot222e7dd2016-08-24 23:37:11922 mojo::FilterChain filters_;
rockot02b8e182016-07-13 20:08:30923 mojo::PipeControlMessageHandler control_message_handler_;
rockot0e4de5f2016-07-22 21:18:07924 ControlMessageProxyThunk control_message_proxy_thunk_;
rockot58909542016-11-10 20:05:45925
926 // NOTE: It is unsafe to call into this object while holding |lock_|.
rockot0e4de5f2016-07-22 21:18:07927 mojo::PipeControlMessageProxy control_message_proxy_;
928
Ken Rockot2b6de982018-03-20 22:28:13929 // Guards access to |outgoing_messages_| only. Used to support memory dumps
930 // which may be triggered from any thread.
931 base::Lock outgoing_messages_lock_;
932
rockot0e4de5f2016-07-22 21:18:07933 // Outgoing messages that were sent before this controller was bound to a
934 // real message pipe.
rockotc4cc691e2016-08-19 18:48:57935 std::vector<mojo::Message> outgoing_messages_;
rockot02b8e182016-07-13 20:08:30936
937 // Guards the fields below for thread-safe access.
938 base::Lock lock_;
939
940 bool encountered_error_ = false;
Ken Rockot3e7284bb2018-02-06 16:11:16941 bool shut_down_ = false;
rockot0e4de5f2016-07-22 21:18:07942
943 // ID #1 is reserved for the mojom::Channel interface.
944 uint32_t next_interface_id_ = 2;
945
Yuzhu Shen7bcd8ebf2017-10-02 23:21:14946 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
rockot02b8e182016-07-13 20:08:30947
948 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
949};
950
Ken Rockot2b6de982018-03-20 22:28:13951bool ControllerMemoryDumpProvider::OnMemoryDump(
952 const base::trace_event::MemoryDumpArgs& args,
953 base::trace_event::ProcessMemoryDump* pmd) {
954 base::AutoLock lock(lock_);
955 for (auto* controller : controllers_) {
956 base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
957 base::StringPrintf("mojo/queued_ipc_channel_message/0x%" PRIxPTR,
958 reinterpret_cast<uintptr_t>(controller)));
959 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
960 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
961 controller->GetQueuedMessageCount());
962 }
963
964 return true;
965}
966
rockot0e4de5f2016-07-22 21:18:07967class MojoBootstrapImpl : public MojoBootstrap {
rockot02b8e182016-07-13 20:08:30968 public:
rockot0e4de5f2016-07-22 21:18:07969 MojoBootstrapImpl(
970 mojo::ScopedMessagePipeHandle handle,
rockot0e4de5f2016-07-22 21:18:07971 const scoped_refptr<ChannelAssociatedGroupController> controller)
yzshen2859a2ac2017-02-14 22:24:25972 : controller_(controller),
973 associated_group_(controller),
974 handle_(std::move(handle)) {}
rockot02b8e182016-07-13 20:08:30975
rockot0e4de5f2016-07-22 21:18:07976 ~MojoBootstrapImpl() override {
977 controller_->ShutDown();
rockot02b8e182016-07-13 20:08:30978 }
979
980 private:
rockota628d0b2017-02-09 08:40:15981 void Connect(mojom::ChannelAssociatedPtr* sender,
982 mojom::ChannelAssociatedRequest* receiver) override {
rockot0e4de5f2016-07-22 21:18:07983 controller_->Bind(std::move(handle_));
rockota628d0b2017-02-09 08:40:15984 controller_->CreateChannelEndpoints(sender, receiver);
msramek5507fee2016-07-22 10:06:21985 }
986
rockot10188752016-09-08 18:24:56987 void Pause() override {
988 controller_->Pause();
989 }
990
991 void Unpause() override {
992 controller_->Unpause();
rockot401fb2c2016-09-06 18:35:57993 }
994
995 void Flush() override {
996 controller_->FlushOutgoingMessages();
997 }
998
msramek5507fee2016-07-22 10:06:21999 mojo::AssociatedGroup* GetAssociatedGroup() override {
yzshen2859a2ac2017-02-14 22:24:251000 return &associated_group_;
msramek5507fee2016-07-22 10:06:211001 }
1002
rockot0e4de5f2016-07-22 21:18:071003 scoped_refptr<ChannelAssociatedGroupController> controller_;
yzshen2859a2ac2017-02-14 22:24:251004 mojo::AssociatedGroup associated_group_;
msramek5507fee2016-07-22 10:06:211005
rockot0e4de5f2016-07-22 21:18:071006 mojo::ScopedMessagePipeHandle handle_;
msramek5507fee2016-07-22 10:06:211007
rockot0e4de5f2016-07-22 21:18:071008 DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl);
msramek5507fee2016-07-22 10:06:211009};
1010
morrita54f6f80c2014-09-23 21:16:001011} // namespace
1012
morrita54f6f80c2014-09-23 21:16:001013// static
danakj03de39b22016-04-23 04:21:091014std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
sammc57ed9f982016-03-10 06:28:351015 mojo::ScopedMessagePipeHandle handle,
1016 Channel::Mode mode,
Hajime Hoshia98f1102017-11-20 06:34:351017 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
1018 const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner) {
Jeremy Roman160eb922017-08-29 17:43:431019 return std::make_unique<MojoBootstrapImpl>(
Hajime Hoshia98f1102017-11-20 06:34:351020 std::move(handle),
1021 new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER,
1022 ipc_task_runner, proxy_task_runner));
sammc57ed9f982016-03-10 06:28:351023}
1024
morrita54f6f80c2014-09-23 21:16:001025} // namespace IPC