зеркало из https://github.com/mozilla/gecko-dev.git
263 строки
8.2 KiB
C++
263 строки
8.2 KiB
C++
/* -*- 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;
|
|
|
|
namespace mozilla {
|
|
namespace ipc {
|
|
|
|
void IPDLParamTraits<nsIVariant*>::Write(Message* aMsg, 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(aMsg, aActor, variant);
|
|
}
|
|
|
|
bool IPDLParamTraits<nsIVariant*>::Read(const Message* aMsg,
|
|
PickleIterator* aIter,
|
|
IProtocol* aActor,
|
|
RefPtr<nsIVariant>* aResult) {
|
|
IDPLVariant value;
|
|
if (!ReadIPDLParam(aMsg, aIter, 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(Message* aMsg, 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(aMsg, aActor, bag);
|
|
}
|
|
|
|
bool IPDLParamTraits<nsIPropertyBag2*>::Read(const Message* aMsg,
|
|
PickleIterator* aIter,
|
|
IProtocol* aActor,
|
|
RefPtr<nsIPropertyBag2>* aResult) {
|
|
nsTArray<IPDLProperty> bag;
|
|
if (!ReadIPDLParam(aMsg, aIter, 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 ipc
|
|
} // namespace mozilla
|