blob: 22ea774f56a5f0114c5f91c1b657cc5ab09057bf [file] [log] [blame]
// Copyright 2018 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.
#ifndef MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_HANDLE_H_
#define MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_HANDLE_H_
#include "base/component_export.h"
#include "base/logging.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "mojo/public/c/system/platform_handle.h"
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
#elif defined(OS_FUCHSIA)
#include <lib/zx/handle.h>
#elif defined(OS_MACOSX) && !defined(OS_IOS)
#include "base/mac/scoped_mach_port.h"
#endif
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include "base/files/scoped_file.h"
#endif
namespace mojo {
// A PlatformHandle is a generic wrapper around a platform-specific system
// handle type, e.g. a POSIX file descriptor or Windows HANDLE. This can wrap
// any of various such types depending on the host platform for which it's
// compiled.
//
// This is useful primarily for two reasons:
//
// - Interacting with the Mojo invitation API, which use OS primitives to
// bootstrap Mojo IPC connections.
// - Interacting with Mojo platform handle wrapping and unwrapping API, which
// allows handles to OS primitives to be transmitted over Mojo IPC with a
// stable wire representation via Mojo handles.
//
// NOTE: This assumes ownership if the handle it represents.
class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformHandle {
public:
enum class Type {
kNone,
#if defined(OS_WIN) || defined(OS_FUCHSIA)
kHandle,
#elif defined(OS_MACOSX) && !defined(OS_IOS)
kMachPort,
#endif
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
kFd,
#endif
};
PlatformHandle();
PlatformHandle(PlatformHandle&& other);
#if defined(OS_WIN)
explicit PlatformHandle(base::win::ScopedHandle handle);
#elif defined(OS_FUCHSIA)
explicit PlatformHandle(zx::handle handle);
#elif defined(OS_MACOSX) && !defined(OS_IOS)
explicit PlatformHandle(base::mac::ScopedMachSendRight mach_port);
#endif
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
explicit PlatformHandle(base::ScopedFD fd);
#endif
~PlatformHandle();
PlatformHandle& operator=(PlatformHandle&& other);
// Takes ownership of |handle|'s underlying platform handle and fills in
// |mojo_handle| with a representation of it. The caller assumes ownership of
// the platform handle.
static void ToMojoPlatformHandle(PlatformHandle handle,
MojoPlatformHandle* mojo_handle);
// Closes the underlying platform handle.
// Assumes ownership of the platform handle described by |handle|, and returns
// it as a new PlatformHandle.
static PlatformHandle FromMojoPlatformHandle(
const MojoPlatformHandle* handle);
Type type() const { return type_; }
void reset();
// Relinquishes ownership of the underlying handle, regardless of type, and
// discards its value. To release and obtain the underlying handle value, use
// one of the specific |Release*()| methods below.
void release();
// Duplicates the underlying platform handle, returning a new PlatformHandle
// which owns it.
PlatformHandle Clone() const;
#if defined(OS_WIN)
bool is_valid() const { return is_valid_handle(); }
bool is_valid_handle() const { return handle_.IsValid(); }
bool is_handle() const { return type_ == Type::kHandle; }
const base::win::ScopedHandle& GetHandle() const { return handle_; }
base::win::ScopedHandle TakeHandle() {
DCHECK_EQ(type_, Type::kHandle);
type_ = Type::kNone;
return std::move(handle_);
}
HANDLE ReleaseHandle() WARN_UNUSED_RESULT {
DCHECK_EQ(type_, Type::kHandle);
type_ = Type::kNone;
return handle_.Take();
}
#elif defined(OS_FUCHSIA)
bool is_valid() const { return is_valid_fd() || is_valid_handle(); }
bool is_valid_handle() const { return handle_.is_valid(); }
bool is_handle() const { return type_ == Type::kHandle; }
const zx::handle& GetHandle() const { return handle_; }
zx::handle TakeHandle() {
if (type_ == Type::kHandle)
type_ = Type::kNone;
return std::move(handle_);
}
zx_handle_t ReleaseHandle() WARN_UNUSED_RESULT {
if (type_ == Type::kHandle)
type_ = Type::kNone;
return handle_.release();
}
#elif defined(OS_MACOSX) && !defined(OS_IOS)
bool is_valid() const { return is_valid_fd() || is_valid_mach_port(); }
bool is_valid_mach_port() const { return mach_port_.is_valid(); }
bool is_mach_port() const { return type_ == Type::kMachPort; }
const base::mac::ScopedMachSendRight& GetMachPort() const {
return mach_port_;
}
base::mac::ScopedMachSendRight TakeMachPort() {
if (type_ == Type::kMachPort)
type_ = Type::kNone;
return std::move(mach_port_);
}
mach_port_t ReleaseMachPort() WARN_UNUSED_RESULT {
if (type_ == Type::kMachPort)
type_ = Type::kNone;
return mach_port_.release();
}
#elif defined(OS_POSIX)
bool is_valid() const { return is_valid_fd(); }
#else
#error "Unsupported platform."
#endif
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
bool is_valid_fd() const { return fd_.is_valid(); }
bool is_fd() const { return type_ == Type::kFd; }
const base::ScopedFD& GetFD() const { return fd_; }
base::ScopedFD TakeFD() {
if (type_ == Type::kFd)
type_ = Type::kNone;
return std::move(fd_);
}
int ReleaseFD() WARN_UNUSED_RESULT {
if (type_ == Type::kFd)
type_ = Type::kNone;
return fd_.release();
}
#endif
private:
Type type_ = Type::kNone;
#if defined(OS_WIN)
base::win::ScopedHandle handle_;
#elif defined(OS_FUCHSIA)
zx::handle handle_;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
base::mac::ScopedMachSendRight mach_port_;
#endif
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
base::ScopedFD fd_;
#endif
DISALLOW_COPY_AND_ASSIGN(PlatformHandle);
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_HANDLE_H_