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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_CORE_IPCZ_DRIVER_OBJECT_H_
#define MOJO_CORE_IPCZ_DRIVER_OBJECT_H_
#include <cstddef>
#include <cstdint>
#include <tuple>
#include "base/containers/span.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "mojo/core/ipcz_api.h"
#include "mojo/core/system_impl_export.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "third_party/ipcz/include/ipcz/ipcz.h"
namespace mojo::core::ipcz_driver {
class Transport;
// Common base class for objects managed by Mojo's ipcz driver.
class MOJO_SYSTEM_IMPL_EXPORT ObjectBase
: public base::RefCountedThreadSafe<ObjectBase> {
public:
REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
enum Type : uint32_t {
// An ipcz transport endpoint.
kTransport,
// A wrapped shared memory region.
kSharedBuffer,
// An active mapping for a shared memory region. These objects are not
// serializable and cannot be transmitted over a Transport.
kSharedBufferMapping,
// A PlatformHandle which can be transmitted as-is by the platform's Channel
// implementation, out-of-band from message data. This is the only type of
// driver object which can be emitted by the driver's Serialize(), and it's
// the only type accepted by its Transmit(). This type is unused on Windows,
// where all platform handles are encoded as inline message data during
// serialization.
kTransmissiblePlatformHandle,
// A PlatformHandle which may or may not be transmissible by the platform's
// Channel implementation, but which can at least be transformed into
// something transmissible during serialization.
kWrappedPlatformHandle,
// A DataPipe instance used to emulate Mojo data pipes over ipcz portals.
kDataPipe,
// A MojoTrap instance used to emulate a Mojo trap. These objects are not
// serializable and cannot be transmitted over a Transport.
kMojoTrap,
// An Invitation instance used to emulate Mojo process invitations. These
// objects are not serializable and cannot be transmitted over a Transport.
kInvitation,
// See Envelope for details.
kEnvelope,
// For ValidateEnum().
kMinValue = kTransport,
kMaxValue = kEnvelope,
};
explicit ObjectBase(Type type);
Type type() const { return type_; }
IpczDriverHandle handle() const {
return reinterpret_cast<IpczDriverHandle>(this);
}
static ObjectBase* FromHandle(IpczDriverHandle handle) {
return reinterpret_cast<ObjectBase*>(handle);
}
static IpczDriverHandle ReleaseAsHandle(scoped_refptr<ObjectBase> object) {
return reinterpret_cast<IpczDriverHandle>(object.release());
}
static scoped_refptr<ObjectBase> TakeFromHandle(IpczDriverHandle handle) {
scoped_refptr<ObjectBase> object(FromHandle(handle));
if (object) {
// We're inheriting a ref previously owned by `handle`, so drop the extra
// ref we just added.
object->Release();
}
return object;
}
// Peeks at `box` and returns a pointer to its underlying object. Does not
// invalidate `box`.
static ObjectBase* FromBox(IpczHandle box) {
return FromHandle(PeekBox(box));
}
// Boxes a reference to `object` and returns an IpczHandle for the box.
static IpczHandle Box(scoped_refptr<ObjectBase> object);
// Closes this object.
virtual void Close();
// Indicates whether this object can be serialized at all.
virtual bool IsSerializable() const;
// Computes the number of bytes and platform handles required to serialize
// this object for transmission through `transmitter`. Returns false if the
// object cannot be serialized or transmitted as such.
virtual bool GetSerializedDimensions(Transport& transmitter,
size_t& num_bytes,
size_t& num_handles);
// Attempts to serialize this object into `data` and `handles` which are
// already sufficiently sized according to GetSerializedDimensions(). Returns
// false if serialization fails.
virtual bool Serialize(Transport& transmitter,
base::span<uint8_t> data,
base::span<PlatformHandle> handles);
protected:
virtual ~ObjectBase();
// Peeks at `box` and returns its underlying driver handle.
static IpczDriverHandle PeekBox(IpczHandle box);
// Unboxes `box` and returns a reference to the object it contained.
static scoped_refptr<ObjectBase> Unbox(IpczHandle box);
private:
friend class base::RefCountedThreadSafe<ObjectBase>;
const Type type_;
};
// Type-specific base class which builds on ObjectBase but which infers its Type
// from a static object_type() method defined by T.
template <typename T>
class Object : public ObjectBase {
public:
Object() : ObjectBase(T::object_type()) {}
// Constructs a new T instance with the forwarded Args, and immediately boxes
// a reference to it. Returns a handle to the new box.
template <typename... Args>
static IpczHandle MakeBoxed(Args&&... args) {
return Box(base::MakeRefCounted<T>(std::forward<Args>(args)...));
}
static T* FromHandle(IpczDriverHandle handle) {
ObjectBase* object = ObjectBase::FromHandle(handle);
if (!object || object->type() != T::object_type()) {
return nullptr;
}
return static_cast<T*>(object);
}
static scoped_refptr<T> TakeFromHandle(IpczDriverHandle handle) {
scoped_refptr<T> object(FromHandle(handle));
if (object) {
// We're inheriting a ref previously owned by `handle`, so drop the extra
// ref we just added.
object->Release();
}
return object;
}
// Peeks at `box` and returns a pointer to its underlying T, if the underlying
// driver object is in fact a T. Does not invalidate `box`.
static T* FromBox(IpczHandle box) { return FromHandle(PeekBox(box)); }
// Unboxes `box` and returns a reference to its underlying T. If `box` is not
// a box that contains a T, this returns null.
static scoped_refptr<T> Unbox(IpczHandle box) {
scoped_refptr<T> object = base::WrapRefCounted(T::FromBox(box));
if (object) {
std::ignore = ObjectBase::Unbox(box);
}
return object;
}
protected:
~Object() override = default;
};
} // namespace mojo::core::ipcz_driver
#endif // MOJO_CORE_IPCZ_DRIVER_OBJECT_H_
|