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

Side by Side Diff: ipc/ipc_mojo_bootstrap.cc

Issue 2173753002: Revert of 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, 4 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
« no previous file with comments | « ipc/ipc_mojo_bootstrap.h ('k') | ipc/ipc_mojo_bootstrap_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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>
13 12
14 #include "base/callback.h" 13 #include "base/callback.h"
15 #include "base/logging.h" 14 #include "base/logging.h"
16 #include "base/macros.h" 15 #include "base/macros.h"
17 #include "base/memory/ptr_util.h" 16 #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"
33 #include "mojo/public/cpp/bindings/message_header_validator.h" 32 #include "mojo/public/cpp/bindings/message_header_validator.h"
34 #include "mojo/public/cpp/bindings/pipe_control_message_handler.h" 33 #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
35 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" 34 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
36 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" 35 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
37 36
38 namespace IPC { 37 namespace IPC {
39 38
40 namespace { 39 namespace {
41 40
42 class ChannelAssociatedGroupController 41 class ChannelAssociatedGroupController
43 : public mojo::AssociatedGroupController, 42 : public mojo::AssociatedGroupController,
44 public mojo::MessageReceiver, 43 public mojo::MessageReceiver,
45 public mojo::PipeControlMessageHandlerDelegate { 44 public mojo::PipeControlMessageHandlerDelegate {
46 public: 45 public:
47 ChannelAssociatedGroupController( 46 ChannelAssociatedGroupController(bool set_interface_id_namespace_bit,
48 bool set_interface_id_namespace_bit, 47 mojo::ScopedMessagePipeHandle handle)
49 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
50 : mojo::AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()), 48 : mojo::AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()),
51 task_runner_(ipc_task_runner), 49 task_runner_(base::ThreadTaskRunnerHandle::Get()),
52 proxy_task_runner_(base::ThreadTaskRunnerHandle::Get()), 50 id_namespace_mask_(set_interface_id_namespace_bit ?
53 set_interface_id_namespace_bit_(set_interface_id_namespace_bit), 51 mojo::kInterfaceIdNamespaceMask : 0),
52 associated_group_(CreateAssociatedGroup()),
53 connector_(std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
54 base::ThreadTaskRunnerHandle::Get()),
54 header_validator_( 55 header_validator_(
55 "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this), 56 "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this),
56 control_message_handler_(this), 57 control_message_handler_(this),
57 control_message_proxy_thunk_(this), 58 control_message_proxy_(&connector_) {
58 control_message_proxy_(&control_message_proxy_thunk_) { 59 connector_.set_incoming_receiver(&header_validator_);
59 thread_checker_.DetachFromThread(); 60 connector_.set_connection_error_handler(
61 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
62 base::Unretained(this)));
60 control_message_handler_.SetDescription( 63 control_message_handler_.SetDescription(
61 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler"); 64 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
62 } 65 }
63 66
64 void Bind(mojo::ScopedMessagePipeHandle handle) { 67 mojo::AssociatedGroup* associated_group() { return associated_group_.get(); }
65 DCHECK(thread_checker_.CalledOnValidThread());
66 DCHECK(task_runner_->BelongsToCurrentThread());
67 thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
68 connector_.reset(new mojo::Connector(
69 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
70 task_runner_));
71 connector_->set_incoming_receiver(&header_validator_);
72 connector_->set_connection_error_handler(
73 base::Bind(&ChannelAssociatedGroupController::OnPipeError,
74 base::Unretained(this)));
75
76 std::vector<std::unique_ptr<mojo::Message>> outgoing_messages;
77 std::swap(outgoing_messages, outgoing_messages_);
78 for (auto& message : outgoing_messages)
79 SendMessage(message.get());
80 }
81
82 void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
83 mojom::ChannelAssociatedRequest* receiver) {
84 mojo::InterfaceId sender_id, receiver_id;
85 if (set_interface_id_namespace_bit_) {
86 sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
87 receiver_id = 1;
88 } else {
89 sender_id = 1;
90 receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
91 }
92
93 {
94 base::AutoLock locker(lock_);
95 Endpoint* sender_endpoint = new Endpoint(this, sender_id);
96 Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
97 endpoints_.insert({ sender_id, sender_endpoint });
98 endpoints_.insert({ receiver_id, receiver_endpoint });
99 }
100
101 mojo::ScopedInterfaceEndpointHandle sender_handle =
102 CreateScopedInterfaceEndpointHandle(sender_id, true);
103 mojo::ScopedInterfaceEndpointHandle receiver_handle =
104 CreateScopedInterfaceEndpointHandle(receiver_id, true);
105
106 sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
107 receiver->Bind(std::move(receiver_handle));
108 }
109 68
110 void ShutDown() { 69 void ShutDown() {
111 DCHECK(thread_checker_.CalledOnValidThread()); 70 DCHECK(thread_checker_.CalledOnValidThread());
112 connector_->CloseMessagePipe(); 71 connector_.CloseMessagePipe();
113 OnPipeError(); 72 OnPipeError();
114 connector_.reset(); 73 associated_group_.reset();
74 }
75
76 void SetProxyTaskRunner(
77 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner) {
78 proxy_task_runner_ = proxy_task_runner;
115 } 79 }
116 80
117 // mojo::AssociatedGroupController: 81 // mojo::AssociatedGroupController:
118 void CreateEndpointHandlePair( 82 void CreateEndpointHandlePair(
119 mojo::ScopedInterfaceEndpointHandle* local_endpoint, 83 mojo::ScopedInterfaceEndpointHandle* local_endpoint,
120 mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override { 84 mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override {
121 base::AutoLock locker(lock_); 85 base::AutoLock locker(lock_);
122 uint32_t id = 0; 86 uint32_t id = 0;
123 do { 87 do {
124 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask) 88 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
125 next_interface_id_ = 2; 89 next_interface_id_ = 1;
126 id = next_interface_id_++; 90 id = (next_interface_id_++) | id_namespace_mask_;
127 if (set_interface_id_namespace_bit_)
128 id |= mojo::kInterfaceIdNamespaceMask;
129 } while (ContainsKey(endpoints_, id)); 91 } while (ContainsKey(endpoints_, id));
130 92
131 Endpoint* endpoint = new Endpoint(this, id); 93 Endpoint* endpoint = new Endpoint(this, id);
132 if (encountered_error_) 94 if (encountered_error_)
133 endpoint->set_peer_closed(); 95 endpoint->set_peer_closed();
134 endpoints_.insert({ id, endpoint }); 96 endpoints_.insert({ id, endpoint });
135 97
136 *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true); 98 *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true);
137 *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false); 99 *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false);
138 } 100 }
(...skipping 13 matching lines...) Expand all
152 } 114 }
153 115
154 void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override { 116 void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override {
155 if (!mojo::IsValidInterfaceId(id)) 117 if (!mojo::IsValidInterfaceId(id))
156 return; 118 return;
157 119
158 base::AutoLock locker(lock_); 120 base::AutoLock locker(lock_);
159 if (!is_local) { 121 if (!is_local) {
160 DCHECK(ContainsKey(endpoints_, id)); 122 DCHECK(ContainsKey(endpoints_, id));
161 DCHECK(!mojo::IsMasterInterfaceId(id)); 123 DCHECK(!mojo::IsMasterInterfaceId(id));
162 control_message_proxy_.NotifyEndpointClosedBeforeSent(id); 124 NotifyEndpointClosedBeforeSent(id);
163 return; 125 return;
164 } 126 }
165 127
166 DCHECK(ContainsKey(endpoints_, id)); 128 DCHECK(ContainsKey(endpoints_, id));
167 Endpoint* endpoint = endpoints_[id].get(); 129 Endpoint* endpoint = endpoints_[id].get();
168 DCHECK(!endpoint->client()); 130 DCHECK(!endpoint->client());
169 DCHECK(!endpoint->closed()); 131 DCHECK(!endpoint->closed());
170 MarkClosedAndMaybeRemove(endpoint); 132 MarkClosedAndMaybeRemove(endpoint);
171 133
172 if (!mojo::IsMasterInterfaceId(id)) 134 if (!mojo::IsMasterInterfaceId(id))
173 control_message_proxy_.NotifyPeerEndpointClosed(id); 135 NotifyPeerEndpointClosed(id);
174 } 136 }
175 137
176 mojo::InterfaceEndpointController* AttachEndpointClient( 138 mojo::InterfaceEndpointController* AttachEndpointClient(
177 const mojo::ScopedInterfaceEndpointHandle& handle, 139 const mojo::ScopedInterfaceEndpointHandle& handle,
178 mojo::InterfaceEndpointClient* client, 140 mojo::InterfaceEndpointClient* client,
179 scoped_refptr<base::SingleThreadTaskRunner> runner) override { 141 scoped_refptr<base::SingleThreadTaskRunner> runner) override {
180 const mojo::InterfaceId id = handle.id(); 142 const mojo::InterfaceId id = handle.id();
181 143
182 DCHECK(mojo::IsValidInterfaceId(id)); 144 DCHECK(mojo::IsValidInterfaceId(id));
183 DCHECK(client); 145 DCHECK(client);
(...skipping 17 matching lines...) Expand all
201 DCHECK(mojo::IsValidInterfaceId(id)); 163 DCHECK(mojo::IsValidInterfaceId(id));
202 164
203 base::AutoLock locker(lock_); 165 base::AutoLock locker(lock_);
204 DCHECK(ContainsKey(endpoints_, id)); 166 DCHECK(ContainsKey(endpoints_, id));
205 167
206 Endpoint* endpoint = endpoints_[id].get(); 168 Endpoint* endpoint = endpoints_[id].get();
207 endpoint->DetachClient(); 169 endpoint->DetachClient();
208 } 170 }
209 171
210 void RaiseError() override { 172 void RaiseError() override {
211 if (IsRunningOnIPCThread()) { 173 if (task_runner_->BelongsToCurrentThread()) {
212 connector_->RaiseError(); 174 connector_.RaiseError();
213 } else { 175 } else {
214 task_runner_->PostTask( 176 task_runner_->PostTask(
215 FROM_HERE, 177 FROM_HERE,
216 base::Bind(&ChannelAssociatedGroupController::RaiseError, this)); 178 base::Bind(&ChannelAssociatedGroupController::RaiseError, this));
217 } 179 }
218 } 180 }
219 181
220 private: 182 private:
221 class Endpoint; 183 class Endpoint;
222 class ControlMessageProxyThunk;
223 friend class Endpoint; 184 friend class Endpoint;
224 friend class ControlMessageProxyThunk;
225 185
226 class Endpoint : public base::RefCountedThreadSafe<Endpoint>, 186 class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
227 public mojo::InterfaceEndpointController { 187 public mojo::InterfaceEndpointController {
228 public: 188 public:
229 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id) 189 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
230 : controller_(controller), id_(id) {} 190 : controller_(controller), id_(id) {}
231 191
232 mojo::InterfaceId id() const { return id_; } 192 mojo::InterfaceId id() const { return id_; }
233 193
234 bool closed() const { 194 bool closed() const {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 253
294 // TODO(rockot): Implement sync waiting. 254 // TODO(rockot): Implement sync waiting.
295 NOTREACHED(); 255 NOTREACHED();
296 } 256 }
297 257
298 bool SyncWatch(const bool* should_stop) override { 258 bool SyncWatch(const bool* should_stop) override {
299 DCHECK(task_runner_->BelongsToCurrentThread()); 259 DCHECK(task_runner_->BelongsToCurrentThread());
300 260
301 // It's not legal to make sync calls from the master endpoint's thread, 261 // It's not legal to make sync calls from the master endpoint's thread,
302 // and in fact they must only happen from the proxy task runner. 262 // and in fact they must only happen from the proxy task runner.
303 DCHECK(!controller_->IsRunningOnIPCThread()); 263 DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
304 DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread()); 264 DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
305 265
306 // TODO(rockot): Implement sync waiting. 266 // TODO(rockot): Implement sync waiting.
307 NOTREACHED(); 267 NOTREACHED();
308 return false; 268 return false;
309 } 269 }
310 270
311 private: 271 private:
312 friend class base::RefCountedThreadSafe<Endpoint>; 272 friend class base::RefCountedThreadSafe<Endpoint>;
313 273
314 ~Endpoint() override {} 274 ~Endpoint() override {}
315 275
316 ChannelAssociatedGroupController* const controller_; 276 ChannelAssociatedGroupController* const controller_;
317 const mojo::InterfaceId id_; 277 const mojo::InterfaceId id_;
318 278
319 bool closed_ = false; 279 bool closed_ = false;
320 bool peer_closed_ = false; 280 bool peer_closed_ = false;
321 mojo::InterfaceEndpointClient* client_ = nullptr; 281 mojo::InterfaceEndpointClient* client_ = nullptr;
322 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 282 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
323 283
324 DISALLOW_COPY_AND_ASSIGN(Endpoint); 284 DISALLOW_COPY_AND_ASSIGN(Endpoint);
325 }; 285 };
326 286
327 class ControlMessageProxyThunk : public MessageReceiver {
328 public:
329 explicit ControlMessageProxyThunk(
330 ChannelAssociatedGroupController* controller)
331 : controller_(controller) {}
332
333 private:
334 // MessageReceiver:
335 bool Accept(mojo::Message* message) override {
336 return controller_->SendMessage(message);
337 }
338
339 ChannelAssociatedGroupController* controller_;
340
341 DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
342 };
343
344 ~ChannelAssociatedGroupController() override { 287 ~ChannelAssociatedGroupController() override {
345 base::AutoLock locker(lock_); 288 base::AutoLock locker(lock_);
289
346 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { 290 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
347 Endpoint* endpoint = iter->second.get(); 291 Endpoint* endpoint = iter->second.get();
348 ++iter; 292 ++iter;
349 293
350 DCHECK(endpoint->closed()); 294 DCHECK(endpoint->closed());
351 MarkPeerClosedAndMaybeRemove(endpoint); 295 MarkPeerClosedAndMaybeRemove(endpoint);
352 } 296 }
353 297
354 DCHECK(endpoints_.empty()); 298 DCHECK(endpoints_.empty());
355 } 299 }
356 300
357 bool IsRunningOnIPCThread() {
358 // |task_runner_| is always non-null but may incorrectly report that
359 // BelongsToCurrentThread() == false during shutdown. By the time shutdown
360 // occurs, |thread_task_runner_| will be non-null and is guaranteed to run
361 // tasks on the same thread as |task_runner_|.
362 return task_runner_->BelongsToCurrentThread() ||
363 (thread_task_runner_ && thread_task_runner_->BelongsToCurrentThread());
364 }
365
366 bool SendMessage(mojo::Message* message) { 301 bool SendMessage(mojo::Message* message) {
367 if (IsRunningOnIPCThread()) { 302 if (task_runner_->BelongsToCurrentThread()) {
368 DCHECK(thread_checker_.CalledOnValidThread()); 303 DCHECK(thread_checker_.CalledOnValidThread());
369 if (!connector_) { 304 return connector_.Accept(message);
370 // Pipe may not be bound yet, so we queue the message.
371 std::unique_ptr<mojo::Message> queued_message(new mojo::Message);
372 message->MoveTo(queued_message.get());
373 outgoing_messages_.emplace_back(std::move(queued_message));
374 return true;
375 }
376 return connector_->Accept(message);
377 } else { 305 } else {
378 // We always post tasks to the master endpoint thread when called from the 306 // We always post tasks to the master endpoint thread when called from the
379 // proxy thread in order to simulate IPC::ChannelProxy::Send behavior. 307 // proxy thread in order to simulate IPC::ChannelProxy::Send behavior.
380 DCHECK(proxy_task_runner_->BelongsToCurrentThread()); 308 DCHECK(proxy_task_runner_ &&
309 proxy_task_runner_->BelongsToCurrentThread());
381 std::unique_ptr<mojo::Message> passed_message(new mojo::Message); 310 std::unique_ptr<mojo::Message> passed_message(new mojo::Message);
382 message->MoveTo(passed_message.get()); 311 message->MoveTo(passed_message.get());
383 task_runner_->PostTask( 312 task_runner_->PostTask(
384 FROM_HERE, 313 FROM_HERE,
385 base::Bind( 314 base::Bind(
386 &ChannelAssociatedGroupController::SendMessageOnMasterThread, 315 &ChannelAssociatedGroupController::SendMessageOnMasterThread,
387 this, base::Passed(&passed_message))); 316 this, base::Passed(&passed_message)));
388 return true; 317 return true;
389 } 318 }
390 } 319 }
(...skipping 19 matching lines...) Expand all
410 Endpoint* endpoint = iter->second.get(); 339 Endpoint* endpoint = iter->second.get();
411 ++iter; 340 ++iter;
412 341
413 if (endpoint->client()) 342 if (endpoint->client())
414 endpoints_to_notify.push_back(endpoint); 343 endpoints_to_notify.push_back(endpoint);
415 344
416 MarkPeerClosedAndMaybeRemove(endpoint); 345 MarkPeerClosedAndMaybeRemove(endpoint);
417 } 346 }
418 347
419 for (auto& endpoint : endpoints_to_notify) { 348 for (auto& endpoint : endpoints_to_notify) {
420 // Because a notification may in turn detach any endpoint, we have to 349 // Because an notification may in turn detach any endpoint, we have to
421 // check each client again here. 350 // check each client again here.
422 if (endpoint->client()) 351 if (endpoint->client())
423 NotifyEndpointOfError(endpoint.get(), false /* force_async */); 352 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
424 } 353 }
425 } 354 }
426 355
427 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) { 356 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
428 lock_.AssertAcquired(); 357 lock_.AssertAcquired();
429 DCHECK(endpoint->task_runner() && endpoint->client()); 358 DCHECK(endpoint->task_runner() && endpoint->client());
430 if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) { 359 if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) {
(...skipping 25 matching lines...) Expand all
456 endpoints_.erase(endpoint->id()); 385 endpoints_.erase(endpoint->id());
457 } 386 }
458 387
459 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) { 388 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
460 lock_.AssertAcquired(); 389 lock_.AssertAcquired();
461 endpoint->set_peer_closed(); 390 endpoint->set_peer_closed();
462 if (endpoint->closed() && endpoint->peer_closed()) 391 if (endpoint->closed() && endpoint->peer_closed())
463 endpoints_.erase(endpoint->id()); 392 endpoints_.erase(endpoint->id());
464 } 393 }
465 394
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
466 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) { 419 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
467 lock_.AssertAcquired(); 420 lock_.AssertAcquired();
468 DCHECK(!inserted || !*inserted); 421 DCHECK(!inserted || !*inserted);
469 422
470 auto iter = endpoints_.find(id); 423 auto iter = endpoints_.find(id);
471 if (iter != endpoints_.end()) 424 if (iter != endpoints_.end())
472 return iter->second.get(); 425 return iter->second.get();
473 426
474 Endpoint* endpoint = new Endpoint(this, id); 427 Endpoint* endpoint = new Endpoint(this, id);
475 endpoints_.insert({ id, endpoint }); 428 endpoints_.insert({ id, endpoint });
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 RaiseError(); 503 RaiseError();
551 } 504 }
552 505
553 Endpoint* GetEndpointForDispatch(mojo::InterfaceId id) { 506 Endpoint* GetEndpointForDispatch(mojo::InterfaceId id) {
554 lock_.AssertAcquired(); 507 lock_.AssertAcquired();
555 bool inserted = false; 508 bool inserted = false;
556 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted); 509 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
557 if (inserted) { 510 if (inserted) {
558 MarkClosedAndMaybeRemove(endpoint); 511 MarkClosedAndMaybeRemove(endpoint);
559 if (!mojo::IsMasterInterfaceId(id)) 512 if (!mojo::IsMasterInterfaceId(id))
560 control_message_proxy_.NotifyPeerEndpointClosed(id); 513 NotifyPeerEndpointClosed(id);
561 return nullptr; 514 return nullptr;
562 } 515 }
563 516
564 if (endpoint->closed()) 517 if (endpoint->closed())
565 return nullptr; 518 return nullptr;
566 519
567 return endpoint; 520 return endpoint;
568 } 521 }
569 522
570 // mojo::PipeControlMessageHandlerDelegate: 523 // mojo::PipeControlMessageHandlerDelegate:
571 bool OnPeerAssociatedEndpointClosed(mojo::InterfaceId id) override { 524 bool OnPeerAssociatedEndpointClosed(mojo::InterfaceId id) override {
572 DCHECK(thread_checker_.CalledOnValidThread()); 525 DCHECK(thread_checker_.CalledOnValidThread());
573 526
574 if (mojo::IsMasterInterfaceId(id)) 527 if (mojo::IsMasterInterfaceId(id))
575 return false; 528 return false;
576 529
577 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
578 base::AutoLock locker(lock_); 530 base::AutoLock locker(lock_);
579 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr); 531 scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
580 if (!endpoint->peer_closed()) { 532 if (!endpoint->peer_closed()) {
581 if (endpoint->client()) 533 if (endpoint->client())
582 NotifyEndpointOfError(endpoint.get(), false /* force_async */); 534 NotifyEndpointOfError(endpoint.get(), false /* force_async */);
583 MarkPeerClosedAndMaybeRemove(endpoint.get()); 535 MarkPeerClosedAndMaybeRemove(endpoint.get());
584 } 536 }
585 537
586 return true; 538 return true;
587 } 539 }
588 540
589 bool OnAssociatedEndpointClosedBeforeSent(mojo::InterfaceId id) override { 541 bool OnAssociatedEndpointClosedBeforeSent(mojo::InterfaceId id) override {
590 DCHECK(thread_checker_.CalledOnValidThread()); 542 DCHECK(thread_checker_.CalledOnValidThread());
591 543
592 if (mojo::IsMasterInterfaceId(id)) 544 if (mojo::IsMasterInterfaceId(id))
593 return false; 545 return false;
594 546
595 base::AutoLock locker(lock_); 547 base::AutoLock locker(lock_);
596 Endpoint* endpoint = FindOrInsertEndpoint(id, nullptr); 548 Endpoint* endpoint = FindOrInsertEndpoint(id, nullptr);
597 DCHECK(!endpoint->closed()); 549 DCHECK(!endpoint->closed());
598 MarkClosedAndMaybeRemove(endpoint); 550 MarkClosedAndMaybeRemove(endpoint);
599 control_message_proxy_.NotifyPeerEndpointClosed(id); 551 control_message_proxy_.NotifyPeerEndpointClosed(id);
600 return true; 552 return true;
601 } 553 }
602 554
603 // Checked in places which must be run on the master endpoint's thread. 555 // Checked in places which must be run on the master endpoint's thread.
604 base::ThreadChecker thread_checker_; 556 base::ThreadChecker thread_checker_;
605 557
606 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 558 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
607
608 // A TaskRunner that runs tasks on the same thread as |task_runner_| but which
609 // is used exclusively to do thread safety checking. This is an unfortunate
610 // consequence of bad interaction between some TaskRunner implementations and
611 // MessageLoop destruction which may cause the user-provided |task_runner_| to
612 // incorrectly report that BelongsToCurrentThread() == false during shutdown.
613 scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
614
615 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_; 559 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
616 const bool set_interface_id_namespace_bit_; 560 const uint32_t id_namespace_mask_;
617 std::unique_ptr<mojo::Connector> connector_; 561 std::unique_ptr<mojo::AssociatedGroup> associated_group_;
562 mojo::Connector connector_;
618 mojo::MessageHeaderValidator header_validator_; 563 mojo::MessageHeaderValidator header_validator_;
619 mojo::PipeControlMessageHandler control_message_handler_; 564 mojo::PipeControlMessageHandler control_message_handler_;
620 ControlMessageProxyThunk control_message_proxy_thunk_;
621 mojo::PipeControlMessageProxy control_message_proxy_;
622
623 // Outgoing messages that were sent before this controller was bound to a
624 // real message pipe.
625 std::vector<std::unique_ptr<mojo::Message>> outgoing_messages_;
626 565
627 // Guards the fields below for thread-safe access. 566 // Guards the fields below for thread-safe access.
628 base::Lock lock_; 567 base::Lock lock_;
629 568
630 bool encountered_error_ = false; 569 bool encountered_error_ = false;
631 570 uint32_t next_interface_id_ = 1;
632 // ID #1 is reserved for the mojom::Channel interface.
633 uint32_t next_interface_id_ = 2;
634
635 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_; 571 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
572 mojo::PipeControlMessageProxy control_message_proxy_;
636 573
637 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController); 574 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
638 }; 575 };
639 576
640 class MojoBootstrapImpl : public MojoBootstrap { 577 class BootstrapMasterProxy {
641 public: 578 public:
642 MojoBootstrapImpl( 579 BootstrapMasterProxy() {}
643 mojo::ScopedMessagePipeHandle handle, 580 ~BootstrapMasterProxy() {
644 Delegate* delegate, 581 endpoint_client_.reset();
645 const scoped_refptr<ChannelAssociatedGroupController> controller) 582 proxy_.reset();
646 : controller_(controller), 583 if (controller_)
647 handle_(std::move(handle)), 584 controller_->ShutDown();
648 delegate_(delegate) { 585 }
649 associated_group_ = controller_->CreateAssociatedGroup(); 586
650 } 587 void Bind(mojo::ScopedMessagePipeHandle handle) {
651 588 DCHECK(!controller_);
652 ~MojoBootstrapImpl() override { 589 controller_ = new ChannelAssociatedGroupController(true, std::move(handle));
653 controller_->ShutDown(); 590 endpoint_client_.reset(new mojo::InterfaceEndpointClient(
654 } 591 controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId),
655 592 nullptr,
656 private: 593 base::MakeUnique<typename mojom::Bootstrap::ResponseValidator_>(),
657 // MojoBootstrap: 594 false, base::ThreadTaskRunnerHandle::Get()));
658 void Connect() override { 595 proxy_.reset(new mojom::BootstrapProxy(endpoint_client_.get()));
659 controller_->Bind(std::move(handle_)); 596 proxy_->serialization_context()->group_controller = controller_;
660 597 }
661 IPC::mojom::ChannelAssociatedPtr sender; 598
662 IPC::mojom::ChannelAssociatedRequest receiver; 599 void set_connection_error_handler(const base::Closure& handler) {
663 controller_->CreateChannelEndpoints(&sender, &receiver); 600 DCHECK(endpoint_client_);
664 601 endpoint_client_->set_connection_error_handler(handler);
665 delegate_->OnPipesAvailable(std::move(sender), std::move(receiver)); 602 }
666 } 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 }
618
619 private:
620 std::unique_ptr<mojom::BootstrapProxy> proxy_;
621 scoped_refptr<ChannelAssociatedGroupController> controller_;
622 std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_;
623
624 DISALLOW_COPY_AND_ASSIGN(BootstrapMasterProxy);
625 };
626
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;
667 684
668 mojo::AssociatedGroup* GetAssociatedGroup() override { 685 mojo::AssociatedGroup* GetAssociatedGroup() override {
669 return associated_group_.get(); 686 return bootstrap_.associated_group();
670 } 687 }
671 688
672 scoped_refptr<ChannelAssociatedGroupController> controller_; 689 void SetProxyTaskRunner(
673 690 scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
674 mojo::ScopedMessagePipeHandle handle_; 691 bootstrap_.controller()->SetProxyTaskRunner(task_runner);
675 Delegate* delegate_; 692 }
676 std::unique_ptr<mojo::AssociatedGroup> associated_group_; 693
677 694 void OnInitDone(int32_t peer_pid);
678 DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl); 695
679 }; 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 }
680 791
681 } // namespace 792 } // namespace
682 793
794 // MojoBootstrap
795
683 // static 796 // static
684 std::unique_ptr<MojoBootstrap> MojoBootstrap::Create( 797 std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
685 mojo::ScopedMessagePipeHandle handle, 798 mojo::ScopedMessagePipeHandle handle,
686 Channel::Mode mode, 799 Channel::Mode mode,
687 Delegate* delegate, 800 Delegate* delegate) {
688 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) { 801 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
689 return base::MakeUnique<MojoBootstrapImpl>( 802 std::unique_ptr<MojoBootstrap> self =
690 std::move(handle), delegate, 803 mode == Channel::MODE_CLIENT
691 new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER, 804 ? std::unique_ptr<MojoBootstrap>(new MojoClientBootstrap)
692 ipc_task_runner)); 805 : std::unique_ptr<MojoBootstrap>(new MojoServerBootstrap);
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_);
693 } 845 }
694 846
695 } // namespace IPC 847 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_mojo_bootstrap.h ('k') | ipc/ipc_mojo_bootstrap_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698