// 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 #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_