blob: c8e9ef30f4680390f2f7f414de4e9c641112d983 [file] [log] [blame]
// 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/public/cpp/system/platform_handle.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include <mach/mach.h>
#include "base/mac/mach_logging.h"
#endif
namespace mojo {
namespace {
uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) {
#if defined(OS_WIN)
return reinterpret_cast<uint64_t>(file);
#else
return static_cast<uint64_t>(file);
#endif
}
base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
#if defined(OS_WIN)
return reinterpret_cast<base::PlatformFile>(value);
#else
return static_cast<base::PlatformFile>(value);
#endif
}
} // namespace
ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
platform_handle.type = kPlatformFileHandleType;
platform_handle.value = PlatformHandleValueFromPlatformFile(platform_file);
MojoHandle mojo_handle;
MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle);
CHECK_EQ(result, MOJO_RESULT_OK);
return ScopedHandle(Handle(mojo_handle));
}
MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
MojoResult result =
MojoUnwrapPlatformHandle(handle.release().value(), &platform_handle);
if (result != MOJO_RESULT_OK)
return result;
if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
*file = base::kInvalidPlatformFile;
} else {
CHECK_EQ(platform_handle.type, kPlatformFileHandleType);
*file = PlatformFileFromPlatformHandleValue(platform_handle.value);
}
return MOJO_RESULT_OK;
}
ScopedSharedBufferHandle WrapSharedMemoryHandle(
const base::SharedMemoryHandle& memory_handle,
size_t size,
UnwrappedSharedMemoryHandleProtection protection) {
if (!memory_handle.IsValid())
return ScopedSharedBufferHandle();
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
platform_handle.type = kPlatformSharedBufferHandleType;
#if defined(OS_MACOSX) && !defined(OS_IOS)
platform_handle.value =
static_cast<uint64_t>(memory_handle.GetMemoryObject());
#else
platform_handle.value =
PlatformHandleValueFromPlatformFile(memory_handle.GetHandle());
#endif
MojoPlatformSharedBufferHandleFlags flags =
MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
if (protection == UnwrappedSharedMemoryHandleProtection::kReadOnly)
flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY;
MojoSharedBufferGuid guid;
guid.high = memory_handle.GetGUID().GetHighForSerialization();
guid.low = memory_handle.GetGUID().GetLowForSerialization();
MojoHandle mojo_handle;
MojoResult result = MojoWrapPlatformSharedBufferHandle(
&platform_handle, size, &guid, flags, &mojo_handle);
CHECK_EQ(result, MOJO_RESULT_OK);
return ScopedSharedBufferHandle(SharedBufferHandle(mojo_handle));
}
MojoResult UnwrapSharedMemoryHandle(
ScopedSharedBufferHandle handle,
base::SharedMemoryHandle* memory_handle,
size_t* size,
UnwrappedSharedMemoryHandleProtection* protection) {
if (!handle.is_valid())
return MOJO_RESULT_INVALID_ARGUMENT;
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
MojoPlatformSharedBufferHandleFlags flags;
size_t num_bytes;
MojoSharedBufferGuid mojo_guid;
MojoResult result = MojoUnwrapPlatformSharedBufferHandle(
handle.release().value(), &platform_handle, &num_bytes, &mojo_guid,
&flags);
if (result != MOJO_RESULT_OK)
return result;
if (size)
*size = num_bytes;
if (protection) {
*protection =
flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY
? UnwrappedSharedMemoryHandleProtection::kReadOnly
: UnwrappedSharedMemoryHandleProtection::kReadWrite;
}
base::UnguessableToken guid =
base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low);
#if defined(OS_MACOSX) && !defined(OS_IOS)
DCHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT);
*memory_handle = base::SharedMemoryHandle(
static_cast<mach_port_t>(platform_handle.value), num_bytes, guid);
#elif defined(OS_FUCHSIA)
DCHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE);
*memory_handle = base::SharedMemoryHandle(
static_cast<zx_handle_t>(platform_handle.value), num_bytes, guid);
#elif defined(OS_POSIX)
DCHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR);
*memory_handle = base::SharedMemoryHandle(
base::FileDescriptor(static_cast<int>(platform_handle.value), false),
num_bytes, guid);
#elif defined(OS_WIN)
DCHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE);
*memory_handle = base::SharedMemoryHandle(
reinterpret_cast<HANDLE>(platform_handle.value), num_bytes, guid);
#endif
return MOJO_RESULT_OK;
}
#if defined(OS_MACOSX) && !defined(OS_IOS)
ScopedHandle WrapMachPort(mach_port_t port) {
kern_return_t kr =
mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, 1);
MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
<< "MachPortAttachmentMac mach_port_mod_refs";
if (kr != KERN_SUCCESS)
return ScopedHandle();
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
platform_handle.value = static_cast<uint64_t>(port);
MojoHandle mojo_handle;
MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle);
CHECK_EQ(result, MOJO_RESULT_OK);
return ScopedHandle(Handle(mojo_handle));
}
MojoResult UnwrapMachPort(ScopedHandle handle, mach_port_t* port) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
MojoResult result =
MojoUnwrapPlatformHandle(handle.release().value(), &platform_handle);
if (result != MOJO_RESULT_OK)
return result;
CHECK(platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT ||
platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_INVALID);
*port = static_cast<mach_port_t>(platform_handle.value);
return MOJO_RESULT_OK;
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
} // namespace mojo