Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: ipc/ipc_mojo_bootstrap.cc

Issue 2163633003: Support early associated interface binding on ChannelMojo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@explicit-channel-ipc-task-runner
Patch Set: . Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ipc/ipc_mojo_bootstrap.h" 5 #include "ipc/ipc_mojo_bootstrap.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <map> 9 #include <map>
10 #include <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 #include <vector>
12 13
13 #include "base/callback.h" 14 #include "base/callback.h"
14 #include "base/logging.h" 15 #include "base/logging.h"
15 #include "base/macros.h" 16 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
17 #include "base/process/process_handle.h"
18 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
19 #include "base/stl_util.h" 19 #include "base/stl_util.h"
20 #include "base/synchronization/lock.h" 20 #include "base/synchronization/lock.h"
21 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
22 #include "build/build_config.h" 22 #include "build/build_config.h"
23 #include "ipc/ipc_message_utils.h" 23 #include "ipc/ipc_message_utils.h"
24 #include "ipc/ipc_platform_file.h" 24 #include "ipc/ipc_platform_file.h"
25 #include "mojo/public/cpp/bindings/associated_group.h" 25 #include "mojo/public/cpp/bindings/associated_group.h"
26 #include "mojo/public/cpp/bindings/associated_group_controller.h" 26 #include "mojo/public/cpp/bindings/associated_group_controller.h"
27 #include "mojo/public/cpp/bindings/binding.h" 27 #include "mojo/public/cpp/bindings/binding.h"
28 #include "mojo/public/cpp/bindings/connector.h" 28 #include "mojo/public/cpp/bindings/connector.h"
29 #include "mojo/public/cpp/bindings/interface_endpoint_client.h" 29 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
30 #include "mojo/public/cpp/bindings/interface_endpoint_controller.h" 30 #include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
31 #include "mojo/public/cpp/bindings/interface_id.h" 31 #include "mojo/public/cpp/bindings/interface_id.h"
32 #include "mojo/public/cpp/bindings/message.h"
32 #include "mojo/public/cpp/bindings/message_header_validator.h" 33 #include "mojo/public/cpp/bindings/message_header_validator.h"
33 #include "mojo/public/cpp/bindings/pipe_control_message_handler.h" 34 #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
34 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" 35 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
35 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" 36 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
36 37
37 namespace IPC { 38 namespace IPC {
38 39
39 namespace { 40 namespace {
40 41
41 class ChannelAssociatedGroupController 42 class ChannelAssociatedGroupController
42 : public mojo::AssociatedGroupController, 43 : public mojo::AssociatedGroupController,
43 public mojo::MessageReceiver, 44 public mojo::MessageReceiver,
44 public mojo::PipeControlMessageHandlerDelegate { 45 public mojo::PipeControlMessageHandlerDelegate {
45 public: 46 public:
46 ChannelAssociatedGroupController(bool set_interface_id_namespace_bit, 47 ChannelAssociatedGroupController(
47 mojo::ScopedMessagePipeHandle handle) 48 bool set_interface_id_namespace_bit,
49 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
48 : mojo::AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()), 50 : mojo::AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()),
49 task_runner_(base::ThreadTaskRunnerHandle::Get()), 51 task_runner_(ipc_task_runner),
50 id_namespace_mask_(set_interface_id_namespace_bit ? 52 proxy_task_runner_(base::ThreadTaskRunnerHandle::Get()),
51 mojo::kInterfaceIdNamespaceMask : 0), 53 set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
52 associated_group_(CreateAssociatedGroup()),
53 connector_(std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
54 base::ThreadTaskRunnerHandle::Get()),
55 header_validator_( 54 header_validator_(
56 "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this), 55 "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this),
57 control_message_handler_(this), 56 control_message_handler_(this),
58 control_message_proxy_(&connector_) { 57 control_message_proxy_thunk_(this),
59 connector_.set_incoming_receiver(&header_validator_); 58 control_message_proxy_(&control_message_proxy_thunk_) {
60 connector_.set_connection_error_handler( 59 thread_checker_.DetachFromThread();
61 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
62 base::Unretained(this)));
63 control_message_handler_.SetDescription( 60 control_message_handler_.SetDescription(
64 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler"); 61 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
65 } 62 }
66 63
67 mojo::AssociatedGroup* associated_group() { return associated_group_.get(); } 64 void Bind(mojo::ScopedMessagePipeHandle handle) {
65 DCHECK(thread_checker_.CalledOnValidThread());
66 DCHECK(task_runner_->BelongsToCurrentThread());
67 connector_.reset(new mojo::Connector(
68 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
69 task_runner_));
70 connector_->set_incoming_receiver(&header_validator_);
71 connector_->set_connection_error_handler(
72 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
73 base::Unretained(this)));
74
75 std::vector<std::unique_ptr<mojo::Message>> outgoing_messages;
76 std::swap(outgoing_messages, outgoing_messages_);
77 for (auto& message : outgoing_messages)
78 SendMessage(message.get());
79 }
80
81 void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
82 mojom::ChannelAssociatedRequest* receiver) {
83 mojo::InterfaceId sender_id, receiver_id;
84 if (set_interface_id_namespace_bit_) {
85 sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
86 receiver_id = 1;
87 } else {
88 sender_id = 1;
89 receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
90 }
91
92 {
93 base::AutoLock locker(lock_);
94 Endpoint* sender_endpoint = new Endpoint(this, sender_id);
95 Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
96 endpoints_.insert({ sender_id, sender_endpoint });
97 endpoints_.insert({ receiver_id, receiver_endpoint });
98 }
99
100 mojo::ScopedInterfaceEndpointHandle sender_handle =
101 CreateScopedInterfaceEndpointHandle(sender_id, true);
102 mojo::ScopedInterfaceEndpointHandle receiver_handle =
103 CreateScopedInterfaceEndpointHandle(receiver_id, true);
104
105 sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
106 receiver->Bind(std::move(receiver_handle));
107 }
68 108
69 void ShutDown() { 109 void ShutDown() {
70 DCHECK(thread_checker_.CalledOnValidThread()); 110 DCHECK(thread_checker_.CalledOnValidThread());
71 connector_.CloseMessagePipe(); 111 connector_->CloseMessagePipe();
72 OnPipeError(); 112 OnPipeError();
73 associated_group_.reset(); 113 connector_.reset();
74 }
75
76 void SetProxyTaskRunner(
77 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner) {
78 proxy_task_runner_ = proxy_task_runner;
79 } 114 }
80 115
81 // mojo::AssociatedGroupController: 116 // mojo::AssociatedGroupController:
82 void CreateEndpointHandlePair( 117 void CreateEndpointHandlePair(
83 mojo::ScopedInterfaceEndpointHandle* local_endpoint, 118 mojo::ScopedInterfaceEndpointHandle* local_endpoint,
84 mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override { 119 mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override {
85 base::AutoLock locker(lock_); 120 base::AutoLock locker(lock_);
86 uint32_t id = 0; 121 uint32_t id = 0;
87 do { 122 do {
88 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask) 123 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
89 next_interface_id_ = 1; 124 next_interface_id_ = 2;
90 id = (next_interface_id_++) | id_namespace_mask_; 125 id = next_interface_id_++;
126 if (set_interface_id_namespace_bit_)
127 id |= mojo::kInterfaceIdNamespaceMask;
91 } while (ContainsKey(endpoints_, id)); 128 } while (ContainsKey(endpoints_, id));
92 129
93 Endpoint* endpoint = new Endpoint(this, id); 130 Endpoint* endpoint = new Endpoint(this, id);
94 if (encountered_error_) 131 if (encountered_error_)
95 endpoint->set_peer_closed(); 132 endpoint->set_peer_closed();
96 endpoints_.insert({ id, endpoint }); 133 endpoints_.insert({ id, endpoint });
97 134
98 *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true); 135 *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true);
99 *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false); 136 *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false);
100 } 137 }
(...skipping 13 matching lines...) Expand all
114 } 151 }
115 152
116 void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override { 153 void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override {
117 if (!mojo::IsValidInterfaceId(id)) 154 if (!mojo::IsValidInterfaceId(id))
118 return; 155 return;
119 156
120 base::AutoLock locker(lock_); 157 base::AutoLock locker(lock_);
121 if (!is_local) { 158 if (!is_local) {
122 DCHECK(ContainsKey(endpoints_, id)); 159 DCHECK(ContainsKey(endpoints_, id));
123 DCHECK(!mojo::IsMasterInterfaceId(id)); 160 DCHECK(!mojo::IsMasterInterfaceId(id));
124 NotifyEndpointClosedBeforeSent(id); 161 control_message_proxy_.NotifyEndpointClosedBeforeSent(id);
125 return; 162 return;
126 } 163 }
127 164
128 DCHECK(ContainsKey(endpoints_, id)); 165 DCHECK(ContainsKey(endpoints_, id));
129 Endpoint* endpoint = endpoints_[id].get(); 166 Endpoint* endpoint = endpoints_[id].get();
130 DCHECK(!endpoint->client()); 167 DCHECK(!endpoint->client());
131 DCHECK(!endpoint->closed()); 168 DCHECK(!endpoint->closed());
132 MarkClosedAndMaybeRemove(endpoint); 169 MarkClosedAndMaybeRemove(endpoint);
133 170
134 if (!mojo::IsMasterInterfaceId(id)) 171 if (!mojo::IsMasterInterfaceId(id))
135 NotifyPeerEndpointClosed(id); 172 control_message_proxy_.NotifyPeerEndpointClosed(id);
136 } 173 }
137 174
138 mojo::InterfaceEndpointController* AttachEndpointClient( 175 mojo::InterfaceEndpointController* AttachEndpointClient(
139 const mojo::ScopedInterfaceEndpointHandle& handle, 176 const mojo::ScopedInterfaceEndpointHandle& handle,
140 mojo::InterfaceEndpointClient* client, 177 mojo::InterfaceEndpointClient* client,
141 scoped_refptr<base::SingleThreadTaskRunner> runner) override { 178 scoped_refptr<base::SingleThreadTaskRunner> runner) override {
142 const mojo::InterfaceId id = handle.id(); 179 const mojo::InterfaceId id = handle.id();
143 180
144 DCHECK(mojo::IsValidInterfaceId(id)); 181 DCHECK(mojo::IsValidInterfaceId(id));
145 DCHECK(client); 182 DCHECK(client);
146 183
184 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
yzshen1 2016/07/20 22:54:51 I think this is not necessary because the Interfac
Ken Rockot(use gerrit already) 2016/07/20 23:10:20 NotifyEndpointOfError may synchronously call into
185
147 base::AutoLock locker(lock_); 186 base::AutoLock locker(lock_);
148 DCHECK(ContainsKey(endpoints_, id)); 187 DCHECK(ContainsKey(endpoints_, id));
149 188
150 Endpoint* endpoint = endpoints_[id].get(); 189 Endpoint* endpoint = endpoints_[id].get();
151 endpoint->AttachClient(client, std::move(runner)); 190 endpoint->AttachClient(client, std::move(runner));
152 191
153 if (endpoint->peer_closed()) 192 if (endpoint->peer_closed())
154 NotifyEndpointOfError(endpoint, true /* force_async */); 193 NotifyEndpointOfError(endpoint, true /* force_async */);
155 194
156 return endpoint; 195 return endpoint;
157 } 196 }
158 197
159 void DetachEndpointClient( 198 void DetachEndpointClient(
160 const mojo::ScopedInterfaceEndpointHandle& handle) override { 199 const mojo::ScopedInterfaceEndpointHandle& handle) override {
161 const mojo::InterfaceId id = handle.id(); 200 const mojo::InterfaceId id = handle.id();
162 201
163 DCHECK(mojo::IsValidInterfaceId(id)); 202 DCHECK(mojo::IsValidInterfaceId(id));
164 203
165 base::AutoLock locker(lock_); 204 base::AutoLock locker(lock_);
166 DCHECK(ContainsKey(endpoints_, id)); 205 DCHECK(ContainsKey(endpoints_, id));
167 206
168 Endpoint* endpoint = endpoints_[id].get(); 207 Endpoint* endpoint = endpoints_[id].get();
169 endpoint->DetachClient(); 208 endpoint->DetachClient();
170 } 209 }
171 210
172 void RaiseError() override { 211 void RaiseError() override {
173 if (task_runner_->BelongsToCurrentThread()) { 212 if (task_runner_->BelongsToCurrentThread()) {
174 connector_.RaiseError(); 213 connector_->RaiseError();
175 } else { 214 } else {
176 task_runner_->PostTask( 215 task_runner_->PostTask(
177 FROM_HERE, 216 FROM_HERE,
178 base::Bind(&ChannelAssociatedGroupController::RaiseError, this)); 217 base::Bind(&ChannelAssociatedGroupController::RaiseError, this));
179 } 218 }
180 } 219 }
181 220
182 private: 221 private:
183 class Endpoint; 222 class Endpoint;
223 class ControlMessageProxyThunk;
184 friend class Endpoint; 224 friend class Endpoint;
225 friend class ControlMessageProxyThunk;
185 226
186 class Endpoint : public base::RefCountedThreadSafe<Endpoint>, 227 class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
187 public mojo::InterfaceEndpointController { 228 public mojo::InterfaceEndpointController {
188 public: 229 public:
189 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id) 230 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
190 : controller_(controller), id_(id) {} 231 : controller_(controller), id_(id) {}
191 232
192 mojo::InterfaceId id() const { return id_; } 233 mojo::InterfaceId id() const { return id_; }
193 234
194 bool closed() const { 235 bool closed() const {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 const mojo::InterfaceId id_; 318 const mojo::InterfaceId id_;
278 319
279 bool closed_ = false; 320 bool closed_ = false;
280 bool peer_closed_ = false; 321 bool peer_closed_ = false;
281 mojo::InterfaceEndpointClient* client_ = nullptr; 322 mojo::InterfaceEndpointClient* client_ = nullptr;
282 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 323 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
283 324
284 DISALLOW_COPY_AND_ASSIGN(Endpoint); 325 DISALLOW_COPY_AND_ASSIGN(Endpoint);
285 }; 326 };
286 327
328 class ControlMessageProxyThunk : public MessageReceiver {
329 public:
330 explicit ControlMessageProxyThunk(
331 ChannelAssociatedGroupController* controller)
332 : controller_(controller) {}
333
334 private:
335 // MessageReceiver:
336 bool Accept(mojo::Message* message) override {
337 return controller_->SendMessage(message);
338 }
339
340 ChannelAssociatedGroupController* controller_;
341
342 DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
343 };
344
287 ~ChannelAssociatedGroupController() override { 345 ~ChannelAssociatedGroupController() override {
288 base::AutoLock locker(lock_); 346 base::AutoLock locker(lock_);
289
290 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { 347 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
291 Endpoint* endpoint = iter->second.get(); 348 Endpoint* endpoint = iter->second.get();
292 ++iter; 349 ++iter;
293 350
294 DCHECK(endpoint->closed()); 351 DCHECK(endpoint->closed());
295 MarkPeerClosedAndMaybeRemove(endpoint); 352 MarkPeerClosedAndMaybeRemove(endpoint);
296 } 353 }
297 354
298 DCHECK(endpoints_.empty()); 355 DCHECK(endpoints_.empty());
299 } 356 }
300 357
301 bool SendMessage(mojo::Message* message) { 358 bool SendMessage(mojo::Message* message) {
302 if (task_runner_->BelongsToCurrentThread()) { 359 if (task_runner_->BelongsToCurrentThread()) {
303 DCHECK(thread_checker_.CalledOnValidThread()); 360 DCHECK(thread_checker_.CalledOnValidThread());
304 return connector_.Accept(message); 361 if (!connector_) {
362 // Pipe may not be bound yet, so we queue the message.
363 std::unique_ptr<mojo::Message> queued_message(new mojo::Message);
364 message->MoveTo(queued_message.get());
365 outgoing_messages_.emplace_back(std::move(queued_message));
366 return true;
367 }
368 return connector_->Accept(message);
305 } else { 369 } else {
306 // We always post tasks to the master endpoint thread when called from the 370 // We always post tasks to the master endpoint thread when called from the
307 // proxy thread in order to simulate IPC::ChannelProxy::Send behavior. 371 // proxy thread in order to simulate IPC::ChannelProxy::Send behavior.
308 DCHECK(proxy_task_runner_ && 372 DCHECK(proxy_task_runner_ &&
309 proxy_task_runner_->BelongsToCurrentThread()); 373 proxy_task_runner_->BelongsToCurrentThread());
310 std::unique_ptr<mojo::Message> passed_message(new mojo::Message); 374 std::unique_ptr<mojo::Message> passed_message(new mojo::Message);
311 message->MoveTo(passed_message.get()); 375 message->MoveTo(passed_message.get());
312 task_runner_->PostTask( 376 task_runner_->PostTask(
313 FROM_HERE, 377 FROM_HERE,
314 base::Bind( 378 base::Bind(
(...skipping 24 matching lines...) Expand all
339 Endpoint* endpoint = iter->second.get(); 403 Endpoint* endpoint = iter->second.get();
340 ++iter; 404 ++iter;
341 405
342 if (endpoint->client()) 406 if (endpoint->client())
343 endpoints_to_notify.push_back(endpoint); 407 endpoints_to_notify.push_back(endpoint);
344 408
345 MarkPeerClosedAndMaybeRemove(endpoint); 409 MarkPeerClosedAndMaybeRemove(endpoint);
346 } 410 }
347 411
348 for (auto& endpoint : endpoints_to_notify) { 412 for (auto& endpoint : endpoints_to_notify) {
349 // Because an notification may in turn detach any endpoint, we have to 413 // Because a notification may in turn detach any endpoint, we have to
350 // check each client again here. 414 // check each client again here.
351 if (endpoint->client()) 415 if (endpoint->client())
352 NotifyEndpointOfError(endpoint.get(), false /* force_async */); 416 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
353 } 417 }
354 } 418 }
355 419
356 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) { 420 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
357 lock_.AssertAcquired(); 421 lock_.AssertAcquired();
358 DCHECK(endpoint->task_runner() && endpoint->client()); 422 DCHECK(endpoint->task_runner() && endpoint->client());
359 if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) { 423 if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) {
360 mojo::InterfaceEndpointClient* client = endpoint->client(); 424 mojo::InterfaceEndpointClient* client = endpoint->client();
361 425
362 base::AutoUnlock unlocker(lock_); 426 base::AutoUnlock unlocker(lock_);
363 client->NotifyError(); 427 client->NotifyError();
364 } else { 428 } else {
365 endpoint->task_runner()->PostTask( 429 endpoint->task_runner()->PostTask(
366 FROM_HERE, 430 FROM_HERE,
367 base::Bind(&ChannelAssociatedGroupController 431 base::Bind(&ChannelAssociatedGroupController
368 ::NotifyEndpointOfErrorOnEndpointThread, this, 432 ::NotifyEndpointOfErrorOnEndpointThread, this,
369 make_scoped_refptr(endpoint))); 433 make_scoped_refptr(endpoint)));
370 } 434 }
371 } 435 }
372 436
373 void NotifyEndpointOfErrorOnEndpointThread(scoped_refptr<Endpoint> endpoint) { 437 void NotifyEndpointOfErrorOnEndpointThread(scoped_refptr<Endpoint> endpoint) {
438 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
yzshen1 2016/07/20 22:54:51 Why do we need to keep it alive explicitly? I thou
Ken Rockot(use gerrit already) 2016/07/20 23:10:20 Ah, you are right :) Fixed.
374 base::AutoLock locker(lock_); 439 base::AutoLock locker(lock_);
375 if (!endpoint->client()) 440 if (!endpoint->client())
376 return; 441 return;
377 DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); 442 DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
378 NotifyEndpointOfError(endpoint.get(), false /* force_async */); 443 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
379 } 444 }
380 445
381 void MarkClosedAndMaybeRemove(Endpoint* endpoint) { 446 void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
382 lock_.AssertAcquired(); 447 lock_.AssertAcquired();
383 endpoint->set_closed(); 448 endpoint->set_closed();
384 if (endpoint->closed() && endpoint->peer_closed()) 449 if (endpoint->closed() && endpoint->peer_closed())
385 endpoints_.erase(endpoint->id()); 450 endpoints_.erase(endpoint->id());
386 } 451 }
387 452
388 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) { 453 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
389 lock_.AssertAcquired(); 454 lock_.AssertAcquired();
390 endpoint->set_peer_closed(); 455 endpoint->set_peer_closed();
391 if (endpoint->closed() && endpoint->peer_closed()) 456 if (endpoint->closed() && endpoint->peer_closed())
392 endpoints_.erase(endpoint->id()); 457 endpoints_.erase(endpoint->id());
393 } 458 }
394 459
395 void NotifyPeerEndpointClosed(mojo::InterfaceId id) {
396 if (task_runner_->BelongsToCurrentThread()) {
397 if (connector_.is_valid())
398 control_message_proxy_.NotifyPeerEndpointClosed(id);
399 } else {
400 task_runner_->PostTask(
401 FROM_HERE,
402 base::Bind(&ChannelAssociatedGroupController
403 ::NotifyPeerEndpointClosed, this, id));
404 }
405 }
406
407 void NotifyEndpointClosedBeforeSent(mojo::InterfaceId id) {
408 if (task_runner_->BelongsToCurrentThread()) {
409 if (connector_.is_valid())
410 control_message_proxy_.NotifyEndpointClosedBeforeSent(id);
411 } else {
412 task_runner_->PostTask(
413 FROM_HERE,
414 base::Bind(&ChannelAssociatedGroupController
415 ::NotifyEndpointClosedBeforeSent, this, id));
416 }
417 }
418
419 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) { 460 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
420 lock_.AssertAcquired(); 461 lock_.AssertAcquired();
421 DCHECK(!inserted || !*inserted); 462 DCHECK(!inserted || !*inserted);
422 463
423 auto iter = endpoints_.find(id); 464 auto iter = endpoints_.find(id);
424 if (iter != endpoints_.end()) 465 if (iter != endpoints_.end())
425 return iter->second.get(); 466 return iter->second.get();
426 467
427 Endpoint* endpoint = new Endpoint(this, id); 468 Endpoint* endpoint = new Endpoint(this, id);
428 endpoints_.insert({ id, endpoint }); 469 endpoints_.insert({ id, endpoint });
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 RaiseError(); 544 RaiseError();
504 } 545 }
505 546
506 Endpoint* GetEndpointForDispatch(mojo::InterfaceId id) { 547 Endpoint* GetEndpointForDispatch(mojo::InterfaceId id) {
507 lock_.AssertAcquired(); 548 lock_.AssertAcquired();
508 bool inserted = false; 549 bool inserted = false;
509 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted); 550 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
510 if (inserted) { 551 if (inserted) {
511 MarkClosedAndMaybeRemove(endpoint); 552 MarkClosedAndMaybeRemove(endpoint);
512 if (!mojo::IsMasterInterfaceId(id)) 553 if (!mojo::IsMasterInterfaceId(id))
513 NotifyPeerEndpointClosed(id); 554 control_message_proxy_.NotifyPeerEndpointClosed(id);
514 return nullptr; 555 return nullptr;
515 } 556 }
516 557
517 if (endpoint->closed()) 558 if (endpoint->closed())
518 return nullptr; 559 return nullptr;
519 560
520 return endpoint; 561 return endpoint;
521 } 562 }
522 563
523 // mojo::PipeControlMessageHandlerDelegate: 564 // mojo::PipeControlMessageHandlerDelegate:
524 bool OnPeerAssociatedEndpointClosed(mojo::InterfaceId id) override { 565 bool OnPeerAssociatedEndpointClosed(mojo::InterfaceId id) override {
525 DCHECK(thread_checker_.CalledOnValidThread()); 566 DCHECK(thread_checker_.CalledOnValidThread());
526 567
527 if (mojo::IsMasterInterfaceId(id)) 568 if (mojo::IsMasterInterfaceId(id))
528 return false; 569 return false;
529 570
571 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
530 base::AutoLock locker(lock_); 572 base::AutoLock locker(lock_);
531 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr); 573 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
532 if (!endpoint->peer_closed()) { 574 if (!endpoint->peer_closed()) {
533 if (endpoint->client()) 575 if (endpoint->client())
534 NotifyEndpointOfError(endpoint.get(), false /* force_async */); 576 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
535 MarkPeerClosedAndMaybeRemove(endpoint.get()); 577 MarkPeerClosedAndMaybeRemove(endpoint.get());
536 } 578 }
537 579
538 return true; 580 return true;
539 } 581 }
(...skipping 10 matching lines...) Expand all
550 MarkClosedAndMaybeRemove(endpoint); 592 MarkClosedAndMaybeRemove(endpoint);
551 control_message_proxy_.NotifyPeerEndpointClosed(id); 593 control_message_proxy_.NotifyPeerEndpointClosed(id);
552 return true; 594 return true;
553 } 595 }
554 596
555 // Checked in places which must be run on the master endpoint's thread. 597 // Checked in places which must be run on the master endpoint's thread.
556 base::ThreadChecker thread_checker_; 598 base::ThreadChecker thread_checker_;
557 599
558 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 600 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
559 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_; 601 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
560 const uint32_t id_namespace_mask_; 602 const bool set_interface_id_namespace_bit_;
561 std::unique_ptr<mojo::AssociatedGroup> associated_group_; 603 std::unique_ptr<mojo::Connector> connector_;
562 mojo::Connector connector_;
563 mojo::MessageHeaderValidator header_validator_; 604 mojo::MessageHeaderValidator header_validator_;
564 mojo::PipeControlMessageHandler control_message_handler_; 605 mojo::PipeControlMessageHandler control_message_handler_;
606 ControlMessageProxyThunk control_message_proxy_thunk_;
607 mojo::PipeControlMessageProxy control_message_proxy_;
608
609 // Outgoing messages that were sent before this controller was bound to a
610 // real message pipe.
611 std::vector<std::unique_ptr<mojo::Message>> outgoing_messages_;
565 612
566 // Guards the fields below for thread-safe access. 613 // Guards the fields below for thread-safe access.
567 base::Lock lock_; 614 base::Lock lock_;
568 615
569 bool encountered_error_ = false; 616 bool encountered_error_ = false;
570 uint32_t next_interface_id_ = 1; 617
618 // ID #1 is reserved for the mojom::Channel interface.
619 uint32_t next_interface_id_ = 2;
620
571 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_; 621 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
572 mojo::PipeControlMessageProxy control_message_proxy_;
573 622
574 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController); 623 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
575 }; 624 };
576 625
577 class BootstrapMasterProxy { 626 class MojoBootstrapImpl : public MojoBootstrap {
578 public: 627 public:
579 BootstrapMasterProxy() {} 628 MojoBootstrapImpl(
580 ~BootstrapMasterProxy() { 629 mojo::ScopedMessagePipeHandle handle,
581 endpoint_client_.reset(); 630 Delegate* delegate,
582 proxy_.reset(); 631 const scoped_refptr<ChannelAssociatedGroupController> controller)
583 if (controller_) 632 : controller_(controller),
584 controller_->ShutDown(); 633 handle_(std::move(handle)),
634 delegate_(delegate) {
635 associated_group_ = controller_->CreateAssociatedGroup();
585 } 636 }
586 637
587 void Bind(mojo::ScopedMessagePipeHandle handle) { 638 ~MojoBootstrapImpl() override {
588 DCHECK(!controller_); 639 controller_->ShutDown();
589 controller_ = new ChannelAssociatedGroupController(true, std::move(handle));
590 endpoint_client_.reset(new mojo::InterfaceEndpointClient(
591 controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId),
592 nullptr,
593 base::MakeUnique<typename mojom::Bootstrap::ResponseValidator_>(),
594 false, base::ThreadTaskRunnerHandle::Get()));
595 proxy_.reset(new mojom::BootstrapProxy(endpoint_client_.get()));
596 proxy_->serialization_context()->group_controller = controller_;
597 }
598
599 void set_connection_error_handler(const base::Closure& handler) {
600 DCHECK(endpoint_client_);
601 endpoint_client_->set_connection_error_handler(handler);
602 }
603
604 mojo::AssociatedGroup* associated_group() {
605 DCHECK(controller_);
606 return controller_->associated_group();
607 }
608
609 ChannelAssociatedGroupController* controller() {
610 DCHECK(controller_);
611 return controller_.get();
612 }
613
614 mojom::Bootstrap* operator->() {
615 DCHECK(proxy_);
616 return proxy_.get();
617 } 640 }
618 641
619 private: 642 private:
620 std::unique_ptr<mojom::BootstrapProxy> proxy_; 643 // MojoBootstrap:
644 void Connect() override {
645 controller_->Bind(std::move(handle_));
646
647 IPC::mojom::ChannelAssociatedPtr sender;
648 IPC::mojom::ChannelAssociatedRequest receiver;
649 controller_->CreateChannelEndpoints(&sender, &receiver);
650
651 delegate_->OnPipesAvailable(std::move(sender), std::move(receiver));
652 }
653
654 mojo::AssociatedGroup* GetAssociatedGroup() override {
655 return associated_group_.get();
656 }
657
621 scoped_refptr<ChannelAssociatedGroupController> controller_; 658 scoped_refptr<ChannelAssociatedGroupController> controller_;
622 std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_;
623 659
624 DISALLOW_COPY_AND_ASSIGN(BootstrapMasterProxy); 660 mojo::ScopedMessagePipeHandle handle_;
661 Delegate* delegate_;
662 std::unique_ptr<mojo::AssociatedGroup> associated_group_;
663
664 DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl);
625 }; 665 };
626 666
627 class BootstrapMasterBinding {
628 public:
629 explicit BootstrapMasterBinding(mojom::Bootstrap* impl) {
630 stub_.set_sink(impl);
631 }
632
633 ~BootstrapMasterBinding() {
634 endpoint_client_.reset();
635 if (controller_)
636 controller_->ShutDown();
637 }
638
639 void set_connection_error_handler(const base::Closure& handler) {
640 DCHECK(endpoint_client_);
641 endpoint_client_->set_connection_error_handler(handler);
642 }
643
644 mojo::AssociatedGroup* associated_group() {
645 DCHECK(controller_);
646 return controller_->associated_group();
647 }
648
649 ChannelAssociatedGroupController* controller() {
650 DCHECK(controller_);
651 return controller_.get();
652 }
653
654 void Bind(mojo::ScopedMessagePipeHandle handle) {
655 DCHECK(!controller_);
656 controller_ =
657 new ChannelAssociatedGroupController(false, std::move(handle));
658 stub_.serialization_context()->group_controller = controller_;
659
660 endpoint_client_.reset(new mojo::InterfaceEndpointClient(
661 controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId),
662 &stub_,
663 base::MakeUnique<typename mojom::Bootstrap::RequestValidator_>(),
664 false, base::ThreadTaskRunnerHandle::Get()));
665 }
666
667 private:
668 mojom::BootstrapStub stub_;
669 scoped_refptr<ChannelAssociatedGroupController> controller_;
670 std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_;
671
672 DISALLOW_COPY_AND_ASSIGN(BootstrapMasterBinding);
673 };
674
675 // MojoBootstrap for the server process. You should create the instance
676 // using MojoBootstrap::Create().
677 class MojoServerBootstrap : public MojoBootstrap {
678 public:
679 MojoServerBootstrap();
680
681 private:
682 // MojoBootstrap implementation.
683 void Connect() override;
684
685 mojo::AssociatedGroup* GetAssociatedGroup() override {
686 return bootstrap_.associated_group();
687 }
688
689 void SetProxyTaskRunner(
690 scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
691 bootstrap_.controller()->SetProxyTaskRunner(task_runner);
692 }
693
694 void OnInitDone(int32_t peer_pid);
695
696 BootstrapMasterProxy bootstrap_;
697 IPC::mojom::ChannelAssociatedPtrInfo send_channel_;
698 IPC::mojom::ChannelAssociatedRequest receive_channel_request_;
699
700 DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
701 };
702
703 MojoServerBootstrap::MojoServerBootstrap() = default;
704
705 void MojoServerBootstrap::Connect() {
706 DCHECK_EQ(state(), STATE_INITIALIZED);
707
708 bootstrap_.Bind(TakeHandle());
709 bootstrap_.set_connection_error_handler(
710 base::Bind(&MojoServerBootstrap::Fail, base::Unretained(this)));
711
712 IPC::mojom::ChannelAssociatedRequest send_channel_request;
713 IPC::mojom::ChannelAssociatedPtrInfo receive_channel;
714
715 bootstrap_.associated_group()->CreateAssociatedInterface(
716 mojo::AssociatedGroup::WILL_PASS_REQUEST, &send_channel_,
717 &send_channel_request);
718 bootstrap_.associated_group()->CreateAssociatedInterface(
719 mojo::AssociatedGroup::WILL_PASS_PTR, &receive_channel,
720 &receive_channel_request_);
721
722 bootstrap_->Init(
723 std::move(send_channel_request), std::move(receive_channel),
724 GetSelfPID(),
725 base::Bind(&MojoServerBootstrap::OnInitDone, base::Unretained(this)));
726
727 set_state(STATE_WAITING_ACK);
728 }
729
730 void MojoServerBootstrap::OnInitDone(int32_t peer_pid) {
731 if (state() != STATE_WAITING_ACK) {
732 set_state(STATE_ERROR);
733 LOG(ERROR) << "Got inconsistent message from client.";
734 return;
735 }
736
737 set_state(STATE_READY);
738 bootstrap_.set_connection_error_handler(base::Closure());
739 delegate()->OnPipesAvailable(std::move(send_channel_),
740 std::move(receive_channel_request_), peer_pid);
741 }
742
743 // MojoBootstrap for client processes. You should create the instance
744 // using MojoBootstrap::Create().
745 class MojoClientBootstrap : public MojoBootstrap, public mojom::Bootstrap {
746 public:
747 MojoClientBootstrap();
748
749 private:
750 // MojoBootstrap implementation.
751 void Connect() override;
752
753 mojo::AssociatedGroup* GetAssociatedGroup() override {
754 return binding_.associated_group();
755 }
756
757 void SetProxyTaskRunner(
758 scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
759 binding_.controller()->SetProxyTaskRunner(task_runner);
760 }
761
762 // mojom::Bootstrap implementation.
763 void Init(mojom::ChannelAssociatedRequest receive_channel,
764 mojom::ChannelAssociatedPtrInfo send_channel,
765 int32_t peer_pid,
766 const InitCallback& callback) override;
767
768 BootstrapMasterBinding binding_;
769
770 DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
771 };
772
773 MojoClientBootstrap::MojoClientBootstrap() : binding_(this) {}
774
775 void MojoClientBootstrap::Connect() {
776 binding_.Bind(TakeHandle());
777 binding_.set_connection_error_handler(
778 base::Bind(&MojoClientBootstrap::Fail, base::Unretained(this)));
779 }
780
781 void MojoClientBootstrap::Init(mojom::ChannelAssociatedRequest receive_channel,
782 mojom::ChannelAssociatedPtrInfo send_channel,
783 int32_t peer_pid,
784 const InitCallback& callback) {
785 callback.Run(GetSelfPID());
786 set_state(STATE_READY);
787 binding_.set_connection_error_handler(base::Closure());
788 delegate()->OnPipesAvailable(std::move(send_channel),
789 std::move(receive_channel), peer_pid);
790 }
791
792 } // namespace 667 } // namespace
793 668
794 // MojoBootstrap
795
796 // static 669 // static
797 std::unique_ptr<MojoBootstrap> MojoBootstrap::Create( 670 std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
798 mojo::ScopedMessagePipeHandle handle, 671 mojo::ScopedMessagePipeHandle handle,
799 Channel::Mode mode, 672 Channel::Mode mode,
800 Delegate* delegate) { 673 Delegate* delegate,
801 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER); 674 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
802 std::unique_ptr<MojoBootstrap> self = 675 return base::MakeUnique<MojoBootstrapImpl>(
803 mode == Channel::MODE_CLIENT 676 std::move(handle), delegate,
804 ? std::unique_ptr<MojoBootstrap>(new MojoClientBootstrap) 677 new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER,
805 : std::unique_ptr<MojoBootstrap>(new MojoServerBootstrap); 678 ipc_task_runner));
806
807 self->Init(std::move(handle), delegate);
808 return self;
809 }
810
811 MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
812 }
813
814 MojoBootstrap::~MojoBootstrap() {}
815
816 void MojoBootstrap::Init(mojo::ScopedMessagePipeHandle handle,
817 Delegate* delegate) {
818 handle_ = std::move(handle);
819 delegate_ = delegate;
820 }
821
822 base::ProcessId MojoBootstrap::GetSelfPID() const {
823 #if defined(OS_LINUX)
824 if (int global_pid = Channel::GetGlobalPid())
825 return global_pid;
826 #endif // OS_LINUX
827 #if defined(OS_NACL)
828 return -1;
829 #else
830 return base::GetCurrentProcId();
831 #endif // defined(OS_NACL)
832 }
833
834 void MojoBootstrap::Fail() {
835 set_state(STATE_ERROR);
836 delegate()->OnBootstrapError();
837 }
838
839 bool MojoBootstrap::HasFailed() const {
840 return state() == STATE_ERROR;
841 }
842
843 mojo::ScopedMessagePipeHandle MojoBootstrap::TakeHandle() {
844 return std::move(handle_);
845 } 679 }
846 680
847 } // namespace IPC 681 } // namespace IPC
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698