Bug 1886946: Remove incorrect assertion that buffer is not-pinned. r=sfink
[gecko.git] / dom / ipc / PropertyBagUtils.cpp
blob6c1b3e8feaef0affe7b4dd94948045d77c0f4915
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "PropertyBagUtils.h"
9 #include "mozilla/SimpleEnumerator.h"
10 #include "mozilla/dom/DOMTypes.h"
11 #include "nsCOMPtr.h"
12 #include "nsHashPropertyBag.h"
13 #include "nsID.h"
14 #include "nsIProperty.h"
15 #include "nsIURI.h"
16 #include "nsVariant.h"
18 using namespace IPC;
19 using namespace mozilla::dom;
21 namespace mozilla::ipc {
23 void IPDLParamTraits<nsIVariant*>::Write(MessageWriter* aWriter,
24 IProtocol* aActor,
25 nsIVariant* aParam) {
26 IDPLVariant variant;
28 variant.type() = aParam->GetDataType();
30 switch (variant.type()) {
31 case nsIDataType::VTYPE_INT8:
32 case nsIDataType::VTYPE_UINT8:
33 case nsIDataType::VTYPE_CHAR: {
34 uint8_t value;
35 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint8(&value));
36 variant.data() = value;
37 break;
39 case nsIDataType::VTYPE_WCHAR:
40 case nsIDataType::VTYPE_INT16: {
41 int16_t value;
42 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInt16(&value));
43 variant.data() = value;
44 break;
46 case nsIDataType::VTYPE_UINT16: {
47 uint16_t value;
48 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint16(&value));
49 variant.data() = value;
50 break;
52 case nsIDataType::VTYPE_INT32: {
53 int32_t value;
54 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInt32(&value));
55 variant.data() = value;
56 break;
58 case nsIDataType::VTYPE_UINT32: {
59 uint32_t value;
60 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint32(&value));
61 variant.data() = value;
62 break;
64 case nsIDataType::VTYPE_FLOAT: {
65 float value;
66 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsFloat(&value));
67 variant.data() = value;
68 break;
70 case nsIDataType::VTYPE_DOUBLE: {
71 double value;
72 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsDouble(&value));
73 variant.data() = value;
74 break;
76 case nsIDataType::VTYPE_BOOL: {
77 bool value;
78 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsBool(&value));
79 variant.data() = value;
80 break;
82 case nsIDataType::VTYPE_ID: {
83 nsID value;
84 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsID(&value));
85 variant.data() = value;
86 break;
88 case nsIDataType::VTYPE_ASTRING:
89 case nsIDataType::VTYPE_WCHAR_STR:
90 case nsIDataType::VTYPE_WSTRING_SIZE_IS: {
91 nsString value;
92 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsAString(value));
93 variant.data() = value;
94 break;
96 case nsIDataType::VTYPE_CSTRING:
97 case nsIDataType::VTYPE_CHAR_STR:
98 case nsIDataType::VTYPE_STRING_SIZE_IS:
99 case nsIDataType::VTYPE_UTF8STRING: {
100 nsCString value;
101 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsACString(value));
102 variant.data() = value;
103 break;
105 case nsIDataType::VTYPE_INTERFACE:
106 case nsIDataType::VTYPE_INTERFACE_IS: {
107 nsIID* iid;
108 nsCOMPtr<nsISupports> value;
109 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInterface(&iid, getter_AddRefs(value)));
110 free(iid);
111 // We only accept nsIURI and nsIPrincipal interface types, patch welcome.
112 if (nsCOMPtr<nsIURI> uri = do_QueryInterface(value)) {
113 variant.data() = uri;
114 } else if (nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(value)) {
115 variant.data() = principal;
116 } else if (value) {
117 variant.type() = nsIDataType::VTYPE_EMPTY;
118 variant.data() = false; // because we need something.
119 } else {
120 // Let's pretend like we had a null URI, though how do we know
121 // it wasn't a null principal?
122 variant.data() = (nsIURI*)nullptr;
124 break;
126 case nsIDataType::VTYPE_VOID:
127 case nsIDataType::VTYPE_EMPTY:
128 variant.data() = false; // because we need something.
129 break;
130 default:
131 MOZ_CRASH("Non handled variant type, patch welcome");
132 break;
134 WriteIPDLParam(aWriter, aActor, variant);
137 bool IPDLParamTraits<nsIVariant*>::Read(MessageReader* aReader,
138 IProtocol* aActor,
139 RefPtr<nsIVariant>* aResult) {
140 IDPLVariant value;
141 if (!ReadIPDLParam(aReader, aActor, &value)) {
142 return false;
145 auto variant = MakeRefPtr<nsVariant>();
147 switch (value.type()) {
148 case nsIDataType::VTYPE_INT8:
149 case nsIDataType::VTYPE_UINT8:
150 if (value.type() == nsIDataType::VTYPE_INT8) {
151 variant->SetAsInt8(value.data().get_uint8_t());
152 } else {
153 variant->SetAsUint8(value.data().get_uint8_t());
155 break;
156 case nsIDataType::VTYPE_INT16:
157 variant->SetAsInt16(value.data().get_int16_t());
158 break;
159 case nsIDataType::VTYPE_INT32:
160 variant->SetAsInt32(value.data().get_int32_t());
161 break;
162 case nsIDataType::VTYPE_UINT16:
163 variant->SetAsUint16(value.data().get_uint16_t());
164 break;
165 case nsIDataType::VTYPE_UINT32:
166 variant->SetAsUint32(value.data().get_uint32_t());
167 break;
168 case nsIDataType::VTYPE_FLOAT:
169 variant->SetAsFloat(value.data().get_float());
170 break;
171 case nsIDataType::VTYPE_DOUBLE:
172 variant->SetAsDouble(value.data().get_double());
173 break;
174 case nsIDataType::VTYPE_BOOL:
175 variant->SetAsBool(value.data().get_bool());
176 break;
177 case nsIDataType::VTYPE_CHAR:
178 variant->SetAsChar(value.data().get_uint8_t());
179 break;
180 case nsIDataType::VTYPE_WCHAR:
181 variant->SetAsWChar(value.data().get_int16_t());
182 break;
183 case nsIDataType::VTYPE_ID:
184 variant->SetAsID(value.data().get_nsID());
185 break;
186 case nsIDataType::VTYPE_ASTRING:
187 case nsIDataType::VTYPE_WCHAR_STR:
188 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
189 variant->SetAsAString(value.data().get_nsString());
190 break;
191 case nsIDataType::VTYPE_CSTRING:
192 case nsIDataType::VTYPE_CHAR_STR:
193 case nsIDataType::VTYPE_STRING_SIZE_IS:
194 variant->SetAsACString(value.data().get_nsCString());
195 break;
196 case nsIDataType::VTYPE_UTF8STRING:
197 variant->SetAsAUTF8String(value.data().get_nsCString());
198 break;
199 case nsIDataType::VTYPE_INTERFACE:
200 case nsIDataType::VTYPE_INTERFACE_IS:
201 if (value.data().type() == IPDLVariantValue::TnsIURI) {
202 variant->SetAsISupports(value.data().get_nsIURI());
203 } else if (value.data().type() == IPDLVariantValue::TnsIPrincipal) {
204 variant->SetAsISupports(value.data().get_nsIPrincipal());
205 } else {
206 MOZ_CRASH("Unexpected interface type");
208 break;
209 case nsIDataType::VTYPE_VOID:
210 variant->SetAsVoid();
211 break;
212 case nsIDataType::VTYPE_EMPTY:
213 break;
214 default:
215 MOZ_CRASH("Non handled variant type, patch welcome");
216 return false;
218 *aResult = std::move(variant);
219 return true;
222 void IPDLParamTraits<nsIPropertyBag2*>::Write(MessageWriter* aWriter,
223 IProtocol* aActor,
224 nsIPropertyBag2* aParam) {
225 // We send a nsIPropertyBag as an array of IPDLProperty
226 nsTArray<IPDLProperty> bag;
228 nsCOMPtr<nsISimpleEnumerator> enumerator;
229 if (aParam &&
230 NS_SUCCEEDED(aParam->GetEnumerator(getter_AddRefs(enumerator)))) {
231 for (auto& property : SimpleEnumerator<nsIProperty>(enumerator)) {
232 nsString name;
233 nsCOMPtr<nsIVariant> value;
234 MOZ_ALWAYS_SUCCEEDS(property->GetName(name));
235 MOZ_ALWAYS_SUCCEEDS(property->GetValue(getter_AddRefs(value)));
236 bag.AppendElement(IPDLProperty{name, value});
239 WriteIPDLParam(aWriter, aActor, bag);
242 bool IPDLParamTraits<nsIPropertyBag2*>::Read(MessageReader* aReader,
243 IProtocol* aActor,
244 RefPtr<nsIPropertyBag2>* aResult) {
245 nsTArray<IPDLProperty> bag;
246 if (!ReadIPDLParam(aReader, aActor, &bag)) {
247 return false;
250 auto properties = MakeRefPtr<nsHashPropertyBag>();
252 for (auto& entry : bag) {
253 nsCOMPtr<nsIVariant> variant = std::move(entry.value());
254 MOZ_ALWAYS_SUCCEEDS(
255 properties->SetProperty(std::move(entry.name()), variant));
257 *aResult = std::move(properties);
258 return true;
261 } // namespace mozilla::ipc