summaryrefslogtreecommitdiffstats
path: root/dom/ipc/PropertyBagUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/ipc/PropertyBagUtils.cpp')
-rw-r--r--dom/ipc/PropertyBagUtils.cpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/dom/ipc/PropertyBagUtils.cpp b/dom/ipc/PropertyBagUtils.cpp
new file mode 100644
index 0000000000..6c1b3e8fea
--- /dev/null
+++ b/dom/ipc/PropertyBagUtils.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PropertyBagUtils.h"
+
+#include "mozilla/SimpleEnumerator.h"
+#include "mozilla/dom/DOMTypes.h"
+#include "nsCOMPtr.h"
+#include "nsHashPropertyBag.h"
+#include "nsID.h"
+#include "nsIProperty.h"
+#include "nsIURI.h"
+#include "nsVariant.h"
+
+using namespace IPC;
+using namespace mozilla::dom;
+
+namespace mozilla::ipc {
+
+void IPDLParamTraits<nsIVariant*>::Write(MessageWriter* aWriter,
+ IProtocol* aActor,
+ nsIVariant* aParam) {
+ IDPLVariant variant;
+
+ variant.type() = aParam->GetDataType();
+
+ switch (variant.type()) {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_CHAR: {
+ uint8_t value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint8(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ case nsIDataType::VTYPE_INT16: {
+ int16_t value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInt16(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_UINT16: {
+ uint16_t value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint16(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_INT32: {
+ int32_t value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInt32(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_UINT32: {
+ uint32_t value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint32(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_FLOAT: {
+ float value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsFloat(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_DOUBLE: {
+ double value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsDouble(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_BOOL: {
+ bool value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsBool(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_ID: {
+ nsID value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsID(&value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS: {
+ nsString value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsAString(value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_UTF8STRING: {
+ nsCString value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsACString(value));
+ variant.data() = value;
+ break;
+ }
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS: {
+ nsIID* iid;
+ nsCOMPtr<nsISupports> value;
+ MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInterface(&iid, getter_AddRefs(value)));
+ free(iid);
+ // We only accept nsIURI and nsIPrincipal interface types, patch welcome.
+ if (nsCOMPtr<nsIURI> uri = do_QueryInterface(value)) {
+ variant.data() = uri;
+ } else if (nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(value)) {
+ variant.data() = principal;
+ } else if (value) {
+ variant.type() = nsIDataType::VTYPE_EMPTY;
+ variant.data() = false; // because we need something.
+ } else {
+ // Let's pretend like we had a null URI, though how do we know
+ // it wasn't a null principal?
+ variant.data() = (nsIURI*)nullptr;
+ }
+ break;
+ }
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_EMPTY:
+ variant.data() = false; // because we need something.
+ break;
+ default:
+ MOZ_CRASH("Non handled variant type, patch welcome");
+ break;
+ }
+ WriteIPDLParam(aWriter, aActor, variant);
+}
+
+bool IPDLParamTraits<nsIVariant*>::Read(MessageReader* aReader,
+ IProtocol* aActor,
+ RefPtr<nsIVariant>* aResult) {
+ IDPLVariant value;
+ if (!ReadIPDLParam(aReader, aActor, &value)) {
+ return false;
+ }
+
+ auto variant = MakeRefPtr<nsVariant>();
+
+ switch (value.type()) {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_UINT8:
+ if (value.type() == nsIDataType::VTYPE_INT8) {
+ variant->SetAsInt8(value.data().get_uint8_t());
+ } else {
+ variant->SetAsUint8(value.data().get_uint8_t());
+ }
+ break;
+ case nsIDataType::VTYPE_INT16:
+ variant->SetAsInt16(value.data().get_int16_t());
+ break;
+ case nsIDataType::VTYPE_INT32:
+ variant->SetAsInt32(value.data().get_int32_t());
+ break;
+ case nsIDataType::VTYPE_UINT16:
+ variant->SetAsUint16(value.data().get_uint16_t());
+ break;
+ case nsIDataType::VTYPE_UINT32:
+ variant->SetAsUint32(value.data().get_uint32_t());
+ break;
+ case nsIDataType::VTYPE_FLOAT:
+ variant->SetAsFloat(value.data().get_float());
+ break;
+ case nsIDataType::VTYPE_DOUBLE:
+ variant->SetAsDouble(value.data().get_double());
+ break;
+ case nsIDataType::VTYPE_BOOL:
+ variant->SetAsBool(value.data().get_bool());
+ break;
+ case nsIDataType::VTYPE_CHAR:
+ variant->SetAsChar(value.data().get_uint8_t());
+ break;
+ case nsIDataType::VTYPE_WCHAR:
+ variant->SetAsWChar(value.data().get_int16_t());
+ break;
+ case nsIDataType::VTYPE_ID:
+ variant->SetAsID(value.data().get_nsID());
+ break;
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ variant->SetAsAString(value.data().get_nsString());
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ variant->SetAsACString(value.data().get_nsCString());
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ variant->SetAsAUTF8String(value.data().get_nsCString());
+ break;
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ if (value.data().type() == IPDLVariantValue::TnsIURI) {
+ variant->SetAsISupports(value.data().get_nsIURI());
+ } else if (value.data().type() == IPDLVariantValue::TnsIPrincipal) {
+ variant->SetAsISupports(value.data().get_nsIPrincipal());
+ } else {
+ MOZ_CRASH("Unexpected interface type");
+ }
+ break;
+ case nsIDataType::VTYPE_VOID:
+ variant->SetAsVoid();
+ break;
+ case nsIDataType::VTYPE_EMPTY:
+ break;
+ default:
+ MOZ_CRASH("Non handled variant type, patch welcome");
+ return false;
+ }
+ *aResult = std::move(variant);
+ return true;
+}
+
+void IPDLParamTraits<nsIPropertyBag2*>::Write(MessageWriter* aWriter,
+ IProtocol* aActor,
+ nsIPropertyBag2* aParam) {
+ // We send a nsIPropertyBag as an array of IPDLProperty
+ nsTArray<IPDLProperty> bag;
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ if (aParam &&
+ NS_SUCCEEDED(aParam->GetEnumerator(getter_AddRefs(enumerator)))) {
+ for (auto& property : SimpleEnumerator<nsIProperty>(enumerator)) {
+ nsString name;
+ nsCOMPtr<nsIVariant> value;
+ MOZ_ALWAYS_SUCCEEDS(property->GetName(name));
+ MOZ_ALWAYS_SUCCEEDS(property->GetValue(getter_AddRefs(value)));
+ bag.AppendElement(IPDLProperty{name, value});
+ }
+ }
+ WriteIPDLParam(aWriter, aActor, bag);
+}
+
+bool IPDLParamTraits<nsIPropertyBag2*>::Read(MessageReader* aReader,
+ IProtocol* aActor,
+ RefPtr<nsIPropertyBag2>* aResult) {
+ nsTArray<IPDLProperty> bag;
+ if (!ReadIPDLParam(aReader, aActor, &bag)) {
+ return false;
+ }
+
+ auto properties = MakeRefPtr<nsHashPropertyBag>();
+
+ for (auto& entry : bag) {
+ nsCOMPtr<nsIVariant> variant = std::move(entry.value());
+ MOZ_ALWAYS_SUCCEEDS(
+ properties->SetProperty(std::move(entry.name()), variant));
+ }
+ *aResult = std::move(properties);
+ return true;
+}
+
+} // namespace mozilla::ipc