| Index: ipc/ipc_mojo_bootstrap.cc
|
| diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
|
| index fc39d0d919e8b0a7dae947585d8abd6c93c4d87a..a21720b7d5c61cab0eddc717d5986c28d62af336 100644
|
| --- a/ipc/ipc_mojo_bootstrap.cc
|
| +++ b/ipc/ipc_mojo_bootstrap.cc
|
| @@ -9,12 +9,12 @@
|
| #include <map>
|
| #include <memory>
|
| #include <utility>
|
| +#include <vector>
|
|
|
| #include "base/callback.h"
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| #include "base/memory/ptr_util.h"
|
| -#include "base/process/process_handle.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/stl_util.h"
|
| #include "base/synchronization/lock.h"
|
| @@ -29,6 +29,7 @@
|
| #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
|
| #include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
|
| #include "mojo/public/cpp/bindings/interface_id.h"
|
| +#include "mojo/public/cpp/bindings/message.h"
|
| #include "mojo/public/cpp/bindings/message_header_validator.h"
|
| #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
|
| #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
|
| @@ -43,39 +44,74 @@ class ChannelAssociatedGroupController
|
| public mojo::MessageReceiver,
|
| public mojo::PipeControlMessageHandlerDelegate {
|
| public:
|
| - ChannelAssociatedGroupController(bool set_interface_id_namespace_bit,
|
| - mojo::ScopedMessagePipeHandle handle)
|
| + ChannelAssociatedGroupController(
|
| + bool set_interface_id_namespace_bit,
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
|
| : mojo::AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()),
|
| - task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| - id_namespace_mask_(set_interface_id_namespace_bit ?
|
| - mojo::kInterfaceIdNamespaceMask : 0),
|
| - associated_group_(CreateAssociatedGroup()),
|
| - connector_(std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
|
| - base::ThreadTaskRunnerHandle::Get()),
|
| + task_runner_(ipc_task_runner),
|
| + proxy_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
|
| header_validator_(
|
| "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this),
|
| control_message_handler_(this),
|
| - control_message_proxy_(&connector_) {
|
| - connector_.set_incoming_receiver(&header_validator_);
|
| - connector_.set_connection_error_handler(
|
| - base::Bind(&ChannelAssociatedGroupController::OnPipeError,
|
| - base::Unretained(this)));
|
| + control_message_proxy_thunk_(this),
|
| + control_message_proxy_(&control_message_proxy_thunk_) {
|
| + thread_checker_.DetachFromThread();
|
| control_message_handler_.SetDescription(
|
| "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
|
| }
|
|
|
| - mojo::AssociatedGroup* associated_group() { return associated_group_.get(); }
|
| + void Bind(mojo::ScopedMessagePipeHandle handle) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(task_runner_->BelongsToCurrentThread());
|
| + thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| + connector_.reset(new mojo::Connector(
|
| + std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
|
| + task_runner_));
|
| + connector_->set_incoming_receiver(&header_validator_);
|
| + connector_->set_connection_error_handler(
|
| + base::Bind(&ChannelAssociatedGroupController::OnPipeError,
|
| + base::Unretained(this)));
|
| +
|
| + std::vector<std::unique_ptr<mojo::Message>> outgoing_messages;
|
| + std::swap(outgoing_messages, outgoing_messages_);
|
| + for (auto& message : outgoing_messages)
|
| + SendMessage(message.get());
|
| + }
|
| +
|
| + void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
|
| + mojom::ChannelAssociatedRequest* receiver) {
|
| + mojo::InterfaceId sender_id, receiver_id;
|
| + if (set_interface_id_namespace_bit_) {
|
| + sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
|
| + receiver_id = 1;
|
| + } else {
|
| + sender_id = 1;
|
| + receiver_id = 1 | mojo::kInterfaceIdNamespaceMask;
|
| + }
|
| +
|
| + {
|
| + base::AutoLock locker(lock_);
|
| + Endpoint* sender_endpoint = new Endpoint(this, sender_id);
|
| + Endpoint* receiver_endpoint = new Endpoint(this, receiver_id);
|
| + endpoints_.insert({ sender_id, sender_endpoint });
|
| + endpoints_.insert({ receiver_id, receiver_endpoint });
|
| + }
|
| +
|
| + mojo::ScopedInterfaceEndpointHandle sender_handle =
|
| + CreateScopedInterfaceEndpointHandle(sender_id, true);
|
| + mojo::ScopedInterfaceEndpointHandle receiver_handle =
|
| + CreateScopedInterfaceEndpointHandle(receiver_id, true);
|
| +
|
| + sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
|
| + receiver->Bind(std::move(receiver_handle));
|
| + }
|
|
|
| void ShutDown() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - connector_.CloseMessagePipe();
|
| + connector_->CloseMessagePipe();
|
| OnPipeError();
|
| - associated_group_.reset();
|
| - }
|
| -
|
| - void SetProxyTaskRunner(
|
| - scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner) {
|
| - proxy_task_runner_ = proxy_task_runner;
|
| + connector_.reset();
|
| }
|
|
|
| // mojo::AssociatedGroupController:
|
| @@ -86,8 +122,10 @@ class ChannelAssociatedGroupController
|
| uint32_t id = 0;
|
| do {
|
| if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask)
|
| - next_interface_id_ = 1;
|
| - id = (next_interface_id_++) | id_namespace_mask_;
|
| + next_interface_id_ = 2;
|
| + id = next_interface_id_++;
|
| + if (set_interface_id_namespace_bit_)
|
| + id |= mojo::kInterfaceIdNamespaceMask;
|
| } while (ContainsKey(endpoints_, id));
|
|
|
| Endpoint* endpoint = new Endpoint(this, id);
|
| @@ -121,7 +159,7 @@ class ChannelAssociatedGroupController
|
| if (!is_local) {
|
| DCHECK(ContainsKey(endpoints_, id));
|
| DCHECK(!mojo::IsMasterInterfaceId(id));
|
| - NotifyEndpointClosedBeforeSent(id);
|
| + control_message_proxy_.NotifyEndpointClosedBeforeSent(id);
|
| return;
|
| }
|
|
|
| @@ -132,7 +170,7 @@ class ChannelAssociatedGroupController
|
| MarkClosedAndMaybeRemove(endpoint);
|
|
|
| if (!mojo::IsMasterInterfaceId(id))
|
| - NotifyPeerEndpointClosed(id);
|
| + control_message_proxy_.NotifyPeerEndpointClosed(id);
|
| }
|
|
|
| mojo::InterfaceEndpointController* AttachEndpointClient(
|
| @@ -170,8 +208,8 @@ class ChannelAssociatedGroupController
|
| }
|
|
|
| void RaiseError() override {
|
| - if (task_runner_->BelongsToCurrentThread()) {
|
| - connector_.RaiseError();
|
| + if (IsRunningOnIPCThread()) {
|
| + connector_->RaiseError();
|
| } else {
|
| task_runner_->PostTask(
|
| FROM_HERE,
|
| @@ -181,7 +219,9 @@ class ChannelAssociatedGroupController
|
|
|
| private:
|
| class Endpoint;
|
| + class ControlMessageProxyThunk;
|
| friend class Endpoint;
|
| + friend class ControlMessageProxyThunk;
|
|
|
| class Endpoint : public base::RefCountedThreadSafe<Endpoint>,
|
| public mojo::InterfaceEndpointController {
|
| @@ -260,7 +300,7 @@ class ChannelAssociatedGroupController
|
|
|
| // It's not legal to make sync calls from the master endpoint's thread,
|
| // and in fact they must only happen from the proxy task runner.
|
| - DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
|
| + DCHECK(!controller_->IsRunningOnIPCThread());
|
| DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
|
|
|
| // TODO(rockot): Implement sync waiting.
|
| @@ -284,9 +324,25 @@ class ChannelAssociatedGroupController
|
| DISALLOW_COPY_AND_ASSIGN(Endpoint);
|
| };
|
|
|
| + class ControlMessageProxyThunk : public MessageReceiver {
|
| + public:
|
| + explicit ControlMessageProxyThunk(
|
| + ChannelAssociatedGroupController* controller)
|
| + : controller_(controller) {}
|
| +
|
| + private:
|
| + // MessageReceiver:
|
| + bool Accept(mojo::Message* message) override {
|
| + return controller_->SendMessage(message);
|
| + }
|
| +
|
| + ChannelAssociatedGroupController* controller_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ControlMessageProxyThunk);
|
| + };
|
| +
|
| ~ChannelAssociatedGroupController() override {
|
| base::AutoLock locker(lock_);
|
| -
|
| for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
|
| Endpoint* endpoint = iter->second.get();
|
| ++iter;
|
| @@ -298,15 +354,30 @@ class ChannelAssociatedGroupController
|
| DCHECK(endpoints_.empty());
|
| }
|
|
|
| + bool IsRunningOnIPCThread() {
|
| + // |task_runner_| is always non-null but may incorrectly report that
|
| + // BelongsToCurrentThread() == false during shutdown. By the time shutdown
|
| + // occurs, |thread_task_runner_| will be non-null and is guaranteed to run
|
| + // tasks on the same thread as |task_runner_|.
|
| + return task_runner_->BelongsToCurrentThread() ||
|
| + (thread_task_runner_ && thread_task_runner_->BelongsToCurrentThread());
|
| + }
|
| +
|
| bool SendMessage(mojo::Message* message) {
|
| - if (task_runner_->BelongsToCurrentThread()) {
|
| + if (IsRunningOnIPCThread()) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - return connector_.Accept(message);
|
| + if (!connector_) {
|
| + // Pipe may not be bound yet, so we queue the message.
|
| + std::unique_ptr<mojo::Message> queued_message(new mojo::Message);
|
| + message->MoveTo(queued_message.get());
|
| + outgoing_messages_.emplace_back(std::move(queued_message));
|
| + return true;
|
| + }
|
| + return connector_->Accept(message);
|
| } else {
|
| // We always post tasks to the master endpoint thread when called from the
|
| // proxy thread in order to simulate IPC::ChannelProxy::Send behavior.
|
| - DCHECK(proxy_task_runner_ &&
|
| - proxy_task_runner_->BelongsToCurrentThread());
|
| + DCHECK(proxy_task_runner_->BelongsToCurrentThread());
|
| std::unique_ptr<mojo::Message> passed_message(new mojo::Message);
|
| message->MoveTo(passed_message.get());
|
| task_runner_->PostTask(
|
| @@ -346,7 +417,7 @@ class ChannelAssociatedGroupController
|
| }
|
|
|
| for (auto& endpoint : endpoints_to_notify) {
|
| - // Because an notification may in turn detach any endpoint, we have to
|
| + // Because a notification may in turn detach any endpoint, we have to
|
| // check each client again here.
|
| if (endpoint->client())
|
| NotifyEndpointOfError(endpoint.get(), false /* force_async */);
|
| @@ -392,30 +463,6 @@ class ChannelAssociatedGroupController
|
| endpoints_.erase(endpoint->id());
|
| }
|
|
|
| - void NotifyPeerEndpointClosed(mojo::InterfaceId id) {
|
| - if (task_runner_->BelongsToCurrentThread()) {
|
| - if (connector_.is_valid())
|
| - control_message_proxy_.NotifyPeerEndpointClosed(id);
|
| - } else {
|
| - task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ChannelAssociatedGroupController
|
| - ::NotifyPeerEndpointClosed, this, id));
|
| - }
|
| - }
|
| -
|
| - void NotifyEndpointClosedBeforeSent(mojo::InterfaceId id) {
|
| - if (task_runner_->BelongsToCurrentThread()) {
|
| - if (connector_.is_valid())
|
| - control_message_proxy_.NotifyEndpointClosedBeforeSent(id);
|
| - } else {
|
| - task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ChannelAssociatedGroupController
|
| - ::NotifyEndpointClosedBeforeSent, this, id));
|
| - }
|
| - }
|
| -
|
| Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
|
| lock_.AssertAcquired();
|
| DCHECK(!inserted || !*inserted);
|
| @@ -510,7 +557,7 @@ class ChannelAssociatedGroupController
|
| if (inserted) {
|
| MarkClosedAndMaybeRemove(endpoint);
|
| if (!mojo::IsMasterInterfaceId(id))
|
| - NotifyPeerEndpointClosed(id);
|
| + control_message_proxy_.NotifyPeerEndpointClosed(id);
|
| return nullptr;
|
| }
|
|
|
| @@ -527,6 +574,7 @@ class ChannelAssociatedGroupController
|
| if (mojo::IsMasterInterfaceId(id))
|
| return false;
|
|
|
| + scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
|
| base::AutoLock locker(lock_);
|
| scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr);
|
| if (!endpoint->peer_closed()) {
|
| @@ -556,292 +604,92 @@ class ChannelAssociatedGroupController
|
| base::ThreadChecker thread_checker_;
|
|
|
| scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| +
|
| + // A TaskRunner that runs tasks on the same thread as |task_runner_| but which
|
| + // is used exclusively to do thread safety checking. This is an unfortunate
|
| + // consequence of bad interaction between some TaskRunner implementations and
|
| + // MessageLoop destruction which may cause the user-provided |task_runner_| to
|
| + // incorrectly report that BelongsToCurrentThread() == false during shutdown.
|
| + scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
|
| +
|
| scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
|
| - const uint32_t id_namespace_mask_;
|
| - std::unique_ptr<mojo::AssociatedGroup> associated_group_;
|
| - mojo::Connector connector_;
|
| + const bool set_interface_id_namespace_bit_;
|
| + std::unique_ptr<mojo::Connector> connector_;
|
| mojo::MessageHeaderValidator header_validator_;
|
| mojo::PipeControlMessageHandler control_message_handler_;
|
| + ControlMessageProxyThunk control_message_proxy_thunk_;
|
| + mojo::PipeControlMessageProxy control_message_proxy_;
|
| +
|
| + // Outgoing messages that were sent before this controller was bound to a
|
| + // real message pipe.
|
| + std::vector<std::unique_ptr<mojo::Message>> outgoing_messages_;
|
|
|
| // Guards the fields below for thread-safe access.
|
| base::Lock lock_;
|
|
|
| bool encountered_error_ = false;
|
| - uint32_t next_interface_id_ = 1;
|
| - std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
|
| - mojo::PipeControlMessageProxy control_message_proxy_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
|
| -};
|
| -
|
| -class BootstrapMasterProxy {
|
| - public:
|
| - BootstrapMasterProxy() {}
|
| - ~BootstrapMasterProxy() {
|
| - endpoint_client_.reset();
|
| - proxy_.reset();
|
| - if (controller_)
|
| - controller_->ShutDown();
|
| - }
|
| -
|
| - void Bind(mojo::ScopedMessagePipeHandle handle) {
|
| - DCHECK(!controller_);
|
| - controller_ = new ChannelAssociatedGroupController(true, std::move(handle));
|
| - endpoint_client_.reset(new mojo::InterfaceEndpointClient(
|
| - controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId),
|
| - nullptr,
|
| - base::MakeUnique<typename mojom::Bootstrap::ResponseValidator_>(),
|
| - false, base::ThreadTaskRunnerHandle::Get()));
|
| - proxy_.reset(new mojom::BootstrapProxy(endpoint_client_.get()));
|
| - proxy_->serialization_context()->group_controller = controller_;
|
| - }
|
| -
|
| - void set_connection_error_handler(const base::Closure& handler) {
|
| - DCHECK(endpoint_client_);
|
| - endpoint_client_->set_connection_error_handler(handler);
|
| - }
|
| -
|
| - mojo::AssociatedGroup* associated_group() {
|
| - DCHECK(controller_);
|
| - return controller_->associated_group();
|
| - }
|
|
|
| - ChannelAssociatedGroupController* controller() {
|
| - DCHECK(controller_);
|
| - return controller_.get();
|
| - }
|
| -
|
| - mojom::Bootstrap* operator->() {
|
| - DCHECK(proxy_);
|
| - return proxy_.get();
|
| - }
|
| + // ID #1 is reserved for the mojom::Channel interface.
|
| + uint32_t next_interface_id_ = 2;
|
|
|
| - private:
|
| - std::unique_ptr<mojom::BootstrapProxy> proxy_;
|
| - scoped_refptr<ChannelAssociatedGroupController> controller_;
|
| - std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_;
|
| + std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(BootstrapMasterProxy);
|
| + DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController);
|
| };
|
|
|
| -class BootstrapMasterBinding {
|
| +class MojoBootstrapImpl : public MojoBootstrap {
|
| public:
|
| - explicit BootstrapMasterBinding(mojom::Bootstrap* impl) {
|
| - stub_.set_sink(impl);
|
| - }
|
| -
|
| - ~BootstrapMasterBinding() {
|
| - endpoint_client_.reset();
|
| - if (controller_)
|
| - controller_->ShutDown();
|
| + MojoBootstrapImpl(
|
| + mojo::ScopedMessagePipeHandle handle,
|
| + Delegate* delegate,
|
| + const scoped_refptr<ChannelAssociatedGroupController> controller)
|
| + : controller_(controller),
|
| + handle_(std::move(handle)),
|
| + delegate_(delegate) {
|
| + associated_group_ = controller_->CreateAssociatedGroup();
|
| }
|
|
|
| - void set_connection_error_handler(const base::Closure& handler) {
|
| - DCHECK(endpoint_client_);
|
| - endpoint_client_->set_connection_error_handler(handler);
|
| + ~MojoBootstrapImpl() override {
|
| + controller_->ShutDown();
|
| }
|
|
|
| - mojo::AssociatedGroup* associated_group() {
|
| - DCHECK(controller_);
|
| - return controller_->associated_group();
|
| - }
|
| -
|
| - ChannelAssociatedGroupController* controller() {
|
| - DCHECK(controller_);
|
| - return controller_.get();
|
| - }
|
| -
|
| - void Bind(mojo::ScopedMessagePipeHandle handle) {
|
| - DCHECK(!controller_);
|
| - controller_ =
|
| - new ChannelAssociatedGroupController(false, std::move(handle));
|
| - stub_.serialization_context()->group_controller = controller_;
|
| -
|
| - endpoint_client_.reset(new mojo::InterfaceEndpointClient(
|
| - controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId),
|
| - &stub_,
|
| - base::MakeUnique<typename mojom::Bootstrap::RequestValidator_>(),
|
| - false, base::ThreadTaskRunnerHandle::Get()));
|
| - }
|
| -
|
| - private:
|
| - mojom::BootstrapStub stub_;
|
| - scoped_refptr<ChannelAssociatedGroupController> controller_;
|
| - std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(BootstrapMasterBinding);
|
| -};
|
| -
|
| -// MojoBootstrap for the server process. You should create the instance
|
| -// using MojoBootstrap::Create().
|
| -class MojoServerBootstrap : public MojoBootstrap {
|
| - public:
|
| - MojoServerBootstrap();
|
| -
|
| private:
|
| - // MojoBootstrap implementation.
|
| - void Connect() override;
|
| -
|
| - mojo::AssociatedGroup* GetAssociatedGroup() override {
|
| - return bootstrap_.associated_group();
|
| - }
|
| -
|
| - void SetProxyTaskRunner(
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
|
| - bootstrap_.controller()->SetProxyTaskRunner(task_runner);
|
| - }
|
| -
|
| - void OnInitDone(int32_t peer_pid);
|
| -
|
| - BootstrapMasterProxy bootstrap_;
|
| - IPC::mojom::ChannelAssociatedPtrInfo send_channel_;
|
| - IPC::mojom::ChannelAssociatedRequest receive_channel_request_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
|
| -};
|
| -
|
| -MojoServerBootstrap::MojoServerBootstrap() = default;
|
| -
|
| -void MojoServerBootstrap::Connect() {
|
| - DCHECK_EQ(state(), STATE_INITIALIZED);
|
| + // MojoBootstrap:
|
| + void Connect() override {
|
| + controller_->Bind(std::move(handle_));
|
|
|
| - bootstrap_.Bind(TakeHandle());
|
| - bootstrap_.set_connection_error_handler(
|
| - base::Bind(&MojoServerBootstrap::Fail, base::Unretained(this)));
|
| + IPC::mojom::ChannelAssociatedPtr sender;
|
| + IPC::mojom::ChannelAssociatedRequest receiver;
|
| + controller_->CreateChannelEndpoints(&sender, &receiver);
|
|
|
| - IPC::mojom::ChannelAssociatedRequest send_channel_request;
|
| - IPC::mojom::ChannelAssociatedPtrInfo receive_channel;
|
| -
|
| - bootstrap_.associated_group()->CreateAssociatedInterface(
|
| - mojo::AssociatedGroup::WILL_PASS_REQUEST, &send_channel_,
|
| - &send_channel_request);
|
| - bootstrap_.associated_group()->CreateAssociatedInterface(
|
| - mojo::AssociatedGroup::WILL_PASS_PTR, &receive_channel,
|
| - &receive_channel_request_);
|
| -
|
| - bootstrap_->Init(
|
| - std::move(send_channel_request), std::move(receive_channel),
|
| - GetSelfPID(),
|
| - base::Bind(&MojoServerBootstrap::OnInitDone, base::Unretained(this)));
|
| -
|
| - set_state(STATE_WAITING_ACK);
|
| -}
|
| -
|
| -void MojoServerBootstrap::OnInitDone(int32_t peer_pid) {
|
| - if (state() != STATE_WAITING_ACK) {
|
| - set_state(STATE_ERROR);
|
| - LOG(ERROR) << "Got inconsistent message from client.";
|
| - return;
|
| + delegate_->OnPipesAvailable(std::move(sender), std::move(receiver));
|
| }
|
|
|
| - set_state(STATE_READY);
|
| - bootstrap_.set_connection_error_handler(base::Closure());
|
| - delegate()->OnPipesAvailable(std::move(send_channel_),
|
| - std::move(receive_channel_request_), peer_pid);
|
| -}
|
| -
|
| -// MojoBootstrap for client processes. You should create the instance
|
| -// using MojoBootstrap::Create().
|
| -class MojoClientBootstrap : public MojoBootstrap, public mojom::Bootstrap {
|
| - public:
|
| - MojoClientBootstrap();
|
| -
|
| - private:
|
| - // MojoBootstrap implementation.
|
| - void Connect() override;
|
| -
|
| mojo::AssociatedGroup* GetAssociatedGroup() override {
|
| - return binding_.associated_group();
|
| - }
|
| -
|
| - void SetProxyTaskRunner(
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
|
| - binding_.controller()->SetProxyTaskRunner(task_runner);
|
| + return associated_group_.get();
|
| }
|
|
|
| - // mojom::Bootstrap implementation.
|
| - void Init(mojom::ChannelAssociatedRequest receive_channel,
|
| - mojom::ChannelAssociatedPtrInfo send_channel,
|
| - int32_t peer_pid,
|
| - const InitCallback& callback) override;
|
| + scoped_refptr<ChannelAssociatedGroupController> controller_;
|
|
|
| - BootstrapMasterBinding binding_;
|
| + mojo::ScopedMessagePipeHandle handle_;
|
| + Delegate* delegate_;
|
| + std::unique_ptr<mojo::AssociatedGroup> associated_group_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
|
| + DISALLOW_COPY_AND_ASSIGN(MojoBootstrapImpl);
|
| };
|
|
|
| -MojoClientBootstrap::MojoClientBootstrap() : binding_(this) {}
|
| -
|
| -void MojoClientBootstrap::Connect() {
|
| - binding_.Bind(TakeHandle());
|
| - binding_.set_connection_error_handler(
|
| - base::Bind(&MojoClientBootstrap::Fail, base::Unretained(this)));
|
| -}
|
| -
|
| -void MojoClientBootstrap::Init(mojom::ChannelAssociatedRequest receive_channel,
|
| - mojom::ChannelAssociatedPtrInfo send_channel,
|
| - int32_t peer_pid,
|
| - const InitCallback& callback) {
|
| - callback.Run(GetSelfPID());
|
| - set_state(STATE_READY);
|
| - binding_.set_connection_error_handler(base::Closure());
|
| - delegate()->OnPipesAvailable(std::move(send_channel),
|
| - std::move(receive_channel), peer_pid);
|
| -}
|
| -
|
| } // namespace
|
|
|
| -// MojoBootstrap
|
| -
|
| // static
|
| std::unique_ptr<MojoBootstrap> MojoBootstrap::Create(
|
| mojo::ScopedMessagePipeHandle handle,
|
| Channel::Mode mode,
|
| - Delegate* delegate) {
|
| - CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
|
| - std::unique_ptr<MojoBootstrap> self =
|
| - mode == Channel::MODE_CLIENT
|
| - ? std::unique_ptr<MojoBootstrap>(new MojoClientBootstrap)
|
| - : std::unique_ptr<MojoBootstrap>(new MojoServerBootstrap);
|
| -
|
| - self->Init(std::move(handle), delegate);
|
| - return self;
|
| -}
|
| -
|
| -MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
|
| -}
|
| -
|
| -MojoBootstrap::~MojoBootstrap() {}
|
| -
|
| -void MojoBootstrap::Init(mojo::ScopedMessagePipeHandle handle,
|
| - Delegate* delegate) {
|
| - handle_ = std::move(handle);
|
| - delegate_ = delegate;
|
| -}
|
| -
|
| -base::ProcessId MojoBootstrap::GetSelfPID() const {
|
| -#if defined(OS_LINUX)
|
| - if (int global_pid = Channel::GetGlobalPid())
|
| - return global_pid;
|
| -#endif // OS_LINUX
|
| -#if defined(OS_NACL)
|
| - return -1;
|
| -#else
|
| - return base::GetCurrentProcId();
|
| -#endif // defined(OS_NACL)
|
| -}
|
| -
|
| -void MojoBootstrap::Fail() {
|
| - set_state(STATE_ERROR);
|
| - delegate()->OnBootstrapError();
|
| -}
|
| -
|
| -bool MojoBootstrap::HasFailed() const {
|
| - return state() == STATE_ERROR;
|
| -}
|
| -
|
| -mojo::ScopedMessagePipeHandle MojoBootstrap::TakeHandle() {
|
| - return std::move(handle_);
|
| + Delegate* delegate,
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
|
| + return base::MakeUnique<MojoBootstrapImpl>(
|
| + std::move(handle), delegate,
|
| + new ChannelAssociatedGroupController(mode == Channel::MODE_SERVER,
|
| + ipc_task_runner));
|
| }
|
|
|
| } // namespace IPC
|
|
|