1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_PROXY_SERIALIZED_HANDLE_H_
#define PPAPI_PROXY_SERIALIZED_HANDLE_H_
#include <stdint.h>
#include <utility>
#include "base/atomicops.h"
#include "base/check_op.h"
#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "build/build_config.h"
#include "ipc/ipc_platform_file.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
namespace base {
class Pickle;
}
namespace ppapi {
namespace proxy {
// SerializedHandle is a unified structure for holding a handle (e.g., a shared
// memory handle, socket descriptor, etc). This is useful for passing handles in
// resource messages and also makes it easier to translate handles in
// NaClIPCAdapter for use in NaCl.
class PPAPI_PROXY_EXPORT SerializedHandle {
public:
enum Type { INVALID, SHARED_MEMORY_REGION, SOCKET, FILE };
// Header contains the fields that we send in IPC messages, apart from the
// actual handle. See comments on the SerializedHandle fields below.
struct Header {
Header() : type(INVALID), size(0), open_flags(0) {}
Header(Type type_arg,
int32_t open_flags_arg,
PP_Resource file_io_arg)
: type(type_arg),
open_flags(open_flags_arg),
file_io(file_io_arg) {}
Type type;
uint32_t size;
int32_t open_flags;
PP_Resource file_io;
};
SerializedHandle();
// Move operations are allowed.
SerializedHandle(SerializedHandle&&);
SerializedHandle& operator=(SerializedHandle&&);
// Create an invalid handle of the given type.
explicit SerializedHandle(Type type);
SerializedHandle(const SerializedHandle&) = delete;
SerializedHandle& operator=(const SerializedHandle&) = delete;
// Create a shared memory region handle.
explicit SerializedHandle(base::ReadOnlySharedMemoryRegion region);
explicit SerializedHandle(base::UnsafeSharedMemoryRegion region);
explicit SerializedHandle(base::subtle::PlatformSharedMemoryRegion region);
// Create a socket or file handle.
SerializedHandle(const Type type,
const IPC::PlatformFileForTransit& descriptor);
Type type() const { return type_; }
bool is_shmem_region() const { return type_ == SHARED_MEMORY_REGION; }
bool is_socket() const { return type_ == SOCKET; }
bool is_file() const { return type_ == FILE; }
const base::subtle::PlatformSharedMemoryRegion& shmem_region() const {
DCHECK(is_shmem_region());
return shm_region_;
}
base::subtle::PlatformSharedMemoryRegion TakeSharedMemoryRegion() {
DCHECK(is_shmem_region());
return std::move(shm_region_);
}
const IPC::PlatformFileForTransit& descriptor() const {
DCHECK(is_socket() || is_file());
return descriptor_;
}
int32_t open_flags() const { return open_flags_; }
PP_Resource file_io() const {
return file_io_;
}
void set_shmem_region(base::subtle::PlatformSharedMemoryRegion region) {
type_ = SHARED_MEMORY_REGION;
shm_region_ = std::move(region);
// Writable regions are not supported.
DCHECK_NE(shm_region_.GetMode(),
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
descriptor_ = IPC::InvalidPlatformFileForTransit();
}
void set_unsafe_shmem_region(base::UnsafeSharedMemoryRegion region) {
set_shmem_region(base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
std::move(region)));
}
void set_socket(const IPC::PlatformFileForTransit& socket) {
type_ = SOCKET;
descriptor_ = socket;
shm_region_ = base::subtle::PlatformSharedMemoryRegion();
}
void set_file_handle(const IPC::PlatformFileForTransit& descriptor,
int32_t open_flags,
PP_Resource file_io) {
type_ = FILE;
descriptor_ = descriptor;
shm_region_ = base::subtle::PlatformSharedMemoryRegion();
open_flags_ = open_flags;
file_io_ = file_io;
}
void set_null() {
type_ = INVALID;
shm_region_ = base::subtle::PlatformSharedMemoryRegion();
descriptor_ = IPC::InvalidPlatformFileForTransit();
}
void set_null_shmem_region() {
set_shmem_region(base::subtle::PlatformSharedMemoryRegion());
}
void set_null_socket() {
set_socket(IPC::InvalidPlatformFileForTransit());
}
void set_null_file_handle() {
set_file_handle(IPC::InvalidPlatformFileForTransit(), 0, 0);
}
bool IsHandleValid() const;
Header header() const { return Header(type_, open_flags_, file_io_); }
// Closes the handle and sets it to invalid.
void Close();
// Write/Read a Header, which contains all the data except the handle. This
// allows us to write the handle in a platform-specific way, as is necessary
// in NaClIPCAdapter to share handles with NaCl from Windows.
static void WriteHeader(const Header& hdr, base::Pickle* pickle);
static bool ReadHeader(base::PickleIterator* iter, Header* hdr);
private:
// The kind of handle we're holding.
Type type_;
// We hold more members than we really need; we can't easily use a union,
// because we hold non-POD types. But these types are pretty light-weight. If
// we add more complex things later, we should come up with a more memory-
// efficient strategy.
// This is valid if type == SHARED_MEMORY_REGION.
base::subtle::PlatformSharedMemoryRegion shm_region_;
// This is valid if type == SOCKET || type == FILE.
IPC::PlatformFileForTransit descriptor_;
// The following fields are valid if type == FILE.
int32_t open_flags_;
// This is non-zero if file writes require quota checking.
PP_Resource file_io_;
};
} // namespace proxy
} // namespace ppapi
#endif // PPAPI_PROXY_SERIALIZED_HANDLE_H_
|