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

Unified Diff: third_party/mojo/src/mojo/edk/system/master_connection_manager.cc

Issue 1676913002: [mojo] Delete third_party/mojo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: let's try that again Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
deleted file mode 100644
index ced54ec069a1642a24abc562500d93dab69117cc..0000000000000000000000000000000000000000
--- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
+++ /dev/null
@@ -1,741 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/mojo/src/mojo/edk/system/master_connection_manager.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "mojo/public/cpp/system/macros.h"
-#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h"
-#include "third_party/mojo/src/mojo/edk/system/connection_manager_messages.h"
-#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h"
-#include "third_party/mojo/src/mojo/edk/system/raw_channel.h"
-#include "third_party/mojo/src/mojo/edk/system/transport_data.h"
-
-namespace mojo {
-namespace system {
-
-namespace {
-
-const ProcessIdentifier kFirstSlaveProcessIdentifier = 2;
-
-static_assert(kMasterProcessIdentifier != kInvalidProcessIdentifier,
- "Bad master process identifier");
-static_assert(kFirstSlaveProcessIdentifier != kInvalidProcessIdentifier,
- "Bad first slave process identifier");
-static_assert(kMasterProcessIdentifier != kFirstSlaveProcessIdentifier,
- "Master and first slave process identifiers are the same");
-
-MessageInTransit::Subtype ConnectionManagerResultToMessageInTransitSubtype(
- ConnectionManager::Result result) {
- switch (result) {
- case ConnectionManager::Result::FAILURE:
- return MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE;
- case ConnectionManager::Result::SUCCESS:
- return MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_SUCCESS;
- case ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS:
- return MessageInTransit::Subtype::
- CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_SAME_PROCESS;
- case ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION:
- return MessageInTransit::Subtype::
- CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_NEW_CONNECTION;
- case ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION:
- return MessageInTransit::Subtype::
- CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_REUSE_CONNECTION;
- }
- NOTREACHED();
- return MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE;
-}
-
-} // namespace
-
-// MasterConnectionManager::Helper ---------------------------------------------
-
-// |MasterConnectionManager::Helper| is not thread-safe, and must only be used
-// on its |owner_|'s private thread.
-class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::Helper final
- : public RawChannel::Delegate {
- public:
- Helper(MasterConnectionManager* owner,
- ProcessIdentifier process_identifier,
- embedder::SlaveInfo slave_info,
- embedder::ScopedPlatformHandle platform_handle);
- ~Helper() override;
-
- void Init();
- embedder::SlaveInfo Shutdown();
-
- private:
- // |RawChannel::Delegate| methods:
- void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) override;
- void OnError(Error error) override;
-
- // Handles an error that's fatal to this object. Note that this probably
- // results in |Shutdown()| being called (in the nested context) and then this
- // object being destroyed.
- void FatalError();
-
- MasterConnectionManager* const owner_;
- const ProcessIdentifier process_identifier_;
- embedder::SlaveInfo const slave_info_;
- scoped_ptr<RawChannel> raw_channel_;
-
- MOJO_DISALLOW_COPY_AND_ASSIGN(Helper);
-};
-
-MasterConnectionManager::Helper::Helper(
- MasterConnectionManager* owner,
- ProcessIdentifier process_identifier,
- embedder::SlaveInfo slave_info,
- embedder::ScopedPlatformHandle platform_handle)
- : owner_(owner),
- process_identifier_(process_identifier),
- slave_info_(slave_info),
- raw_channel_(RawChannel::Create(std::move(platform_handle))) {}
-
-MasterConnectionManager::Helper::~Helper() {
- DCHECK(!raw_channel_);
-}
-
-void MasterConnectionManager::Helper::Init() {
- raw_channel_->Init(this);
-}
-
-embedder::SlaveInfo MasterConnectionManager::Helper::Shutdown() {
- raw_channel_->Shutdown();
- raw_channel_.reset();
- return slave_info_;
-}
-
-void MasterConnectionManager::Helper::OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) {
- if (message_view.type() != MessageInTransit::Type::CONNECTION_MANAGER) {
- LOG(ERROR) << "Invalid message type " << message_view.type();
- FatalError(); // WARNING: This destroys us.
- return;
- }
-
- // Currently, all the messages simply have a |ConnectionIdentifier| as data.
- if (message_view.num_bytes() != sizeof(ConnectionIdentifier)) {
- LOG(ERROR) << "Invalid message size " << message_view.num_bytes();
- FatalError(); // WARNING: This destroys us.
- return;
- }
-
- // And none of them should have any platform handles attached.
- if (message_view.transport_data_buffer()) {
- LOG(ERROR) << "Invalid message with transport data";
- FatalError(); // WARNING: This destroys us.
- return;
- }
-
- const ConnectionIdentifier* connection_id =
- reinterpret_cast<const ConnectionIdentifier*>(message_view.bytes());
- Result result = Result::FAILURE;
- // Note: It's important to fully zero-initialize |data|, including padding,
- // since it'll be sent to another process.
- ConnectionManagerAckSuccessConnectData data = {};
- embedder::ScopedPlatformHandle platform_handle;
- uint32_t num_bytes = 0;
- const void* bytes = nullptr;
- switch (message_view.subtype()) {
- case MessageInTransit::Subtype::CONNECTION_MANAGER_ALLOW_CONNECT:
- result = owner_->AllowConnectImpl(process_identifier_, *connection_id)
- ? Result::SUCCESS
- : Result::FAILURE;
- break;
- case MessageInTransit::Subtype::CONNECTION_MANAGER_CANCEL_CONNECT:
- result = owner_->CancelConnectImpl(process_identifier_, *connection_id)
- ? Result::SUCCESS
- : Result::FAILURE;
- break;
- case MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT: {
- result = owner_->ConnectImpl(process_identifier_, *connection_id,
- &data.peer_process_identifier,
- &data.is_first, &platform_handle);
- DCHECK_NE(result, Result::SUCCESS);
- // Success acks for "connect" have the peer process identifier as data
- // (and also a platform handle in the case of "new connection" -- handled
- // further below).
- if (result != Result::FAILURE) {
- num_bytes = static_cast<uint32_t>(sizeof(data));
- bytes = &data;
- }
- break;
- }
- default:
- LOG(ERROR) << "Invalid message subtype " << message_view.subtype();
- FatalError(); // WARNING: This destroys us.
- return;
- }
-
- scoped_ptr<MessageInTransit> response(new MessageInTransit(
- MessageInTransit::Type::CONNECTION_MANAGER_ACK,
- ConnectionManagerResultToMessageInTransitSubtype(result), num_bytes,
- bytes));
-
- if (result == Result::SUCCESS_CONNECT_NEW_CONNECTION) {
- DCHECK_EQ(message_view.subtype(),
- MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT);
- DCHECK(platform_handle.is_valid());
- embedder::ScopedPlatformHandleVectorPtr platform_handles(
- new embedder::PlatformHandleVector());
- platform_handles->push_back(platform_handle.release());
- response->SetTransportData(make_scoped_ptr(
- new TransportData(std::move(platform_handles),
- raw_channel_->GetSerializedPlatformHandleSize())));
- } else {
- DCHECK(!platform_handle.is_valid());
- }
-
- if (!raw_channel_->WriteMessage(std::move(response))) {
- LOG(ERROR) << "WriteMessage failed";
- FatalError(); // WARNING: This destroys us.
- return;
- }
-}
-
-void MasterConnectionManager::Helper::OnError(Error /*error*/) {
- // Every error (read or write) is fatal (for that particular connection). Read
- // errors are fatal since no more commands will be received from that
- // connection. Write errors are fatal since it is no longer possible to send
- // responses.
- FatalError(); // WARNING: This destroys us.
-}
-
-void MasterConnectionManager::Helper::FatalError() {
- owner_->OnError(process_identifier_); // WARNING: This destroys us.
-}
-
-// MasterConnectionManager::PendingConnectInfo ---------------------------------
-
-struct MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::PendingConnectInfo {
- // States:
- // - This is created upon a first "allow connect" (with |first| set
- // immediately). We then wait for a second "allow connect".
- // - After the second "allow connect" (and |second| is set), we wait for
- // "connects" from both |first| and |second|.
- // - We may then receive "connect" from either |first| or |second|, at which
- // which point it remains to wait for "connect" from the other.
- // I.e., the valid state transitions are:
- // AWAITING_SECOND_ALLOW_CONNECT -> AWAITING_CONNECTS_FROM_BOTH
- // -> {AWAITING_CONNECT_FROM_FIRST,AWAITING_CONNECT_FROM_SECOND}
- enum class State {
- AWAITING_SECOND_ALLOW_CONNECT,
- AWAITING_CONNECTS_FROM_BOTH,
- AWAITING_CONNECT_FROM_FIRST,
- AWAITING_CONNECT_FROM_SECOND
- };
-
- explicit PendingConnectInfo(ProcessIdentifier first)
- : state(State::AWAITING_SECOND_ALLOW_CONNECT),
- first(first),
- second(kInvalidProcessIdentifier) {
- DCHECK_NE(first, kInvalidProcessIdentifier);
- }
- ~PendingConnectInfo() {}
-
- State state;
-
- ProcessIdentifier first;
- ProcessIdentifier second;
-};
-
-// MasterConnectionManager::ProcessConnections ---------------------------------
-
-class MasterConnectionManager::ProcessConnections {
- public:
- enum class ConnectionStatus { NONE, PENDING, RUNNING };
-
- ProcessConnections() {}
- ~ProcessConnections() {
- // TODO(vtl): Log a warning if there are connections pending? (This might be
- // very spammy, since the |MasterConnectionManager| may have many
- // |ProcessConnections|.
- for (auto& p : process_connections_)
- p.second.CloseIfNecessary();
- }
-
- // If |pending_platform_handle| is non-null and the status is |PENDING| this
- // will "return"/pass the stored pending platform handle. Warning: In that
- // case, this has the side effect of changing the state to |RUNNING|.
- ConnectionStatus GetConnectionStatus(
- ProcessIdentifier to_process_identifier,
- embedder::ScopedPlatformHandle* pending_platform_handle) {
- DCHECK(!pending_platform_handle || !pending_platform_handle->is_valid());
-
- auto it = process_connections_.find(to_process_identifier);
- if (it == process_connections_.end())
- return ConnectionStatus::NONE;
- if (!it->second.is_valid())
- return ConnectionStatus::RUNNING;
- // Pending:
- if (pending_platform_handle) {
- pending_platform_handle->reset(it->second);
- it->second = embedder::PlatformHandle();
- }
- return ConnectionStatus::PENDING;
- }
-
- void AddConnection(ProcessIdentifier to_process_identifier,
- ConnectionStatus status,
- embedder::ScopedPlatformHandle pending_platform_handle) {
- DCHECK(process_connections_.find(to_process_identifier) ==
- process_connections_.end());
-
- if (status == ConnectionStatus::RUNNING) {
- DCHECK(!pending_platform_handle.is_valid());
- process_connections_[to_process_identifier] = embedder::PlatformHandle();
- } else if (status == ConnectionStatus::PENDING) {
- DCHECK(pending_platform_handle.is_valid());
- process_connections_[to_process_identifier] =
- pending_platform_handle.release();
- } else {
- NOTREACHED();
- }
- }
-
- private:
- base::hash_map<ProcessIdentifier, embedder::PlatformHandle>
- process_connections_; // "Owns" any valid platform handles.
-
- MOJO_DISALLOW_COPY_AND_ASSIGN(ProcessConnections);
-};
-
-// MasterConnectionManager -----------------------------------------------------
-
-MasterConnectionManager::MasterConnectionManager(
- embedder::PlatformSupport* platform_support)
- : ConnectionManager(platform_support),
- master_process_delegate_(),
- private_thread_("MasterConnectionManagerPrivateThread"),
- next_process_identifier_(kFirstSlaveProcessIdentifier) {
- connections_[kMasterProcessIdentifier] = new ProcessConnections();
-}
-
-MasterConnectionManager::~MasterConnectionManager() {
- DCHECK(!delegate_thread_task_runner_);
- DCHECK(!master_process_delegate_);
- DCHECK(!private_thread_.message_loop());
- DCHECK(helpers_.empty());
- DCHECK(pending_connects_.empty());
-}
-
-void MasterConnectionManager::Init(
- embedder::MasterProcessDelegate* master_process_delegate) {
- DCHECK(master_process_delegate);
- DCHECK(!delegate_thread_task_runner_);
- DCHECK(!master_process_delegate_);
- DCHECK(!private_thread_.message_loop());
-
- delegate_thread_task_runner_ = base::MessageLoop::current()->task_runner();
- master_process_delegate_ = master_process_delegate;
- CHECK(private_thread_.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
-}
-
-ProcessIdentifier MasterConnectionManager::AddSlave(
- embedder::SlaveInfo slave_info,
- embedder::ScopedPlatformHandle platform_handle) {
- // We don't really care if |slave_info| is non-null or not.
- DCHECK(platform_handle.is_valid());
- AssertNotOnPrivateThread();
-
- ProcessIdentifier slave_process_identifier;
- {
- MutexLocker locker(&mutex_);
- CHECK_NE(next_process_identifier_, kMasterProcessIdentifier);
- slave_process_identifier = next_process_identifier_;
- next_process_identifier_++;
- DCHECK(connections_.find(slave_process_identifier) == connections_.end());
- connections_[slave_process_identifier] = new ProcessConnections();
- }
-
- // We have to wait for the task to be executed, in case someone calls
- // |AddSlave()| followed immediately by |Shutdown()|.
- base::WaitableEvent event(false, false);
- private_thread_.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&MasterConnectionManager::AddSlaveOnPrivateThread,
- base::Unretained(this), base::Unretained(slave_info),
- base::Passed(&platform_handle), slave_process_identifier,
- base::Unretained(&event)));
- event.Wait();
-
- return slave_process_identifier;
-}
-
-ProcessIdentifier MasterConnectionManager::AddSlaveAndBootstrap(
- embedder::SlaveInfo slave_info,
- embedder::ScopedPlatformHandle platform_handle,
- const ConnectionIdentifier& connection_id) {
- ProcessIdentifier slave_process_identifier =
- AddSlave(slave_info, std::move(platform_handle));
-
- MutexLocker locker(&mutex_);
- DCHECK(pending_connects_.find(connection_id) == pending_connects_.end());
- PendingConnectInfo* info = new PendingConnectInfo(kMasterProcessIdentifier);
- info->state = PendingConnectInfo::State::AWAITING_CONNECTS_FROM_BOTH;
- info->second = slave_process_identifier;
- pending_connects_[connection_id] = info;
-
- return slave_process_identifier;
-}
-
-void MasterConnectionManager::Shutdown() {
- AssertNotOnPrivateThread();
- DCHECK(master_process_delegate_);
- DCHECK(private_thread_.message_loop());
-
- // The |Stop()| will actually finish all posted tasks.
- private_thread_.message_loop()->PostTask(
- FROM_HERE, base::Bind(&MasterConnectionManager::ShutdownOnPrivateThread,
- base::Unretained(this)));
- private_thread_.Stop();
- DCHECK(helpers_.empty());
- DCHECK(pending_connects_.empty());
- master_process_delegate_ = nullptr;
- delegate_thread_task_runner_ = nullptr;
-}
-
-bool MasterConnectionManager::AllowConnect(
- const ConnectionIdentifier& connection_id) {
- AssertNotOnPrivateThread();
- return AllowConnectImpl(kMasterProcessIdentifier, connection_id);
-}
-
-bool MasterConnectionManager::CancelConnect(
- const ConnectionIdentifier& connection_id) {
- AssertNotOnPrivateThread();
- return CancelConnectImpl(kMasterProcessIdentifier, connection_id);
-}
-
-ConnectionManager::Result MasterConnectionManager::Connect(
- const ConnectionIdentifier& connection_id,
- ProcessIdentifier* peer_process_identifier,
- bool* is_first,
- embedder::ScopedPlatformHandle* platform_handle) {
- return ConnectImpl(kMasterProcessIdentifier, connection_id,
- peer_process_identifier, is_first, platform_handle);
-}
-
-bool MasterConnectionManager::AllowConnectImpl(
- ProcessIdentifier process_identifier,
- const ConnectionIdentifier& connection_id) {
- DCHECK_NE(process_identifier, kInvalidProcessIdentifier);
-
- MutexLocker locker(&mutex_);
-
- auto it = pending_connects_.find(connection_id);
- if (it == pending_connects_.end()) {
- pending_connects_[connection_id] =
- new PendingConnectInfo(process_identifier);
- // TODO(vtl): Track process identifier -> pending connections also (so these
- // can be removed efficiently if that process disconnects).
- DVLOG(1) << "New pending connection ID " << connection_id.ToString()
- << ": AllowConnect() from first process identifier "
- << process_identifier;
- return true;
- }
-
- PendingConnectInfo* info = it->second;
- if (info->state == PendingConnectInfo::State::AWAITING_SECOND_ALLOW_CONNECT) {
- info->state = PendingConnectInfo::State::AWAITING_CONNECTS_FROM_BOTH;
- info->second = process_identifier;
- DVLOG(1) << "Pending connection ID " << connection_id.ToString()
- << ": AllowConnect() from second process identifier "
- << process_identifier;
- return true;
- }
-
- // Someone's behaving badly, but we don't know who (it might not be the
- // caller).
- LOG(ERROR) << "AllowConnect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " already in state " << static_cast<int>(info->state);
- pending_connects_.erase(it);
- delete info;
- return false;
-}
-
-bool MasterConnectionManager::CancelConnectImpl(
- ProcessIdentifier process_identifier,
- const ConnectionIdentifier& connection_id) {
- DCHECK_NE(process_identifier, kInvalidProcessIdentifier);
-
- MutexLocker locker(&mutex_);
-
- auto it = pending_connects_.find(connection_id);
- if (it == pending_connects_.end()) {
- // Not necessarily the caller's fault, and not necessarily an error.
- DVLOG(1) << "CancelConnect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " which is not (or no longer) pending";
- return true;
- }
-
- PendingConnectInfo* info = it->second;
- if (process_identifier != info->first && process_identifier != info->second) {
- LOG(ERROR) << "CancelConnect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " which is neither connectee";
- return false;
- }
-
- // Just erase it. The other side may also try to cancel, in which case it'll
- // "fail" in the first if statement above (we assume that connection IDs never
- // collide, so there's no need to carefully track both sides).
- pending_connects_.erase(it);
- delete info;
- return true;
-}
-
-ConnectionManager::Result MasterConnectionManager::ConnectImpl(
- ProcessIdentifier process_identifier,
- const ConnectionIdentifier& connection_id,
- ProcessIdentifier* peer_process_identifier,
- bool* is_first,
- embedder::ScopedPlatformHandle* platform_handle) {
- DCHECK_NE(process_identifier, kInvalidProcessIdentifier);
- DCHECK(peer_process_identifier);
- DCHECK(is_first);
- DCHECK(platform_handle);
- DCHECK(!platform_handle->is_valid()); // Not technically wrong, but unlikely.
-
- MutexLocker locker(&mutex_);
-
- auto it = pending_connects_.find(connection_id);
- if (it == pending_connects_.end()) {
- // Not necessarily the caller's fault.
- LOG(ERROR) << "Connect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " which is not pending";
- return Result::FAILURE;
- }
-
- PendingConnectInfo* info = it->second;
- ProcessIdentifier peer;
- if (info->state == PendingConnectInfo::State::AWAITING_CONNECTS_FROM_BOTH) {
- if (process_identifier == info->first) {
- info->state = PendingConnectInfo::State::AWAITING_CONNECT_FROM_SECOND;
- peer = info->second;
- } else if (process_identifier == info->second) {
- info->state = PendingConnectInfo::State::AWAITING_CONNECT_FROM_FIRST;
- peer = info->first;
- } else {
- LOG(ERROR) << "Connect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " which is neither connectee";
- return Result::FAILURE;
- }
-
- DVLOG(1) << "Connection ID " << connection_id.ToString()
- << ": first Connect() from process identifier "
- << process_identifier;
- *peer_process_identifier = peer;
- *is_first = true;
- return ConnectImplHelperNoLock(process_identifier, peer, platform_handle);
- }
-
- // The remaining cases all result in |it| being removed from
- // |pending_connects_| and deleting |info|.
- pending_connects_.erase(it);
- scoped_ptr<PendingConnectInfo> info_deleter(info);
-
- // |remaining_connectee| should be the same as |process_identifier|.
- ProcessIdentifier remaining_connectee;
- if (info->state == PendingConnectInfo::State::AWAITING_CONNECT_FROM_FIRST) {
- remaining_connectee = info->first;
- peer = info->second;
- } else if (info->state ==
- PendingConnectInfo::State::AWAITING_CONNECT_FROM_SECOND) {
- remaining_connectee = info->second;
- peer = info->first;
- } else {
- // Someone's behaving badly, but we don't know who (it might not be the
- // caller).
- LOG(ERROR) << "Connect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " in state " << static_cast<int>(info->state);
- return Result::FAILURE;
- }
-
- if (process_identifier != remaining_connectee) {
- LOG(ERROR) << "Connect() from process " << process_identifier
- << " for connection ID " << connection_id.ToString()
- << " which is not the remaining connectee";
- return Result::FAILURE;
- }
-
- DVLOG(1) << "Connection ID " << connection_id.ToString()
- << ": second Connect() from process identifier "
- << process_identifier;
- *peer_process_identifier = peer;
- *is_first = false;
- return ConnectImplHelperNoLock(process_identifier, peer, platform_handle);
-}
-
-ConnectionManager::Result MasterConnectionManager::ConnectImplHelperNoLock(
- ProcessIdentifier process_identifier,
- ProcessIdentifier peer_process_identifier,
- embedder::ScopedPlatformHandle* platform_handle) {
- if (process_identifier == peer_process_identifier) {
- platform_handle->reset();
- DVLOG(1) << "Connect: same process";
- return Result::SUCCESS_CONNECT_SAME_PROCESS;
- }
-
- // We should know about the process identified by |process_identifier|.
- DCHECK(connections_.find(process_identifier) != connections_.end());
- ProcessConnections* process_connections = connections_[process_identifier];
- // We should also know about the peer.
- DCHECK(connections_.find(peer_process_identifier) != connections_.end());
- switch (process_connections->GetConnectionStatus(peer_process_identifier,
- platform_handle)) {
- case ProcessConnections::ConnectionStatus::NONE: {
- // TODO(vtl): In the "second connect" case, this should never be reached
- // (but it's not easy to DCHECK this invariant here).
- process_connections->AddConnection(
- peer_process_identifier,
- ProcessConnections::ConnectionStatus::RUNNING,
- embedder::ScopedPlatformHandle());
- embedder::PlatformChannelPair platform_channel_pair;
- *platform_handle = platform_channel_pair.PassServerHandle();
-
- connections_[peer_process_identifier]->AddConnection(
- process_identifier, ProcessConnections::ConnectionStatus::PENDING,
- platform_channel_pair.PassClientHandle());
- break;
- }
- case ProcessConnections::ConnectionStatus::PENDING:
- DCHECK(connections_[peer_process_identifier]->GetConnectionStatus(
- process_identifier, nullptr) ==
- ProcessConnections::ConnectionStatus::RUNNING);
- break;
- case ProcessConnections::ConnectionStatus::RUNNING:
- // |process_identifier| already has a connection to
- // |peer_process_identifier|, so it should reuse that.
- platform_handle->reset();
- DVLOG(1) << "Connect: reuse connection";
- return Result::SUCCESS_CONNECT_REUSE_CONNECTION;
- }
- DCHECK(platform_handle->is_valid());
- DVLOG(1) << "Connect: new connection";
- return Result::SUCCESS_CONNECT_NEW_CONNECTION;
-}
-
-void MasterConnectionManager::ShutdownOnPrivateThread() {
- AssertOnPrivateThread();
-
- if (!pending_connects_.empty()) {
- DVLOG(1) << "Shutting down with connections pending";
- for (auto& p : pending_connects_)
- delete p.second;
- pending_connects_.clear();
- }
-
- for (auto& p : connections_)
- delete p.second;
- connections_.clear();
-
- if (!helpers_.empty()) {
- DVLOG(1) << "Shutting down with slaves still connected";
- for (auto& p : helpers_) {
- embedder::SlaveInfo slave_info = p.second->Shutdown();
- delete p.second;
- CallOnSlaveDisconnect(slave_info);
- }
- helpers_.clear();
- }
-}
-
-void MasterConnectionManager::AddSlaveOnPrivateThread(
- embedder::SlaveInfo slave_info,
- embedder::ScopedPlatformHandle platform_handle,
- ProcessIdentifier slave_process_identifier,
- base::WaitableEvent* event) {
- DCHECK(platform_handle.is_valid());
- DCHECK(event);
- AssertOnPrivateThread();
-
- scoped_ptr<Helper> helper(new Helper(this, slave_process_identifier,
- slave_info, std::move(platform_handle)));
- helper->Init();
-
- DCHECK(helpers_.find(slave_process_identifier) == helpers_.end());
- helpers_[slave_process_identifier] = helper.release();
-
- DVLOG(1) << "Added slave process identifier " << slave_process_identifier;
- event->Signal();
-}
-
-void MasterConnectionManager::OnError(ProcessIdentifier process_identifier) {
- DCHECK_NE(process_identifier, kInvalidProcessIdentifier);
- AssertOnPrivateThread();
-
- auto it = helpers_.find(process_identifier);
- DCHECK(it != helpers_.end());
- Helper* helper = it->second;
- embedder::SlaveInfo slave_info = helper->Shutdown();
- helpers_.erase(it);
- delete helper;
-
- {
- MutexLocker locker(&mutex_);
-
- // TODO(vtl): This isn't very efficient.
- for (auto it = pending_connects_.begin(); it != pending_connects_.end();) {
- if (it->second->first == process_identifier ||
- it->second->second == process_identifier) {
- auto it_to_erase = it;
- ++it;
- delete it_to_erase->second;
- pending_connects_.erase(it_to_erase);
- } else {
- ++it;
- }
- }
- }
-
- CallOnSlaveDisconnect(slave_info);
-}
-
-void MasterConnectionManager::CallOnSlaveDisconnect(
- embedder::SlaveInfo slave_info) {
- AssertOnPrivateThread();
- DCHECK(master_process_delegate_);
- delegate_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&embedder::MasterProcessDelegate::OnSlaveDisconnect,
- base::Unretained(master_process_delegate_),
- base::Unretained(slave_info)));
-}
-
-void MasterConnectionManager::AssertNotOnPrivateThread() const {
- // This should only be called after |Init()| and before |Shutdown()|. (If not,
- // the subsequent |DCHECK_NE()| is invalid, since the current thread may not
- // have a message loop.)
- DCHECK(private_thread_.message_loop());
- DCHECK_NE(base::MessageLoop::current(), private_thread_.message_loop());
-}
-
-void MasterConnectionManager::AssertOnPrivateThread() const {
- // This should only be called after |Init()| and before |Shutdown()|.
- DCHECK(private_thread_.message_loop());
- DCHECK_EQ(base::MessageLoop::current(), private_thread_.message_loop());
-}
-
-} // namespace system
-} // namespace mojo
« no previous file with comments | « third_party/mojo/src/mojo/edk/system/master_connection_manager.h ('k') | third_party/mojo/src/mojo/edk/system/memory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698