PropertyBagUtils.cpp (8131B)
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/. */ 6 7 #include "PropertyBagUtils.h" 8 9 #include "ipc/IPCMessageUtilsSpecializations.h" 10 #include "mozilla/SimpleEnumerator.h" 11 #include "mozilla/dom/DOMTypes.h" 12 #include "nsCOMPtr.h" 13 #include "nsHashPropertyBag.h" 14 #include "nsID.h" 15 #include "nsIProperty.h" 16 #include "nsIURI.h" 17 #include "nsVariant.h" 18 19 using namespace mozilla::dom; 20 21 namespace IPC { 22 23 void ParamTraits<nsIVariant*>::Write(MessageWriter* aWriter, 24 nsIVariant* aParam) { 25 IDPLVariant variant; 26 27 variant.type() = aParam->GetDataType(); 28 29 switch (variant.type()) { 30 case nsIDataType::VTYPE_INT8: 31 case nsIDataType::VTYPE_UINT8: 32 case nsIDataType::VTYPE_CHAR: { 33 uint8_t value; 34 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint8(&value)); 35 variant.data() = value; 36 break; 37 } 38 case nsIDataType::VTYPE_WCHAR: 39 case nsIDataType::VTYPE_INT16: { 40 int16_t value; 41 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInt16(&value)); 42 variant.data() = value; 43 break; 44 } 45 case nsIDataType::VTYPE_UINT16: { 46 uint16_t value; 47 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint16(&value)); 48 variant.data() = value; 49 break; 50 } 51 case nsIDataType::VTYPE_INT32: { 52 int32_t value; 53 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInt32(&value)); 54 variant.data() = value; 55 break; 56 } 57 case nsIDataType::VTYPE_UINT32: { 58 uint32_t value; 59 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsUint32(&value)); 60 variant.data() = value; 61 break; 62 } 63 case nsIDataType::VTYPE_FLOAT: { 64 float value; 65 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsFloat(&value)); 66 variant.data() = value; 67 break; 68 } 69 case nsIDataType::VTYPE_DOUBLE: { 70 double value; 71 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsDouble(&value)); 72 variant.data() = value; 73 break; 74 } 75 case nsIDataType::VTYPE_BOOL: { 76 bool value; 77 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsBool(&value)); 78 variant.data() = value; 79 break; 80 } 81 case nsIDataType::VTYPE_ID: { 82 nsID value; 83 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsID(&value)); 84 variant.data() = value; 85 break; 86 } 87 case nsIDataType::VTYPE_ASTRING: 88 case nsIDataType::VTYPE_WCHAR_STR: 89 case nsIDataType::VTYPE_WSTRING_SIZE_IS: { 90 nsString value; 91 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsAString(value)); 92 variant.data() = value; 93 break; 94 } 95 case nsIDataType::VTYPE_CSTRING: 96 case nsIDataType::VTYPE_CHAR_STR: 97 case nsIDataType::VTYPE_STRING_SIZE_IS: 98 case nsIDataType::VTYPE_UTF8STRING: { 99 nsCString value; 100 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsACString(value)); 101 variant.data() = value; 102 break; 103 } 104 case nsIDataType::VTYPE_INTERFACE: 105 case nsIDataType::VTYPE_INTERFACE_IS: { 106 nsIID* iid; 107 nsCOMPtr<nsISupports> value; 108 MOZ_ALWAYS_SUCCEEDS(aParam->GetAsInterface(&iid, getter_AddRefs(value))); 109 free(iid); 110 // We only accept nsIURI and nsIPrincipal interface types, patch welcome. 111 if (nsCOMPtr<nsIURI> uri = do_QueryInterface(value)) { 112 variant.data() = uri; 113 } else if (nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(value)) { 114 variant.data() = principal; 115 } else if (value) { 116 variant.type() = nsIDataType::VTYPE_EMPTY; 117 variant.data() = false; // because we need something. 118 } else { 119 // Let's pretend like we had a null URI, though how do we know 120 // it wasn't a null principal? 121 variant.data() = (nsIURI*)nullptr; 122 } 123 break; 124 } 125 case nsIDataType::VTYPE_VOID: 126 case nsIDataType::VTYPE_EMPTY: 127 variant.data() = false; // because we need something. 128 break; 129 default: 130 MOZ_CRASH("Non handled variant type, patch welcome"); 131 break; 132 } 133 WriteParam(aWriter, variant); 134 } 135 136 bool ParamTraits<nsIVariant*>::Read(MessageReader* aReader, 137 RefPtr<nsIVariant>* aResult) { 138 IDPLVariant value; 139 if (!ReadParam(aReader, &value)) { 140 return false; 141 } 142 143 auto variant = mozilla::MakeRefPtr<nsVariant>(); 144 145 switch (value.type()) { 146 case nsIDataType::VTYPE_INT8: 147 case nsIDataType::VTYPE_UINT8: 148 if (value.type() == nsIDataType::VTYPE_INT8) { 149 variant->SetAsInt8(value.data().get_uint8_t()); 150 } else { 151 variant->SetAsUint8(value.data().get_uint8_t()); 152 } 153 break; 154 case nsIDataType::VTYPE_INT16: 155 variant->SetAsInt16(value.data().get_int16_t()); 156 break; 157 case nsIDataType::VTYPE_INT32: 158 variant->SetAsInt32(value.data().get_int32_t()); 159 break; 160 case nsIDataType::VTYPE_UINT16: 161 variant->SetAsUint16(value.data().get_uint16_t()); 162 break; 163 case nsIDataType::VTYPE_UINT32: 164 variant->SetAsUint32(value.data().get_uint32_t()); 165 break; 166 case nsIDataType::VTYPE_FLOAT: 167 variant->SetAsFloat(value.data().get_float()); 168 break; 169 case nsIDataType::VTYPE_DOUBLE: 170 variant->SetAsDouble(value.data().get_double()); 171 break; 172 case nsIDataType::VTYPE_BOOL: 173 variant->SetAsBool(value.data().get_bool()); 174 break; 175 case nsIDataType::VTYPE_CHAR: 176 variant->SetAsChar(value.data().get_uint8_t()); 177 break; 178 case nsIDataType::VTYPE_WCHAR: 179 variant->SetAsWChar(value.data().get_int16_t()); 180 break; 181 case nsIDataType::VTYPE_ID: 182 variant->SetAsID(value.data().get_nsID()); 183 break; 184 case nsIDataType::VTYPE_ASTRING: 185 case nsIDataType::VTYPE_WCHAR_STR: 186 case nsIDataType::VTYPE_WSTRING_SIZE_IS: 187 variant->SetAsAString(value.data().get_nsString()); 188 break; 189 case nsIDataType::VTYPE_CSTRING: 190 case nsIDataType::VTYPE_CHAR_STR: 191 case nsIDataType::VTYPE_STRING_SIZE_IS: 192 variant->SetAsACString(value.data().get_nsCString()); 193 break; 194 case nsIDataType::VTYPE_UTF8STRING: 195 variant->SetAsAUTF8String(value.data().get_nsCString()); 196 break; 197 case nsIDataType::VTYPE_INTERFACE: 198 case nsIDataType::VTYPE_INTERFACE_IS: 199 if (value.data().type() == IPDLVariantValue::TnsIURI) { 200 variant->SetAsISupports(value.data().get_nsIURI()); 201 } else if (value.data().type() == IPDLVariantValue::TnsIPrincipal) { 202 variant->SetAsISupports(value.data().get_nsIPrincipal()); 203 } else { 204 MOZ_CRASH("Unexpected interface type"); 205 } 206 break; 207 case nsIDataType::VTYPE_VOID: 208 variant->SetAsVoid(); 209 break; 210 case nsIDataType::VTYPE_EMPTY: 211 break; 212 default: 213 MOZ_CRASH("Non handled variant type, patch welcome"); 214 return false; 215 } 216 *aResult = std::move(variant); 217 return true; 218 } 219 220 void ParamTraits<nsIPropertyBag2*>::Write(MessageWriter* aWriter, 221 nsIPropertyBag2* aParam) { 222 // We send a nsIPropertyBag as an array of IPDLProperty 223 nsTArray<IPDLProperty> bag; 224 225 nsCOMPtr<nsISimpleEnumerator> enumerator; 226 if (aParam && 227 NS_SUCCEEDED(aParam->GetEnumerator(getter_AddRefs(enumerator)))) { 228 for (auto& property : mozilla::SimpleEnumerator<nsIProperty>(enumerator)) { 229 nsString name; 230 nsCOMPtr<nsIVariant> value; 231 MOZ_ALWAYS_SUCCEEDS(property->GetName(name)); 232 MOZ_ALWAYS_SUCCEEDS(property->GetValue(getter_AddRefs(value))); 233 bag.AppendElement(IPDLProperty{name, value}); 234 } 235 } 236 WriteParam(aWriter, bag); 237 } 238 239 bool ParamTraits<nsIPropertyBag2*>::Read(MessageReader* aReader, 240 RefPtr<nsIPropertyBag2>* aResult) { 241 nsTArray<IPDLProperty> bag; 242 if (!ReadParam(aReader, &bag)) { 243 return false; 244 } 245 246 auto properties = mozilla::MakeRefPtr<nsHashPropertyBag>(); 247 248 for (auto& entry : bag) { 249 nsCOMPtr<nsIVariant> variant = std::move(entry.value()); 250 MOZ_ALWAYS_SUCCEEDS( 251 properties->SetProperty(std::move(entry.name()), variant)); 252 } 253 *aResult = std::move(properties); 254 return true; 255 } 256 257 } // namespace IPC