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"
12 #include "nsHashPropertyBag.h"
14 #include "nsIProperty.h"
16 #include "nsVariant.h"
19 using namespace mozilla::dom
;
21 namespace mozilla::ipc
{
23 void IPDLParamTraits
<nsIVariant
*>::Write(MessageWriter
* aWriter
,
28 variant
.type() = aParam
->GetDataType();
30 switch (variant
.type()) {
31 case nsIDataType::VTYPE_INT8
:
32 case nsIDataType::VTYPE_UINT8
:
33 case nsIDataType::VTYPE_CHAR
: {
35 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsUint8(&value
));
36 variant
.data() = value
;
39 case nsIDataType::VTYPE_WCHAR
:
40 case nsIDataType::VTYPE_INT16
: {
42 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsInt16(&value
));
43 variant
.data() = value
;
46 case nsIDataType::VTYPE_UINT16
: {
48 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsUint16(&value
));
49 variant
.data() = value
;
52 case nsIDataType::VTYPE_INT32
: {
54 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsInt32(&value
));
55 variant
.data() = value
;
58 case nsIDataType::VTYPE_UINT32
: {
60 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsUint32(&value
));
61 variant
.data() = value
;
64 case nsIDataType::VTYPE_FLOAT
: {
66 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsFloat(&value
));
67 variant
.data() = value
;
70 case nsIDataType::VTYPE_DOUBLE
: {
72 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsDouble(&value
));
73 variant
.data() = value
;
76 case nsIDataType::VTYPE_BOOL
: {
78 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsBool(&value
));
79 variant
.data() = value
;
82 case nsIDataType::VTYPE_ID
: {
84 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsID(&value
));
85 variant
.data() = value
;
88 case nsIDataType::VTYPE_ASTRING
:
89 case nsIDataType::VTYPE_WCHAR_STR
:
90 case nsIDataType::VTYPE_WSTRING_SIZE_IS
: {
92 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsAString(value
));
93 variant
.data() = value
;
96 case nsIDataType::VTYPE_CSTRING
:
97 case nsIDataType::VTYPE_CHAR_STR
:
98 case nsIDataType::VTYPE_STRING_SIZE_IS
:
99 case nsIDataType::VTYPE_UTF8STRING
: {
101 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsACString(value
));
102 variant
.data() = value
;
105 case nsIDataType::VTYPE_INTERFACE
:
106 case nsIDataType::VTYPE_INTERFACE_IS
: {
108 nsCOMPtr
<nsISupports
> value
;
109 MOZ_ALWAYS_SUCCEEDS(aParam
->GetAsInterface(&iid
, getter_AddRefs(value
)));
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
;
117 variant
.type() = nsIDataType::VTYPE_EMPTY
;
118 variant
.data() = false; // because we need something.
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;
126 case nsIDataType::VTYPE_VOID
:
127 case nsIDataType::VTYPE_EMPTY
:
128 variant
.data() = false; // because we need something.
131 MOZ_CRASH("Non handled variant type, patch welcome");
134 WriteIPDLParam(aWriter
, aActor
, variant
);
137 bool IPDLParamTraits
<nsIVariant
*>::Read(MessageReader
* aReader
,
139 RefPtr
<nsIVariant
>* aResult
) {
141 if (!ReadIPDLParam(aReader
, aActor
, &value
)) {
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());
153 variant
->SetAsUint8(value
.data().get_uint8_t());
156 case nsIDataType::VTYPE_INT16
:
157 variant
->SetAsInt16(value
.data().get_int16_t());
159 case nsIDataType::VTYPE_INT32
:
160 variant
->SetAsInt32(value
.data().get_int32_t());
162 case nsIDataType::VTYPE_UINT16
:
163 variant
->SetAsUint16(value
.data().get_uint16_t());
165 case nsIDataType::VTYPE_UINT32
:
166 variant
->SetAsUint32(value
.data().get_uint32_t());
168 case nsIDataType::VTYPE_FLOAT
:
169 variant
->SetAsFloat(value
.data().get_float());
171 case nsIDataType::VTYPE_DOUBLE
:
172 variant
->SetAsDouble(value
.data().get_double());
174 case nsIDataType::VTYPE_BOOL
:
175 variant
->SetAsBool(value
.data().get_bool());
177 case nsIDataType::VTYPE_CHAR
:
178 variant
->SetAsChar(value
.data().get_uint8_t());
180 case nsIDataType::VTYPE_WCHAR
:
181 variant
->SetAsWChar(value
.data().get_int16_t());
183 case nsIDataType::VTYPE_ID
:
184 variant
->SetAsID(value
.data().get_nsID());
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());
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());
196 case nsIDataType::VTYPE_UTF8STRING
:
197 variant
->SetAsAUTF8String(value
.data().get_nsCString());
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());
206 MOZ_CRASH("Unexpected interface type");
209 case nsIDataType::VTYPE_VOID
:
210 variant
->SetAsVoid();
212 case nsIDataType::VTYPE_EMPTY
:
215 MOZ_CRASH("Non handled variant type, patch welcome");
218 *aResult
= std::move(variant
);
222 void IPDLParamTraits
<nsIPropertyBag2
*>::Write(MessageWriter
* aWriter
,
224 nsIPropertyBag2
* aParam
) {
225 // We send a nsIPropertyBag as an array of IPDLProperty
226 nsTArray
<IPDLProperty
> bag
;
228 nsCOMPtr
<nsISimpleEnumerator
> enumerator
;
230 NS_SUCCEEDED(aParam
->GetEnumerator(getter_AddRefs(enumerator
)))) {
231 for (auto& property
: SimpleEnumerator
<nsIProperty
>(enumerator
)) {
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
,
244 RefPtr
<nsIPropertyBag2
>* aResult
) {
245 nsTArray
<IPDLProperty
> bag
;
246 if (!ReadIPDLParam(aReader
, aActor
, &bag
)) {
250 auto properties
= MakeRefPtr
<nsHashPropertyBag
>();
252 for (auto& entry
: bag
) {
253 nsCOMPtr
<nsIVariant
> variant
= std::move(entry
.value());
255 properties
->SetProperty(std::move(entry
.name()), variant
));
257 *aResult
= std::move(properties
);
261 } // namespace mozilla::ipc