tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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