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

Unified Diff: mojo/edk/system/mach_port_relay.cc

Issue 1712143002: [mojo-edk] Add support for transferring mach ports. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix build Created 4 years, 9 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
« no previous file with comments | « mojo/edk/system/mach_port_relay.h ('k') | mojo/edk/system/node_channel.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/edk/system/mach_port_relay.cc
diff --git a/mojo/edk/system/mach_port_relay.cc b/mojo/edk/system/mach_port_relay.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2dd40e51aae207c36ebd8c8fd19c4c5a6c301036
--- /dev/null
+++ b/mojo/edk/system/mach_port_relay.cc
@@ -0,0 +1,155 @@
+// Copyright 2016 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 "mojo/edk/system/mach_port_relay.h"
+
+#include <mach/mach.h>
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/mac/mach_port_util.h"
+#include "base/mac/scoped_mach_port.h"
+#include "base/process/process.h"
+#include "mojo/edk/embedder/platform_handle_vector.h"
+
+namespace mojo {
+namespace edk {
+
+// static
+bool MachPortRelay::ReceivePorts(PlatformHandleVector* handles) {
+ DCHECK(handles);
+
+ for (size_t i = 0; i < handles->size(); i++) {
+ PlatformHandle* handle = handles->data() + i;
+ DCHECK(handle->type != PlatformHandle::Type::MACH);
+ if (handle->type != PlatformHandle::Type::MACH_NAME)
+ continue;
+
+ base::mac::ScopedMachReceiveRight message_port(handle->port);
+ base::mac::ScopedMachSendRight received_port(
+ base::ReceiveMachPort(message_port.get()));
+ if (received_port.get() == MACH_PORT_NULL) {
+ handle->port = MACH_PORT_NULL;
+ LOG(ERROR) << "Error receiving mach port";
+ return false;
+ }
+
+ handle->port = received_port.release();
+ handle->type = PlatformHandle::Type::MACH;
+ }
+
+ return true;
+}
+
+MachPortRelay::MachPortRelay(base::PortProvider* port_provider)
+ : port_provider_(port_provider) {
+ DCHECK(port_provider);
+ port_provider_->AddObserver(this);
+}
+
+MachPortRelay::~MachPortRelay() {
+ port_provider_->RemoveObserver(this);
+}
+
+bool MachPortRelay::SendPortsToProcess(Channel::Message* message,
+ base::ProcessHandle process) {
+ DCHECK(message);
+ mach_port_t task_port = port_provider_->TaskForPid(process);
+ if (task_port == MACH_PORT_NULL)
+ return false;
+
+ size_t num_sent = 0;
+ bool error = false;
+ ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
+ // Message should have handles, otherwise there's no point in calling this
+ // function.
+ DCHECK(handles);
+ for (size_t i = 0; i < handles->size(); i++) {
+ PlatformHandle* handle = &(*handles)[i];
+ DCHECK(handle->type != PlatformHandle::Type::MACH_NAME);
+ if (handle->type != PlatformHandle::Type::MACH)
+ continue;
+
+ mach_port_name_t intermediate_port;
+ DCHECK(handle->port != MACH_PORT_NULL);
+ intermediate_port = base::CreateIntermediateMachPort(
+ task_port, base::mac::ScopedMachSendRight(handle->port), nullptr);
+ if (intermediate_port == MACH_PORT_NULL) {
+ handle->port = MACH_PORT_NULL;
+ error = true;
+ break;
+ }
+ handle->port = intermediate_port;
+ handle->type = PlatformHandle::Type::MACH_NAME;
+ num_sent++;
+ }
+ DCHECK(error || num_sent);
+ message->SetHandles(std::move(handles));
+
+ return !error;
+}
+
+bool MachPortRelay::ExtractPortRights(Channel::Message* message,
+ base::ProcessHandle process) {
+ DCHECK(message);
+
+ mach_port_t task_port = port_provider_->TaskForPid(process);
+ if (task_port == MACH_PORT_NULL)
+ return false;
+
+ size_t num_received = 0;
+ bool error = false;
+ ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
+ // Message should have handles, otherwise there's no point in calling this
+ // function.
+ DCHECK(handles);
+ for (size_t i = 0; i < handles->size(); i++) {
+ PlatformHandle* handle = handles->data() + i;
+ DCHECK(handle->type != PlatformHandle::Type::MACH);
+ if (handle->type != PlatformHandle::Type::MACH_NAME)
+ continue;
+
+ mach_port_t extracted_right = MACH_PORT_NULL;
+ mach_msg_type_name_t extracted_right_type;
+ kern_return_t kr =
+ mach_port_extract_right(task_port, handle->port,
+ MACH_MSG_TYPE_MOVE_SEND,
+ &extracted_right, &extracted_right_type);
+ if (kr != KERN_SUCCESS) {
+ error = true;
+ break;
+ }
+
+ DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND),
+ extracted_right_type);
+ handle->port = extracted_right;
+ handle->type = PlatformHandle::Type::MACH;
+ num_received++;
+ }
+ DCHECK(error || num_received);
+ message->SetHandles(std::move(handles));
+
+ return !error;
+}
+
+void MachPortRelay::AddObserver(Observer* observer) {
+ base::AutoLock locker(observers_lock_);
+ bool inserted = observers_.insert(observer).second;
+ DCHECK(inserted);
+}
+
+void MachPortRelay::RemoveObserver(Observer* observer) {
+ base::AutoLock locker(observers_lock_);
+ observers_.erase(observer);
+}
+
+void MachPortRelay::OnReceivedTaskPort(base::ProcessHandle process) {
+ base::AutoLock locker(observers_lock_);
+ for (const auto observer : observers_)
+ observer->OnProcessReady(process);
+}
+
+} // namespace edk
+} // namespace mojo
« no previous file with comments | « mojo/edk/system/mach_port_relay.h ('k') | mojo/edk/system/node_channel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698