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
mojo / core / ipcz_driver / object.h [blame]
// 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,
};
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_