You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
5.4 KiB
157 lines
5.4 KiB
// Copyright (c) 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 "ipc/ipc_message_attachment.h"
|
|
|
|
#include "base/files/scoped_file.h"
|
|
#include "base/logging.h"
|
|
#include "ipc/ipc_mojo_handle_attachment.h"
|
|
#include "mojo/public/cpp/system/platform_handle.h"
|
|
|
|
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
#include "base/posix/eintr_wrapper.h"
|
|
#include "ipc/ipc_platform_file_attachment_posix.h"
|
|
#endif
|
|
|
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
|
#include "ipc/mach_port_attachment_mac.h"
|
|
#endif
|
|
|
|
#if defined(OS_WIN)
|
|
#include "ipc/handle_attachment_win.h"
|
|
#endif
|
|
|
|
#if defined(OS_FUCHSIA)
|
|
#include "ipc/handle_attachment_fuchsia.h"
|
|
#endif
|
|
|
|
namespace IPC {
|
|
|
|
namespace {
|
|
|
|
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
|
|
return attachment->Owns()
|
|
? base::ScopedFD(attachment->TakePlatformFile())
|
|
: base::ScopedFD(HANDLE_EINTR(dup(attachment->file())));
|
|
}
|
|
#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
|
|
} // namespace
|
|
|
|
MessageAttachment::MessageAttachment() = default;
|
|
|
|
MessageAttachment::~MessageAttachment() = default;
|
|
|
|
mojo::ScopedHandle MessageAttachment::TakeMojoHandle() {
|
|
switch (GetType()) {
|
|
case Type::MOJO_HANDLE:
|
|
return static_cast<internal::MojoHandleAttachment*>(this)->TakeHandle();
|
|
|
|
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
case Type::PLATFORM_FILE: {
|
|
// We dup() the handles in IPC::Message to transmit.
|
|
// IPC::MessageAttachmentSet has intricate lifetime semantics for FDs, so
|
|
// just to dup()-and-own them is the safest option.
|
|
base::ScopedFD file =
|
|
TakeOrDupFile(static_cast<internal::PlatformFileAttachment*>(this));
|
|
if (!file.is_valid()) {
|
|
DPLOG(WARNING) << "Failed to dup FD to transmit.";
|
|
return mojo::ScopedHandle();
|
|
}
|
|
return mojo::WrapPlatformFile(file.release());
|
|
}
|
|
#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
|
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
|
case Type::MACH_PORT: {
|
|
auto* attachment = static_cast<internal::MachPortAttachmentMac*>(this);
|
|
MojoPlatformHandle platform_handle = {
|
|
sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT,
|
|
static_cast<uint64_t>(attachment->get_mach_port())};
|
|
MojoHandle wrapped_handle;
|
|
if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
|
|
MOJO_RESULT_OK) {
|
|
return mojo::ScopedHandle();
|
|
}
|
|
attachment->reset_mach_port_ownership();
|
|
return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
|
|
}
|
|
#elif defined(OS_FUCHSIA)
|
|
case Type::FUCHSIA_HANDLE: {
|
|
auto* attachment = static_cast<internal::HandleAttachmentFuchsia*>(this);
|
|
MojoPlatformHandle platform_handle = {
|
|
sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE,
|
|
static_cast<uint64_t>(attachment->Take())};
|
|
MojoHandle wrapped_handle;
|
|
if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
|
|
MOJO_RESULT_OK) {
|
|
return mojo::ScopedHandle();
|
|
}
|
|
return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
|
|
}
|
|
#elif defined(OS_WIN)
|
|
case Type::WIN_HANDLE:
|
|
return mojo::WrapPlatformFile(
|
|
static_cast<internal::HandleAttachmentWin*>(this)->Take());
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
NOTREACHED();
|
|
return mojo::ScopedHandle();
|
|
}
|
|
|
|
// static
|
|
scoped_refptr<MessageAttachment> MessageAttachment::CreateFromMojoHandle(
|
|
mojo::ScopedHandle handle,
|
|
Type type) {
|
|
if (type == Type::MOJO_HANDLE)
|
|
return new internal::MojoHandleAttachment(std::move(handle));
|
|
|
|
MojoPlatformHandle platform_handle = {sizeof(platform_handle), 0, 0};
|
|
MojoResult unwrap_result = MojoUnwrapPlatformHandle(
|
|
handle.release().value(), nullptr, &platform_handle);
|
|
if (unwrap_result != MOJO_RESULT_OK)
|
|
return nullptr;
|
|
|
|
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
if (type == Type::PLATFORM_FILE) {
|
|
base::PlatformFile file = base::kInvalidPlatformFile;
|
|
if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
|
|
file = static_cast<base::PlatformFile>(platform_handle.value);
|
|
return new internal::PlatformFileAttachment(file);
|
|
}
|
|
#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
|
|
|
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
|
if (type == Type::MACH_PORT) {
|
|
mach_port_t mach_port = MACH_PORT_NULL;
|
|
if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT)
|
|
mach_port = static_cast<mach_port_t>(platform_handle.value);
|
|
return new internal::MachPortAttachmentMac(
|
|
mach_port, internal::MachPortAttachmentMac::FROM_WIRE);
|
|
}
|
|
#elif defined(OS_FUCHSIA)
|
|
if (type == Type::FUCHSIA_HANDLE) {
|
|
zx::handle handle;
|
|
if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
|
|
handle.reset(static_cast<zx_handle_t>(platform_handle.value));
|
|
return new internal::HandleAttachmentFuchsia(std::move(handle));
|
|
}
|
|
#elif defined(OS_WIN)
|
|
if (type == Type::WIN_HANDLE) {
|
|
base::PlatformFile handle = base::kInvalidPlatformFile;
|
|
if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE)
|
|
handle = reinterpret_cast<base::PlatformFile>(platform_handle.value);
|
|
return new internal::HandleAttachmentWin(
|
|
handle, internal::HandleAttachmentWin::FROM_WIRE);
|
|
}
|
|
#endif
|
|
NOTREACHED();
|
|
return nullptr;
|
|
}
|
|
|
|
} // namespace IPC
|