LCOV - code coverage report
Current view: top level - js/xpconnect/src - XPCVariant.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 85 361 23.5 %
Date: 2017-07-14 16:53:18 Functions: 14 42 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
       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             : /* nsIVariant implementation for xpconnect. */
       8             : 
       9             : #include "mozilla/Range.h"
      10             : 
      11             : #include "xpcprivate.h"
      12             : 
      13             : #include "jsfriendapi.h"
      14             : #include "jsprf.h"
      15             : #include "jswrapper.h"
      16             : 
      17             : using namespace JS;
      18             : using namespace mozilla;
      19             : 
      20           3 : NS_IMPL_CLASSINFO(XPCVariant, nullptr, 0, XPCVARIANT_CID)
      21          21 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCVariant)
      22           6 :   NS_INTERFACE_MAP_ENTRY(XPCVariant)
      23           6 :   NS_INTERFACE_MAP_ENTRY(nsIVariant)
      24           3 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      25           3 :   NS_IMPL_QUERY_CLASSINFO(XPCVariant)
      26           3 : NS_INTERFACE_MAP_END
      27           0 : NS_IMPL_CI_INTERFACE_GETTER(XPCVariant, XPCVariant, nsIVariant)
      28             : 
      29           6 : NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant)
      30           9 : NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant)
      31             : 
      32           3 : XPCVariant::XPCVariant(JSContext* cx, const Value& aJSVal)
      33           3 :     : mJSVal(aJSVal), mCCGeneration(0)
      34             : {
      35           3 :     if (!mJSVal.isPrimitive()) {
      36             :         // XXXbholley - The innerization here was from bug 638026. Blake says
      37             :         // the basic problem was that we were storing the C++ inner but the JS
      38             :         // outer, which meant that, after navigation, the JS inner could be
      39             :         // collected, which would cause us to try to recreate the JS inner at
      40             :         // some later point after teardown, which would crash. This is shouldn't
      41             :         // be a problem anymore because SetParentToWindow will do the right
      42             :         // thing, but I'm saving the cleanup here for another day. Blake thinks
      43             :         // that we should just not store the WN if we're creating a variant for
      44             :         // an outer window.
      45           0 :         JSObject* obj = js::ToWindowIfWindowProxy(&mJSVal.toObject());
      46           0 :         mJSVal = JS::ObjectValue(*obj);
      47             : 
      48           0 :         JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
      49           0 :         mReturnRawObject = !(unwrapped && IS_WN_REFLECTOR(unwrapped));
      50             :     } else
      51           3 :         mReturnRawObject = false;
      52           3 : }
      53             : 
      54           6 : XPCTraceableVariant::~XPCTraceableVariant()
      55             : {
      56           2 :     Value val = GetJSValPreserveColor();
      57             : 
      58           2 :     MOZ_ASSERT(val.isGCThing() || val.isNull(), "Must be traceable or unlinked");
      59             : 
      60           2 :     mData.Cleanup();
      61             : 
      62           2 :     if (!val.isNull())
      63           2 :         RemoveFromRootSet();
      64           6 : }
      65             : 
      66           2 : void XPCTraceableVariant::TraceJS(JSTracer* trc)
      67             : {
      68           2 :     MOZ_ASSERT(GetJSValPreserveColor().isGCThing());
      69           2 :     JS::TraceEdge(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
      70           2 : }
      71             : 
      72             : NS_IMPL_CYCLE_COLLECTION_CLASS(XPCVariant)
      73             : 
      74           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPCVariant)
      75           0 :     JS::Value val = tmp->GetJSValPreserveColor();
      76           0 :     if (val.isObject()) {
      77           0 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mJSVal");
      78           0 :         cb.NoteJSChild(JS::GCCellPtr(val));
      79             :     }
      80             : 
      81           0 :     tmp->mData.Traverse(cb);
      82           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      83             : 
      84           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant)
      85           0 :     JS::Value val = tmp->GetJSValPreserveColor();
      86             : 
      87           0 :     tmp->mData.Cleanup();
      88             : 
      89           0 :     if (val.isGCThing()) {
      90           0 :         XPCTraceableVariant* v = static_cast<XPCTraceableVariant*>(tmp);
      91           0 :         v->RemoveFromRootSet();
      92             :     }
      93           0 :     tmp->mJSVal = JS::NullValue();
      94           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      95             : 
      96             : // static
      97             : already_AddRefed<XPCVariant>
      98           3 : XPCVariant::newVariant(JSContext* cx, const Value& aJSVal)
      99             : {
     100           6 :     RefPtr<XPCVariant> variant;
     101             : 
     102           3 :     if (!aJSVal.isGCThing())
     103           1 :         variant = new XPCVariant(cx, aJSVal);
     104             :     else
     105           2 :         variant = new XPCTraceableVariant(cx, aJSVal);
     106             : 
     107           3 :     if (!variant->InitializeData(cx))
     108           0 :         return nullptr;
     109             : 
     110           3 :     return variant.forget();
     111             : }
     112             : 
     113             : // Helper class to give us a namespace for the table based code below.
     114             : class XPCArrayHomogenizer
     115             : {
     116             : private:
     117             :     enum Type
     118             :     {
     119             :         tNull  = 0 ,  // null value
     120             :         tInt       ,  // Integer
     121             :         tDbl       ,  // Double
     122             :         tBool      ,  // Boolean
     123             :         tStr       ,  // String
     124             :         tID        ,  // ID
     125             :         tArr       ,  // Array
     126             :         tISup      ,  // nsISupports (really just a plain JSObject)
     127             :         tUnk       ,  // Unknown. Used only for initial state.
     128             : 
     129             :         tTypeCount ,  // Just a count for table dimensioning.
     130             : 
     131             :         tVar       ,  // nsVariant - last ditch if no other common type found.
     132             :         tErr          // No valid state or type has this value.
     133             :     };
     134             : 
     135             :     // Table has tUnk as a state (column) but not as a type (row).
     136             :     static const Type StateTable[tTypeCount][tTypeCount-1];
     137             : 
     138             : public:
     139             :     static bool GetTypeForArray(JSContext* cx, HandleObject array,
     140             :                                 uint32_t length,
     141             :                                 nsXPTType* resultType, nsID* resultID);
     142             : };
     143             : 
     144             : 
     145             : // Current state is the column down the side.
     146             : // Current type is the row along the top.
     147             : // New state is in the box at the intersection.
     148             : 
     149             : const XPCArrayHomogenizer::Type
     150             : XPCArrayHomogenizer::StateTable[tTypeCount][tTypeCount-1] = {
     151             : /*          tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tArr ,tISup */
     152             : /* tNull */{tNull,tVar ,tVar ,tVar ,tStr ,tID  ,tVar ,tISup },
     153             : /* tInt  */{tVar ,tInt ,tDbl ,tVar ,tVar ,tVar ,tVar ,tVar  },
     154             : /* tDbl  */{tVar ,tDbl ,tDbl ,tVar ,tVar ,tVar ,tVar ,tVar  },
     155             : /* tBool */{tVar ,tVar ,tVar ,tBool,tVar ,tVar ,tVar ,tVar  },
     156             : /* tStr  */{tStr ,tVar ,tVar ,tVar ,tStr ,tVar ,tVar ,tVar  },
     157             : /* tID   */{tID  ,tVar ,tVar ,tVar ,tVar ,tID  ,tVar ,tVar  },
     158             : /* tArr  */{tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr  },
     159             : /* tISup */{tISup,tVar ,tVar ,tVar ,tVar ,tVar ,tVar ,tISup },
     160             : /* tUnk  */{tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tVar ,tISup }};
     161             : 
     162             : // static
     163             : bool
     164           0 : XPCArrayHomogenizer::GetTypeForArray(JSContext* cx, HandleObject array,
     165             :                                      uint32_t length,
     166             :                                      nsXPTType* resultType, nsID* resultID)
     167             : {
     168           0 :     Type state = tUnk;
     169             :     Type type;
     170             : 
     171           0 :     RootedValue val(cx);
     172           0 :     RootedObject jsobj(cx);
     173           0 :     for (uint32_t i = 0; i < length; i++) {
     174           0 :         if (!JS_GetElement(cx, array, i, &val))
     175           0 :             return false;
     176             : 
     177           0 :         if (val.isInt32()) {
     178           0 :             type = tInt;
     179           0 :         } else if (val.isDouble()) {
     180           0 :             type = tDbl;
     181           0 :         } else if (val.isBoolean()) {
     182           0 :             type = tBool;
     183           0 :         } else if (val.isUndefined() || val.isSymbol()) {
     184           0 :             state = tVar;
     185           0 :             break;
     186           0 :         } else if (val.isNull()) {
     187           0 :             type = tNull;
     188           0 :         } else if (val.isString()) {
     189           0 :             type = tStr;
     190             :         } else {
     191           0 :             MOZ_ASSERT(val.isObject(), "invalid type of jsval!");
     192           0 :             jsobj = &val.toObject();
     193             : 
     194             :             bool isArray;
     195           0 :             if (!JS_IsArrayObject(cx, jsobj, &isArray))
     196           0 :                 return false;
     197             : 
     198           0 :             if (isArray)
     199           0 :                 type = tArr;
     200           0 :             else if (xpc_JSObjectIsID(cx, jsobj))
     201           0 :                 type = tID;
     202             :             else
     203           0 :                 type = tISup;
     204             :         }
     205             : 
     206           0 :         MOZ_ASSERT(state != tErr, "bad state table!");
     207           0 :         MOZ_ASSERT(type  != tErr, "bad type!");
     208           0 :         MOZ_ASSERT(type  != tVar, "bad type!");
     209           0 :         MOZ_ASSERT(type  != tUnk, "bad type!");
     210             : 
     211           0 :         state = StateTable[state][type];
     212             : 
     213           0 :         MOZ_ASSERT(state != tErr, "bad state table!");
     214           0 :         MOZ_ASSERT(state != tUnk, "bad state table!");
     215             : 
     216           0 :         if (state == tVar)
     217           0 :             break;
     218             :     }
     219             : 
     220           0 :     switch (state) {
     221             :         case tInt :
     222           0 :             *resultType = nsXPTType((uint8_t)TD_INT32);
     223           0 :             break;
     224             :         case tDbl :
     225           0 :             *resultType = nsXPTType((uint8_t)TD_DOUBLE);
     226           0 :             break;
     227             :         case tBool:
     228           0 :             *resultType = nsXPTType((uint8_t)TD_BOOL);
     229           0 :             break;
     230             :         case tStr :
     231           0 :             *resultType = nsXPTType((uint8_t)TD_PWSTRING);
     232           0 :             break;
     233             :         case tID  :
     234           0 :             *resultType = nsXPTType((uint8_t)TD_PNSIID);
     235           0 :             break;
     236             :         case tISup:
     237           0 :             *resultType = nsXPTType((uint8_t)TD_INTERFACE_IS_TYPE);
     238           0 :             *resultID = NS_GET_IID(nsISupports);
     239           0 :             break;
     240             :         case tNull:
     241             :             // FALL THROUGH
     242             :         case tVar :
     243           0 :             *resultType = nsXPTType((uint8_t)TD_INTERFACE_IS_TYPE);
     244           0 :             *resultID = NS_GET_IID(nsIVariant);
     245           0 :             break;
     246             :         case tArr :
     247             :             // FALL THROUGH
     248             :         case tUnk :
     249             :             // FALL THROUGH
     250             :         case tErr :
     251             :             // FALL THROUGH
     252             :         default:
     253           0 :             NS_ERROR("bad state");
     254           0 :             return false;
     255             :     }
     256           0 :     return true;
     257             : }
     258             : 
     259           3 : bool XPCVariant::InitializeData(JSContext* cx)
     260             : {
     261           3 :     if (!js::CheckRecursionLimit(cx))
     262           0 :         return false;
     263             : 
     264           6 :     RootedValue val(cx, GetJSVal());
     265             : 
     266           3 :     if (val.isInt32()) {
     267           1 :         mData.SetFromInt32(val.toInt32());
     268           1 :         return true;
     269             :     }
     270           2 :     if (val.isDouble()) {
     271           0 :         mData.SetFromDouble(val.toDouble());
     272           0 :         return true;
     273             :     }
     274           2 :     if (val.isBoolean()) {
     275           0 :         mData.SetFromBool(val.toBoolean());
     276           0 :         return true;
     277             :     }
     278             :     // We can't represent symbol on C++ side, so pretend it is void.
     279           2 :     if (val.isUndefined() || val.isSymbol()) {
     280           0 :         mData.SetToVoid();
     281           0 :         return true;
     282             :     }
     283           2 :     if (val.isNull()) {
     284           0 :         mData.SetToEmpty();
     285           0 :         return true;
     286             :     }
     287           2 :     if (val.isString()) {
     288           2 :         JSString* str = val.toString();
     289           2 :         if (!str)
     290           0 :             return false;
     291             : 
     292           2 :         MOZ_ASSERT(mData.GetType() == nsIDataType::VTYPE_EMPTY,
     293             :                    "Why do we already have data?");
     294             : 
     295           2 :         size_t length = JS_GetStringLength(str);
     296           2 :         mData.AllocateWStringWithSize(length);
     297             : 
     298           2 :         mozilla::Range<char16_t> destChars(mData.u.wstr.mWStringValue, length);
     299           2 :         if (!JS_CopyStringChars(cx, destChars, str))
     300           0 :             return false;
     301             : 
     302           2 :         MOZ_ASSERT(mData.u.wstr.mWStringValue[length] == '\0');
     303           2 :         return true;
     304             :     }
     305             : 
     306             :     // leaving only JSObject...
     307           0 :     MOZ_ASSERT(val.isObject(), "invalid type of jsval!");
     308             : 
     309           0 :     RootedObject jsobj(cx, &val.toObject());
     310             : 
     311             :     // Let's see if it is a xpcJSID.
     312             : 
     313           0 :     const nsID* id = xpc_JSObjectToID(cx, jsobj);
     314           0 :     if (id) {
     315           0 :         mData.SetFromID(*id);
     316           0 :         return true;
     317             :     }
     318             : 
     319             :     // Let's see if it is a js array object.
     320             : 
     321             :     uint32_t len;
     322             : 
     323             :     bool isArray;
     324           0 :     if (!JS_IsArrayObject(cx, jsobj, &isArray) ||
     325           0 :         (isArray && !JS_GetArrayLength(cx, jsobj, &len)))
     326             :     {
     327           0 :         return false;
     328             :     }
     329             : 
     330           0 :     if (isArray) {
     331           0 :         if (!len) {
     332             :             // Zero length array
     333           0 :             mData.SetToEmptyArray();
     334           0 :             return true;
     335             :         }
     336             : 
     337           0 :         nsXPTType type;
     338             :         nsID id;
     339             : 
     340           0 :         if (!XPCArrayHomogenizer::GetTypeForArray(cx, jsobj, len, &type, &id))
     341           0 :             return false;
     342             : 
     343           0 :         if (!XPCConvert::JSArray2Native(&mData.u.array.mArrayValue,
     344             :                                         val, len, type, &id, nullptr))
     345           0 :             return false;
     346             : 
     347           0 :         mData.mType = nsIDataType::VTYPE_ARRAY;
     348           0 :         if (type.IsInterfacePointer())
     349           0 :             mData.u.array.mArrayInterfaceID = id;
     350           0 :         mData.u.array.mArrayCount = len;
     351           0 :         mData.u.array.mArrayType = type.TagPart();
     352             : 
     353           0 :         return true;
     354             :     }
     355             : 
     356             :     // XXX This could be smarter and pick some more interesting iface.
     357             : 
     358           0 :     nsXPConnect*  xpc = nsXPConnect::XPConnect();
     359           0 :     nsCOMPtr<nsISupports> wrapper;
     360           0 :     const nsIID& iid = NS_GET_IID(nsISupports);
     361             : 
     362           0 :     if (NS_FAILED(xpc->WrapJS(cx, jsobj, iid, getter_AddRefs(wrapper)))) {
     363           0 :         return false;
     364             :     }
     365             : 
     366           0 :     mData.SetFromInterface(iid, wrapper);
     367           0 :     return true;
     368             : }
     369             : 
     370             : NS_IMETHODIMP
     371           0 : XPCVariant::GetAsJSVal(MutableHandleValue result)
     372             : {
     373           0 :   result.set(GetJSVal());
     374           0 :   return NS_OK;
     375             : }
     376             : 
     377             : // static
     378             : bool
     379          45 : XPCVariant::VariantDataToJS(nsIVariant* variant,
     380             :                             nsresult* pErr, MutableHandleValue pJSVal)
     381             : {
     382             :     // Get the type early because we might need to spoof it below.
     383             :     uint16_t type;
     384          45 :     if (NS_FAILED(variant->GetDataType(&type)))
     385           0 :         return false;
     386             : 
     387          90 :     AutoJSContext cx;
     388          90 :     RootedValue realVal(cx);
     389          45 :     nsresult rv = variant->GetAsJSVal(&realVal);
     390             : 
     391          45 :     if (NS_SUCCEEDED(rv) &&
     392           0 :         (realVal.isPrimitive() ||
     393           0 :          type == nsIDataType::VTYPE_ARRAY ||
     394           0 :          type == nsIDataType::VTYPE_EMPTY_ARRAY ||
     395           0 :          type == nsIDataType::VTYPE_ID)) {
     396           0 :         if (!JS_WrapValue(cx, &realVal))
     397           0 :             return false;
     398           0 :         pJSVal.set(realVal);
     399           0 :         return true;
     400             :     }
     401             : 
     402          90 :     nsCOMPtr<XPCVariant> xpcvariant = do_QueryInterface(variant);
     403          45 :     if (xpcvariant && xpcvariant->mReturnRawObject) {
     404           0 :         MOZ_ASSERT(type == nsIDataType::VTYPE_INTERFACE ||
     405             :                    type == nsIDataType::VTYPE_INTERFACE_IS,
     406             :                    "Weird variant");
     407             : 
     408           0 :         if (!JS_WrapValue(cx, &realVal))
     409           0 :             return false;
     410           0 :         pJSVal.set(realVal);
     411           0 :         return true;
     412             :     }
     413             : 
     414             :     // else, it's an object and we really need to double wrap it if we've
     415             :     // already decided that its 'natural' type is as some sort of interface.
     416             : 
     417             :     // We just fall through to the code below and let it do what it does.
     418             : 
     419             :     // The nsIVariant is not a XPCVariant (or we act like it isn't).
     420             :     // So we extract the data and do the Right Thing.
     421             : 
     422             :     // We ASSUME that the variant implementation can do these conversions...
     423             : 
     424             :     nsID iid;
     425             : 
     426          45 :     switch (type) {
     427             :         case nsIDataType::VTYPE_INT8:
     428             :         case nsIDataType::VTYPE_INT16:
     429             :         case nsIDataType::VTYPE_INT32:
     430             :         case nsIDataType::VTYPE_INT64:
     431             :         case nsIDataType::VTYPE_UINT8:
     432             :         case nsIDataType::VTYPE_UINT16:
     433             :         case nsIDataType::VTYPE_UINT32:
     434             :         case nsIDataType::VTYPE_UINT64:
     435             :         case nsIDataType::VTYPE_FLOAT:
     436             :         case nsIDataType::VTYPE_DOUBLE:
     437             :         {
     438             :             double d;
     439          15 :             if (NS_FAILED(variant->GetAsDouble(&d)))
     440           0 :                 return false;
     441          15 :             pJSVal.setNumber(d);
     442          15 :             return true;
     443             :         }
     444             :         case nsIDataType::VTYPE_BOOL:
     445             :         {
     446             :             bool b;
     447          15 :             if (NS_FAILED(variant->GetAsBool(&b)))
     448           0 :                 return false;
     449          15 :             pJSVal.setBoolean(b);
     450          15 :             return true;
     451             :         }
     452             :         case nsIDataType::VTYPE_CHAR:
     453             :         {
     454             :             char c;
     455           0 :             if (NS_FAILED(variant->GetAsChar(&c)))
     456           0 :                 return false;
     457           0 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&c, TD_CHAR, &iid, pErr);
     458             :         }
     459             :         case nsIDataType::VTYPE_WCHAR:
     460             :         {
     461             :             char16_t wc;
     462           0 :             if (NS_FAILED(variant->GetAsWChar(&wc)))
     463           0 :                 return false;
     464           0 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&wc, TD_WCHAR, &iid, pErr);
     465             :         }
     466             :         case nsIDataType::VTYPE_ID:
     467             :         {
     468           0 :             if (NS_FAILED(variant->GetAsID(&iid)))
     469           0 :                 return false;
     470           0 :             nsID* v = &iid;
     471           0 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, TD_PNSIID, &iid, pErr);
     472             :         }
     473             :         case nsIDataType::VTYPE_ASTRING:
     474             :         {
     475           8 :             nsAutoString astring;
     476           4 :             if (NS_FAILED(variant->GetAsAString(astring)))
     477           0 :                 return false;
     478           4 :             nsAutoString* v = &astring;
     479           4 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, TD_ASTRING, &iid, pErr);
     480             :         }
     481             :         case nsIDataType::VTYPE_DOMSTRING:
     482             :         {
     483           0 :             nsAutoString astring;
     484           0 :             if (NS_FAILED(variant->GetAsAString(astring)))
     485           0 :                 return false;
     486           0 :             nsAutoString* v = &astring;
     487           0 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
     488           0 :                                              TD_DOMSTRING, &iid, pErr);
     489             :         }
     490             :         case nsIDataType::VTYPE_CSTRING:
     491             :         {
     492          18 :             nsAutoCString cString;
     493           9 :             if (NS_FAILED(variant->GetAsACString(cString)))
     494           0 :                 return false;
     495           9 :             nsAutoCString* v = &cString;
     496          18 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
     497           9 :                                              TD_CSTRING, &iid, pErr);
     498             :         }
     499             :         case nsIDataType::VTYPE_UTF8STRING:
     500             :         {
     501           0 :             nsUTF8String utf8String;
     502           0 :             if (NS_FAILED(variant->GetAsAUTF8String(utf8String)))
     503           0 :                 return false;
     504           0 :             nsUTF8String* v = &utf8String;
     505           0 :             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
     506           0 :                                              TD_UTF8STRING, &iid, pErr);
     507             :         }
     508             :         case nsIDataType::VTYPE_CHAR_STR:
     509             :         {
     510             :             char* pc;
     511           0 :             if (NS_FAILED(variant->GetAsString(&pc)))
     512           0 :                 return false;
     513           0 :             bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pc,
     514           0 :                                                      TD_PSTRING, &iid, pErr);
     515           0 :             free(pc);
     516           0 :             return success;
     517             :         }
     518             :         case nsIDataType::VTYPE_STRING_SIZE_IS:
     519             :         {
     520             :             char* pc;
     521             :             uint32_t size;
     522           0 :             if (NS_FAILED(variant->GetAsStringWithSize(&size, &pc)))
     523           0 :                 return false;
     524           0 :             bool success = XPCConvert::NativeStringWithSize2JS(pJSVal, (const void*)&pc,
     525           0 :                                                                TD_PSTRING_SIZE_IS, size, pErr);
     526           0 :             free(pc);
     527           0 :             return success;
     528             :         }
     529             :         case nsIDataType::VTYPE_WCHAR_STR:
     530             :         {
     531             :             char16_t* pwc;
     532           0 :             if (NS_FAILED(variant->GetAsWString(&pwc)))
     533           0 :                 return false;
     534           0 :             bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pwc,
     535           0 :                                                      TD_PSTRING, &iid, pErr);
     536           0 :             free(pwc);
     537           0 :             return success;
     538             :         }
     539             :         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
     540             :         {
     541             :             char16_t* pwc;
     542             :             uint32_t size;
     543           0 :             if (NS_FAILED(variant->GetAsWStringWithSize(&size, &pwc)))
     544           0 :                 return false;
     545           0 :             bool success = XPCConvert::NativeStringWithSize2JS(pJSVal, (const void*)&pwc,
     546           0 :                                                                TD_PWSTRING_SIZE_IS, size, pErr);
     547           0 :             free(pwc);
     548           0 :             return success;
     549             :         }
     550             :         case nsIDataType::VTYPE_INTERFACE:
     551             :         case nsIDataType::VTYPE_INTERFACE_IS:
     552             :         {
     553             :             nsISupports* pi;
     554             :             nsID* piid;
     555           0 :             if (NS_FAILED(variant->GetAsInterface(&piid, (void**)&pi)))
     556           0 :                 return false;
     557             : 
     558           0 :             iid = *piid;
     559           0 :             free((char*)piid);
     560             : 
     561           0 :             bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pi,
     562           0 :                                                      TD_INTERFACE_IS_TYPE, &iid, pErr);
     563           0 :             if (pi)
     564           0 :                 pi->Release();
     565           0 :             return success;
     566             :         }
     567             :         case nsIDataType::VTYPE_ARRAY:
     568             :         {
     569           0 :             nsDiscriminatedUnion du;
     570             :             nsresult rv;
     571             : 
     572             :             rv = variant->GetAsArray(&du.u.array.mArrayType,
     573             :                                      &du.u.array.mArrayInterfaceID,
     574             :                                      &du.u.array.mArrayCount,
     575           0 :                                      &du.u.array.mArrayValue);
     576           0 :             if (NS_FAILED(rv))
     577           0 :                 return false;
     578             : 
     579             :             // must exit via VARIANT_DONE from here on...
     580           0 :             du.mType = nsIDataType::VTYPE_ARRAY;
     581             : 
     582           0 :             nsXPTType conversionType;
     583           0 :             uint16_t elementType = du.u.array.mArrayType;
     584           0 :             const nsID* pid = nullptr;
     585             : 
     586           0 :             switch (elementType) {
     587             :                 case nsIDataType::VTYPE_INT8:
     588             :                 case nsIDataType::VTYPE_INT16:
     589             :                 case nsIDataType::VTYPE_INT32:
     590             :                 case nsIDataType::VTYPE_INT64:
     591             :                 case nsIDataType::VTYPE_UINT8:
     592             :                 case nsIDataType::VTYPE_UINT16:
     593             :                 case nsIDataType::VTYPE_UINT32:
     594             :                 case nsIDataType::VTYPE_UINT64:
     595             :                 case nsIDataType::VTYPE_FLOAT:
     596             :                 case nsIDataType::VTYPE_DOUBLE:
     597             :                 case nsIDataType::VTYPE_BOOL:
     598             :                 case nsIDataType::VTYPE_CHAR:
     599             :                 case nsIDataType::VTYPE_WCHAR:
     600           0 :                     conversionType = nsXPTType((uint8_t)elementType);
     601           0 :                     break;
     602             : 
     603             :                 case nsIDataType::VTYPE_ID:
     604             :                 case nsIDataType::VTYPE_CHAR_STR:
     605             :                 case nsIDataType::VTYPE_WCHAR_STR:
     606           0 :                     conversionType = nsXPTType((uint8_t)elementType);
     607           0 :                     break;
     608             : 
     609             :                 case nsIDataType::VTYPE_INTERFACE:
     610           0 :                     pid = &NS_GET_IID(nsISupports);
     611           0 :                     conversionType = nsXPTType((uint8_t)elementType);
     612           0 :                     break;
     613             : 
     614             :                 case nsIDataType::VTYPE_INTERFACE_IS:
     615           0 :                     pid = &du.u.array.mArrayInterfaceID;
     616           0 :                     conversionType = nsXPTType((uint8_t)elementType);
     617           0 :                     break;
     618             : 
     619             :                 // The rest are illegal.
     620             :                 case nsIDataType::VTYPE_VOID:
     621             :                 case nsIDataType::VTYPE_ASTRING:
     622             :                 case nsIDataType::VTYPE_DOMSTRING:
     623             :                 case nsIDataType::VTYPE_CSTRING:
     624             :                 case nsIDataType::VTYPE_UTF8STRING:
     625             :                 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
     626             :                 case nsIDataType::VTYPE_STRING_SIZE_IS:
     627             :                 case nsIDataType::VTYPE_ARRAY:
     628             :                 case nsIDataType::VTYPE_EMPTY_ARRAY:
     629             :                 case nsIDataType::VTYPE_EMPTY:
     630             :                 default:
     631           0 :                     NS_ERROR("bad type in array!");
     632           0 :                     return false;
     633             :             }
     634             : 
     635             :             bool success =
     636           0 :                 XPCConvert::NativeArray2JS(pJSVal,
     637             :                                            (const void**)&du.u.array.mArrayValue,
     638             :                                            conversionType, pid,
     639           0 :                                            du.u.array.mArrayCount, pErr);
     640             : 
     641           0 :             return success;
     642             :         }
     643             :         case nsIDataType::VTYPE_EMPTY_ARRAY:
     644             :         {
     645           0 :             JSObject* array = JS_NewArrayObject(cx, 0);
     646           0 :             if (!array)
     647           0 :                 return false;
     648           0 :             pJSVal.setObject(*array);
     649           0 :             return true;
     650             :         }
     651             :         case nsIDataType::VTYPE_VOID:
     652           0 :             pJSVal.setUndefined();
     653           0 :             return true;
     654             :         case nsIDataType::VTYPE_EMPTY:
     655           2 :             pJSVal.setNull();
     656           2 :             return true;
     657             :         default:
     658           0 :             NS_ERROR("bad type in variant!");
     659           0 :             return false;
     660             :     }
     661             : }
     662             : 
     663             : /***************************************************************************/
     664             : /***************************************************************************/
     665             : // XXX These default implementations need to be improved to allow for
     666             : // some more interesting conversions.
     667             : 
     668             : 
     669           3 : NS_IMETHODIMP XPCVariant::GetDataType(uint16_t* aDataType)
     670             : {
     671           3 :     *aDataType = mData.GetType();
     672           3 :     return NS_OK;
     673             : }
     674             : 
     675           0 : NS_IMETHODIMP XPCVariant::GetAsInt8(uint8_t* _retval)
     676             : {
     677           0 :     return mData.ConvertToInt8(_retval);
     678             : }
     679             : 
     680           0 : NS_IMETHODIMP XPCVariant::GetAsInt16(int16_t* _retval)
     681             : {
     682           0 :     return mData.ConvertToInt16(_retval);
     683             : }
     684             : 
     685           0 : NS_IMETHODIMP XPCVariant::GetAsInt32(int32_t* _retval)
     686             : {
     687           0 :     return mData.ConvertToInt32(_retval);
     688             : }
     689             : 
     690           1 : NS_IMETHODIMP XPCVariant::GetAsInt64(int64_t* _retval)
     691             : {
     692           1 :     return mData.ConvertToInt64(_retval);
     693             : }
     694             : 
     695           0 : NS_IMETHODIMP XPCVariant::GetAsUint8(uint8_t* _retval)
     696             : {
     697           0 :     return mData.ConvertToUint8(_retval);
     698             : }
     699             : 
     700           0 : NS_IMETHODIMP XPCVariant::GetAsUint16(uint16_t* _retval)
     701             : {
     702           0 :     return mData.ConvertToUint16(_retval);
     703             : }
     704             : 
     705           0 : NS_IMETHODIMP XPCVariant::GetAsUint32(uint32_t* _retval)
     706             : {
     707           0 :     return mData.ConvertToUint32(_retval);
     708             : }
     709             : 
     710           0 : NS_IMETHODIMP XPCVariant::GetAsUint64(uint64_t* _retval)
     711             : {
     712           0 :     return mData.ConvertToUint64(_retval);
     713             : }
     714             : 
     715           0 : NS_IMETHODIMP XPCVariant::GetAsFloat(float* _retval)
     716             : {
     717           0 :     return mData.ConvertToFloat(_retval);
     718             : }
     719             : 
     720           0 : NS_IMETHODIMP XPCVariant::GetAsDouble(double* _retval)
     721             : {
     722           0 :     return mData.ConvertToDouble(_retval);
     723             : }
     724             : 
     725           0 : NS_IMETHODIMP XPCVariant::GetAsBool(bool* _retval)
     726             : {
     727           0 :     return mData.ConvertToBool(_retval);
     728             : }
     729             : 
     730           0 : NS_IMETHODIMP XPCVariant::GetAsChar(char* _retval)
     731             : {
     732           0 :     return mData.ConvertToChar(_retval);
     733             : }
     734             : 
     735           0 : NS_IMETHODIMP XPCVariant::GetAsWChar(char16_t* _retval)
     736             : {
     737           0 :     return mData.ConvertToWChar(_retval);
     738             : }
     739             : 
     740           0 : NS_IMETHODIMP_(nsresult) XPCVariant::GetAsID(nsID* retval)
     741             : {
     742           0 :     return mData.ConvertToID(retval);
     743             : }
     744             : 
     745           2 : NS_IMETHODIMP XPCVariant::GetAsAString(nsAString & _retval)
     746             : {
     747           2 :     return mData.ConvertToAString(_retval);
     748             : }
     749             : 
     750           0 : NS_IMETHODIMP XPCVariant::GetAsDOMString(nsAString & _retval)
     751             : {
     752             :     // A DOMString maps to an AString internally, so we can re-use
     753             :     // ConvertToAString here.
     754           0 :     return mData.ConvertToAString(_retval);
     755             : }
     756             : 
     757           0 : NS_IMETHODIMP XPCVariant::GetAsACString(nsACString & _retval)
     758             : {
     759           0 :     return mData.ConvertToACString(_retval);
     760             : }
     761             : 
     762           0 : NS_IMETHODIMP XPCVariant::GetAsAUTF8String(nsAUTF8String & _retval)
     763             : {
     764           0 :     return mData.ConvertToAUTF8String(_retval);
     765             : }
     766             : 
     767           0 : NS_IMETHODIMP XPCVariant::GetAsString(char** _retval)
     768             : {
     769           0 :     return mData.ConvertToString(_retval);
     770             : }
     771             : 
     772           0 : NS_IMETHODIMP XPCVariant::GetAsWString(char16_t** _retval)
     773             : {
     774           0 :     return mData.ConvertToWString(_retval);
     775             : }
     776             : 
     777           0 : NS_IMETHODIMP XPCVariant::GetAsISupports(nsISupports** _retval)
     778             : {
     779           0 :     return mData.ConvertToISupports(_retval);
     780             : }
     781             : 
     782           0 : NS_IMETHODIMP XPCVariant::GetAsInterface(nsIID** iid, void** iface)
     783             : {
     784           0 :     return mData.ConvertToInterface(iid, iface);
     785             : }
     786             : 
     787             : 
     788           0 : NS_IMETHODIMP_(nsresult) XPCVariant::GetAsArray(uint16_t* type, nsIID* iid, uint32_t* count, void * *ptr)
     789             : {
     790           0 :     return mData.ConvertToArray(type, iid, count, ptr);
     791             : }
     792             : 
     793           0 : NS_IMETHODIMP XPCVariant::GetAsStringWithSize(uint32_t* size, char** str)
     794             : {
     795           0 :     return mData.ConvertToStringWithSize(size, str);
     796             : }
     797             : 
     798           0 : NS_IMETHODIMP XPCVariant::GetAsWStringWithSize(uint32_t* size, char16_t** str)
     799             : {
     800           0 :     return mData.ConvertToWStringWithSize(size, str);
     801             : }

Generated by: LCOV version 1.13