OLD | NEW |
---|---|
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()), | 54 associated_group_(CreateAssociatedGroup()), |
53 connector_(std::move(handle), mojo::Connector::SINGLE_THREADED_SEND, | |
54 base::ThreadTaskRunnerHandle::Get()), | |
55 header_validator_( | 55 header_validator_( |
56 "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this), | 56 "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this), |
57 control_message_handler_(this), | 57 control_message_handler_(this), |
58 control_message_proxy_(&connector_) { | 58 control_message_proxy_thunk_(this), |
59 connector_.set_incoming_receiver(&header_validator_); | 59 control_message_proxy_(&control_message_proxy_thunk_) { |
60 connector_.set_connection_error_handler( | 60 thread_checker_.DetachFromThread(); |
61 base::Bind(&ChannelAssociatedGroupController::OnPipeError, | |
62 base::Unretained(this))); | |
63 control_message_handler_.SetDescription( | 61 control_message_handler_.SetDescription( |
64 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler"); | 62 "IPC::mojom::Bootstrap [master] PipeControlMessageHandler"); |
65 } | 63 } |
66 | 64 |
67 mojo::AssociatedGroup* associated_group() { return associated_group_.get(); } | 65 mojo::AssociatedGroup* associated_group() { return associated_group_.get(); } |
68 | 66 |
67 void Bind(mojo::ScopedMessagePipeHandle handle) { | |
68 DCHECK(thread_checker_.CalledOnValidThread()); | |
69 DCHECK(task_runner_->BelongsToCurrentThread()); | |
70 connector_.reset(new mojo::Connector( | |
71 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND, | |
72 base::ThreadTaskRunnerHandle::Get())); | |
yzshen1
2016/07/20 17:13:15
It may not matter, but strictly speaking we probab
Ken Rockot(use gerrit already)
2016/07/20 21:08:39
Indeed. This was an artifact from a previous itera
| |
73 connector_->set_incoming_receiver(&header_validator_); | |
74 connector_->set_connection_error_handler( | |
75 base::Bind(&ChannelAssociatedGroupController::OnPipeError, | |
76 base::Unretained(this))); | |
77 | |
78 std::vector<std::unique_ptr<mojo::Message>> outgoing_messages; | |
79 std::swap(outgoing_messages, outgoing_messages_); | |
80 for (auto& message : outgoing_messages) | |
81 SendMessage(message.get()); | |
82 } | |
83 | |
84 void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender, | |
85 mojom::ChannelAssociatedRequest* receiver) { | |
86 mojo::InterfaceId sender_id, receiver_id; | |
87 if (set_interface_id_namespace_bit_) { | |
88 sender_id = 1 | mojo::kInterfaceIdNamespaceMask; | |
89 receiver_id = 1; | |
90 } else { | |
91 sender_id = 1; | |
92 receiver_id = 1 | mojo::kInterfaceIdNamespaceMask; | |
93 } | |
94 | |
95 { | |
96 base::AutoLock locker(lock_); | |
97 Endpoint* sender_endpoint = new Endpoint(this, sender_id); | |
98 Endpoint* receiver_endpoint = new Endpoint(this, receiver_id); | |
99 endpoints_.insert({ sender_id, sender_endpoint }); | |
100 endpoints_.insert({ receiver_id, receiver_endpoint }); | |
101 } | |
102 | |
103 mojo::ScopedInterfaceEndpointHandle sender_handle = | |
104 CreateScopedInterfaceEndpointHandle(sender_id, true); | |
105 mojo::ScopedInterfaceEndpointHandle receiver_handle = | |
106 CreateScopedInterfaceEndpointHandle(receiver_id, true); | |
107 | |
108 sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0)); | |
109 receiver->Bind(std::move(receiver_handle)); | |
110 } | |
111 | |
69 void ShutDown() { | 112 void ShutDown() { |
70 DCHECK(thread_checker_.CalledOnValidThread()); | 113 DCHECK(thread_checker_.CalledOnValidThread()); |
71 connector_.CloseMessagePipe(); | 114 connector_->CloseMessagePipe(); |
72 OnPipeError(); | 115 OnPipeError(); |
73 associated_group_.reset(); | 116 associated_group_.reset(); |
74 } | 117 connector_.reset(); |
75 | |
76 void SetProxyTaskRunner( | |
77 scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner) { | |
78 proxy_task_runner_ = proxy_task_runner; | |
79 } | 118 } |
80 | 119 |
81 // mojo::AssociatedGroupController: | 120 // mojo::AssociatedGroupController: |
82 void CreateEndpointHandlePair( | 121 void CreateEndpointHandlePair( |
83 mojo::ScopedInterfaceEndpointHandle* local_endpoint, | 122 mojo::ScopedInterfaceEndpointHandle* local_endpoint, |
84 mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override { | 123 mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override { |
85 base::AutoLock locker(lock_); | 124 base::AutoLock locker(lock_); |
86 uint32_t id = 0; | 125 uint32_t id = 0; |
87 do { | 126 do { |
88 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask) | 127 if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask) |
89 next_interface_id_ = 1; | 128 next_interface_id_ = 2; |
90 id = (next_interface_id_++) | id_namespace_mask_; | 129 id = next_interface_id_++; |
130 if (set_interface_id_namespace_bit_) | |
131 id |= mojo::kInterfaceIdNamespaceMask; | |
91 } while (ContainsKey(endpoints_, id)); | 132 } while (ContainsKey(endpoints_, id)); |
92 | 133 |
93 Endpoint* endpoint = new Endpoint(this, id); | 134 Endpoint* endpoint = new Endpoint(this, id); |
94 if (encountered_error_) | 135 if (encountered_error_) |
95 endpoint->set_peer_closed(); | 136 endpoint->set_peer_closed(); |
96 endpoints_.insert({ id, endpoint }); | 137 endpoints_.insert({ id, endpoint }); |
97 | 138 |
98 *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true); | 139 *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true); |
99 *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false); | 140 *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false); |
100 } | 141 } |
(...skipping 13 matching lines...) Expand all Loading... | |
114 } | 155 } |
115 | 156 |
116 void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override { | 157 void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override { |
117 if (!mojo::IsValidInterfaceId(id)) | 158 if (!mojo::IsValidInterfaceId(id)) |
118 return; | 159 return; |
119 | 160 |
120 base::AutoLock locker(lock_); | 161 base::AutoLock locker(lock_); |
121 if (!is_local) { | 162 if (!is_local) { |
122 DCHECK(ContainsKey(endpoints_, id)); | 163 DCHECK(ContainsKey(endpoints_, id)); |
123 DCHECK(!mojo::IsMasterInterfaceId(id)); | 164 DCHECK(!mojo::IsMasterInterfaceId(id)); |
124 NotifyEndpointClosedBeforeSent(id); | 165 control_message_proxy_.NotifyEndpointClosedBeforeSent(id); |
125 return; | 166 return; |
126 } | 167 } |
127 | 168 |
128 DCHECK(ContainsKey(endpoints_, id)); | 169 DCHECK(ContainsKey(endpoints_, id)); |
129 Endpoint* endpoint = endpoints_[id].get(); | 170 Endpoint* endpoint = endpoints_[id].get(); |
130 DCHECK(!endpoint->client()); | 171 DCHECK(!endpoint->client()); |
131 DCHECK(!endpoint->closed()); | 172 DCHECK(!endpoint->closed()); |
132 MarkClosedAndMaybeRemove(endpoint); | 173 MarkClosedAndMaybeRemove(endpoint); |
133 | 174 |
134 if (!mojo::IsMasterInterfaceId(id)) | 175 if (!mojo::IsMasterInterfaceId(id)) |
135 NotifyPeerEndpointClosed(id); | 176 control_message_proxy_.NotifyPeerEndpointClosed(id); |
136 } | 177 } |
137 | 178 |
138 mojo::InterfaceEndpointController* AttachEndpointClient( | 179 mojo::InterfaceEndpointController* AttachEndpointClient( |
139 const mojo::ScopedInterfaceEndpointHandle& handle, | 180 const mojo::ScopedInterfaceEndpointHandle& handle, |
140 mojo::InterfaceEndpointClient* client, | 181 mojo::InterfaceEndpointClient* client, |
141 scoped_refptr<base::SingleThreadTaskRunner> runner) override { | 182 scoped_refptr<base::SingleThreadTaskRunner> runner) override { |
142 const mojo::InterfaceId id = handle.id(); | 183 const mojo::InterfaceId id = handle.id(); |
143 | 184 |
144 DCHECK(mojo::IsValidInterfaceId(id)); | 185 DCHECK(mojo::IsValidInterfaceId(id)); |
145 DCHECK(client); | 186 DCHECK(client); |
(...skipping 18 matching lines...) Expand all Loading... | |
164 | 205 |
165 base::AutoLock locker(lock_); | 206 base::AutoLock locker(lock_); |
166 DCHECK(ContainsKey(endpoints_, id)); | 207 DCHECK(ContainsKey(endpoints_, id)); |
167 | 208 |
168 Endpoint* endpoint = endpoints_[id].get(); | 209 Endpoint* endpoint = endpoints_[id].get(); |
169 endpoint->DetachClient(); | 210 endpoint->DetachClient(); |
170 } | 211 } |
171 | 212 |
172 void RaiseError() override { | 213 void RaiseError() override { |
173 if (task_runner_->BelongsToCurrentThread()) { | 214 if (task_runner_->BelongsToCurrentThread()) { |
174 connector_.RaiseError(); | 215 connector_->RaiseError(); |
175 } else { | 216 } else { |
176 task_runner_->PostTask( | 217 task_runner_->PostTask( |
177 FROM_HERE, | 218 FROM_HERE, |
178 base::Bind(&ChannelAssociatedGroupController::RaiseError, this)); | 219 base::Bind(&ChannelAssociatedGroupController::RaiseError, this)); |
179 } | 220 } |
180 } | 221 } |
181 | 222 |
182 private: | 223 private: |
183 class Endpoint; | 224 class Endpoint; |
225 class ControlMessageProxyThunk; | |
184 friend class Endpoint; | 226 friend class Endpoint; |
227 friend class ControlMessageProxyThunk; | |
185 | 228 |
186 class Endpoint : public base::RefCountedThreadSafe<Endpoint>, | 229 class Endpoint : public base::RefCountedThreadSafe<Endpoint>, |
187 public mojo::InterfaceEndpointController { | 230 public mojo::InterfaceEndpointController { |
188 public: | 231 public: |
189 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id) | 232 Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id) |
190 : controller_(controller), id_(id) {} | 233 : controller_(controller), id_(id) {} |
191 | 234 |
192 mojo::InterfaceId id() const { return id_; } | 235 mojo::InterfaceId id() const { return id_; } |
193 | 236 |
194 bool closed() const { | 237 bool closed() const { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 const mojo::InterfaceId id_; | 320 const mojo::InterfaceId id_; |
278 | 321 |
279 bool closed_ = false; | 322 bool closed_ = false; |
280 bool peer_closed_ = false; | 323 bool peer_closed_ = false; |
281 mojo::InterfaceEndpointClient* client_ = nullptr; | 324 mojo::InterfaceEndpointClient* client_ = nullptr; |
282 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 325 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
283 | 326 |
284 DISALLOW_COPY_AND_ASSIGN(Endpoint); | 327 DISALLOW_COPY_AND_ASSIGN(Endpoint); |
285 }; | 328 }; |
286 | 329 |
330 class ControlMessageProxyThunk : public MessageReceiver { | |
331 public: | |
332 explicit ControlMessageProxyThunk( | |
333 ChannelAssociatedGroupController* controller) | |
334 : controller_(controller) {} | |
335 | |
336 private: | |
337 // MessageReceiver: | |
338 bool Accept(mojo::Message* message) override { | |
339 return controller_->SendMessage(message); | |
340 } | |
341 | |
342 ChannelAssociatedGroupController* controller_; | |
343 | |
344 DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk); | |
345 }; | |
346 | |
287 ~ChannelAssociatedGroupController() override { | 347 ~ChannelAssociatedGroupController() override { |
288 base::AutoLock locker(lock_); | 348 base::AutoLock locker(lock_); |
289 | |
290 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { | 349 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { |
291 Endpoint* endpoint = iter->second.get(); | 350 Endpoint* endpoint = iter->second.get(); |
292 ++iter; | 351 ++iter; |
293 | 352 |
294 DCHECK(endpoint->closed()); | 353 DCHECK(endpoint->closed()); |
295 MarkPeerClosedAndMaybeRemove(endpoint); | 354 MarkPeerClosedAndMaybeRemove(endpoint); |
296 } | 355 } |
297 | 356 |
298 DCHECK(endpoints_.empty()); | 357 DCHECK(endpoints_.empty()); |
299 } | 358 } |
300 | 359 |
301 bool SendMessage(mojo::Message* message) { | 360 bool SendMessage(mojo::Message* message) { |
302 if (task_runner_->BelongsToCurrentThread()) { | 361 if (task_runner_->BelongsToCurrentThread()) { |
303 DCHECK(thread_checker_.CalledOnValidThread()); | 362 DCHECK(thread_checker_.CalledOnValidThread()); |
304 return connector_.Accept(message); | 363 if (!connector_) { |
364 // Pipe may not be bound yet, so we queue the message. | |
365 std::unique_ptr<mojo::Message> queued_message(new mojo::Message); | |
366 message->MoveTo(queued_message.get()); | |
367 outgoing_messages_.emplace_back(std::move(queued_message)); | |
368 return true; | |
369 } | |
370 return connector_->Accept(message); | |
305 } else { | 371 } else { |
306 // We always post tasks to the master endpoint thread when called from the | 372 // We always post tasks to the master endpoint thread when called from the |
307 // proxy thread in order to simulate IPC::ChannelProxy::Send behavior. | 373 // proxy thread in order to simulate IPC::ChannelProxy::Send behavior. |
308 DCHECK(proxy_task_runner_ && | 374 DCHECK(proxy_task_runner_ && |
309 proxy_task_runner_->BelongsToCurrentThread()); | 375 proxy_task_runner_->BelongsToCurrentThread()); |
310 std::unique_ptr<mojo::Message> passed_message(new mojo::Message); | 376 std::unique_ptr<mojo::Message> passed_message(new mojo::Message); |
311 message->MoveTo(passed_message.get()); | 377 message->MoveTo(passed_message.get()); |
312 task_runner_->PostTask( | 378 task_runner_->PostTask( |
313 FROM_HERE, | 379 FROM_HERE, |
314 base::Bind( | 380 base::Bind( |
(...skipping 24 matching lines...) Expand all Loading... | |
339 Endpoint* endpoint = iter->second.get(); | 405 Endpoint* endpoint = iter->second.get(); |
340 ++iter; | 406 ++iter; |
341 | 407 |
342 if (endpoint->client()) | 408 if (endpoint->client()) |
343 endpoints_to_notify.push_back(endpoint); | 409 endpoints_to_notify.push_back(endpoint); |
344 | 410 |
345 MarkPeerClosedAndMaybeRemove(endpoint); | 411 MarkPeerClosedAndMaybeRemove(endpoint); |
346 } | 412 } |
347 | 413 |
348 for (auto& endpoint : endpoints_to_notify) { | 414 for (auto& endpoint : endpoints_to_notify) { |
349 // Because an notification may in turn detach any endpoint, we have to | 415 // Because a notification may in turn detach any endpoint, we have to |
350 // check each client again here. | 416 // check each client again here. |
351 if (endpoint->client()) | 417 if (endpoint->client()) |
352 NotifyEndpointOfError(endpoint.get(), false /* force_async */); | 418 NotifyEndpointOfError(endpoint.get(), false /* force_async */); |
353 } | 419 } |
354 } | 420 } |
355 | 421 |
356 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) { | 422 void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) { |
357 lock_.AssertAcquired(); | 423 lock_.AssertAcquired(); |
358 DCHECK(endpoint->task_runner() && endpoint->client()); | 424 DCHECK(endpoint->task_runner() && endpoint->client()); |
359 if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) { | 425 if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) { |
(...skipping 25 matching lines...) Expand all Loading... | |
385 endpoints_.erase(endpoint->id()); | 451 endpoints_.erase(endpoint->id()); |
386 } | 452 } |
387 | 453 |
388 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) { | 454 void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) { |
389 lock_.AssertAcquired(); | 455 lock_.AssertAcquired(); |
390 endpoint->set_peer_closed(); | 456 endpoint->set_peer_closed(); |
391 if (endpoint->closed() && endpoint->peer_closed()) | 457 if (endpoint->closed() && endpoint->peer_closed()) |
392 endpoints_.erase(endpoint->id()); | 458 endpoints_.erase(endpoint->id()); |
393 } | 459 } |
394 | 460 |
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) { | 461 Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) { |
420 lock_.AssertAcquired(); | 462 lock_.AssertAcquired(); |
421 DCHECK(!inserted || !*inserted); | 463 DCHECK(!inserted || !*inserted); |
422 | 464 |
423 auto iter = endpoints_.find(id); | 465 auto iter = endpoints_.find(id); |
424 if (iter != endpoints_.end()) | 466 if (iter != endpoints_.end()) |
425 return iter->second.get(); | 467 return iter->second.get(); |
426 | 468 |
427 Endpoint* endpoint = new Endpoint(this, id); | 469 Endpoint* endpoint = new Endpoint(this, id); |
428 endpoints_.insert({ id, endpoint }); | 470 endpoints_.insert({ id, endpoint }); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
503 RaiseError(); | 545 RaiseError(); |
504 } | 546 } |
505 | 547 |
506 Endpoint* GetEndpointForDispatch(mojo::InterfaceId id) { | 548 Endpoint* GetEndpointForDispatch(mojo::InterfaceId id) { |
507 lock_.AssertAcquired(); | 549 lock_.AssertAcquired(); |
508 bool inserted = false; | 550 bool inserted = false; |
509 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted); | 551 Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted); |
510 if (inserted) { | 552 if (inserted) { |
511 MarkClosedAndMaybeRemove(endpoint); | 553 MarkClosedAndMaybeRemove(endpoint); |
512 if (!mojo::IsMasterInterfaceId(id)) | 554 if (!mojo::IsMasterInterfaceId(id)) |
513 NotifyPeerEndpointClosed(id); | 555 control_message_proxy_.NotifyPeerEndpointClosed(id); |
514 return nullptr; | 556 return nullptr; |
515 } | 557 } |
516 | 558 |
517 if (endpoint->closed()) | 559 if (endpoint->closed()) |
518 return nullptr; | 560 return nullptr; |
519 | 561 |
520 return endpoint; | 562 return endpoint; |
521 } | 563 } |
522 | 564 |
523 // mojo::PipeControlMessageHandlerDelegate: | 565 // mojo::PipeControlMessageHandlerDelegate: |
(...skipping 26 matching lines...) Expand all Loading... | |
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::AssociatedGroup> associated_group_; |
562 mojo::Connector connector_; | 604 std::unique_ptr<mojo::Connector> connector_; |
563 mojo::MessageHeaderValidator header_validator_; | 605 mojo::MessageHeaderValidator header_validator_; |
564 mojo::PipeControlMessageHandler control_message_handler_; | 606 mojo::PipeControlMessageHandler control_message_handler_; |
607 ControlMessageProxyThunk control_message_proxy_thunk_; | |
608 mojo::PipeControlMessageProxy control_message_proxy_; | |
609 | |
610 // Outgoing messages that were sent before this controller was bound to a | |
611 // real message pipe. | |
612 std::vector<std::unique_ptr<mojo::Message>> outgoing_messages_; | |
565 | 613 |
566 // Guards the fields below for thread-safe access. | 614 // Guards the fields below for thread-safe access. |
567 base::Lock lock_; | 615 base::Lock lock_; |
568 | 616 |
569 bool encountered_error_ = false; | 617 bool encountered_error_ = false; |
570 uint32_t next_interface_id_ = 1; | 618 |
619 // ID #1 is reserved for the mojom::Channel interface. | |
620 uint32_t next_interface_id_ = 2; | |
621 | |
571 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_; | 622 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_; |
572 mojo::PipeControlMessageProxy control_message_proxy_; | |
573 | 623 |
574 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController); | 624 DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController); |
575 }; | 625 }; |
576 | 626 |
577 class BootstrapMasterProxy { | 627 class MojoBootstrapImpl : public MojoBootstrap, |
628 public mojo::MessageReceiverWithResponderStatus { | |
578 public: | 629 public: |
579 BootstrapMasterProxy() {} | 630 MojoBootstrapImpl( |
580 ~BootstrapMasterProxy() { | 631 mojo::ScopedMessagePipeHandle handle, |
581 endpoint_client_.reset(); | 632 Delegate* delegate, |
582 proxy_.reset(); | 633 const scoped_refptr<ChannelAssociatedGroupController> controller) |
583 if (controller_) | 634 : controller_(controller), |
584 controller_->ShutDown(); | 635 handle_(std::move(handle)), |
636 delegate_(delegate) {} | |
637 | |
638 ~MojoBootstrapImpl() override { controller_->ShutDown(); } | |
639 | |
640 private: | |
641 // MojoBootstrap: | |
642 void Connect() override { | |
643 controller_->Bind(std::move(handle_)); | |
644 | |
645 IPC::mojom::ChannelAssociatedPtr sender; | |
646 IPC::mojom::ChannelAssociatedRequest receiver; | |
647 controller_->CreateChannelEndpoints(&sender, &receiver); | |
648 | |
649 delegate_->OnPipesAvailable(std::move(sender), std::move(receiver)); | |
585 } | 650 } |
586 | 651 |
587 void Bind(mojo::ScopedMessagePipeHandle handle) { | 652 mojo::AssociatedGroup* GetAssociatedGroup() override { |
588 DCHECK(!controller_); | |
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(); | 653 return controller_->associated_group(); |
607 } | 654 } |
608 | 655 |
609 ChannelAssociatedGroupController* controller() { | 656 // mojo::MessageReceiverWithResponderStatus: |
yzshen1
2016/07/20 17:13:15
What is this interface used for ?
Ken Rockot(use gerrit already)
2016/07/20 21:08:39
Nothing! It was used when I still had an Interface
| |
610 DCHECK(controller_); | 657 bool Accept(mojo::Message* message) override { |
611 return controller_.get(); | 658 NOTREACHED(); |
659 return false; | |
612 } | 660 } |
613 | 661 |
614 mojom::Bootstrap* operator->() { | 662 bool AcceptWithResponder( |
615 DCHECK(proxy_); | 663 mojo::Message* message, |
616 return proxy_.get(); | 664 mojo::MessageReceiverWithStatus* responder) override { |
665 NOTREACHED(); | |
666 return false; | |
617 } | 667 } |
618 | 668 |
619 private: | |
620 std::unique_ptr<mojom::BootstrapProxy> proxy_; | |
621 scoped_refptr<ChannelAssociatedGroupController> controller_; | 669 scoped_refptr<ChannelAssociatedGroupController> controller_; |
622 std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_; | |
623 | 670 |
624 DISALLOW_COPY_AND_ASSIGN(BootstrapMasterProxy); | 671 mojo::ScopedMessagePipeHandle handle_; |
672 Delegate* delegate_; | |
673 | |
674 DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl); | |
625 }; | 675 }; |
626 | 676 |
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 | 677 } // namespace |
793 | 678 |
794 // MojoBootstrap | |
795 | |
796 // static | 679 // static |
797 std::unique_ptr<MojoBootstrap> MojoBootstrap::Create( | 680 std::unique_ptr<MojoBootstrap> MojoBootstrap::Create( |
798 mojo::ScopedMessagePipeHandle handle, | 681 mojo::ScopedMessagePipeHandle handle, |
799 Channel::Mode mode, | 682 Channel::Mode mode, |
800 Delegate* delegate) { | 683 Delegate* delegate, |
801 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER); | 684 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) { |
802 std::unique_ptr<MojoBootstrap> self = | 685 return base::MakeUnique<MojoBootstrapImpl>( |
803 mode == Channel::MODE_CLIENT | 686 std::move(handle), delegate, |
804 ? std::unique_ptr<MojoBootstrap>(new MojoClientBootstrap) | 687 new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER, |
805 : std::unique_ptr<MojoBootstrap>(new MojoServerBootstrap); | 688 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 } | 689 } |
846 | 690 |
847 } // namespace IPC | 691 } // namespace IPC |
OLD | NEW |