diff options
Diffstat (limited to 'dom/ipc/PropertyBagUtils.cpp')
-rw-r--r-- | dom/ipc/PropertyBagUtils.cpp | 261 |
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 |