LCOV - code coverage report
Current view: top level - xpcom/reflect/xptinfo - xptiInterfaceInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 238 345 69.0 %
Date: 2017-07-14 16:53:18 Functions: 30 36 83.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             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
       7             : 
       8             : #include "xptiprivate.h"
       9             : #include "mozilla/dom/ScriptSettings.h"
      10             : #include "mozilla/DebugOnly.h"
      11             : #include "mozilla/XPTInterfaceInfoManager.h"
      12             : #include "mozilla/PodOperations.h"
      13             : #include "jsapi.h"
      14             : 
      15             : using namespace mozilla;
      16             : 
      17             : /* static */ xptiInterfaceEntry*
      18        3849 : xptiInterfaceEntry::Create(const char* name, const nsID& iid,
      19             :                            XPTInterfaceDescriptor* aDescriptor,
      20             :                            xptiTypelibGuts* aTypelib)
      21             : {
      22        3849 :     int namelen = strlen(name);
      23             :     void* place =
      24        3849 :         XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry) + namelen);
      25        3849 :     if (!place) {
      26           0 :         return nullptr;
      27             :     }
      28             :     return new (place) xptiInterfaceEntry(name, namelen, iid, aDescriptor,
      29        3849 :                                           aTypelib);
      30             : }
      31             : 
      32        3849 : xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
      33             :                                        size_t nameLength,
      34             :                                        const nsID& iid,
      35             :                                        XPTInterfaceDescriptor* aDescriptor,
      36        3849 :                                        xptiTypelibGuts* aTypelib)
      37             :     : mIID(iid)
      38             :     , mDescriptor(aDescriptor)
      39             :     , mTypelib(aTypelib)
      40             :     , mParent(nullptr)
      41             :     , mInfo(nullptr)
      42             :     , mMethodBaseIndex(0)
      43             :     , mConstantBaseIndex(0)
      44        3849 :     , mFlags(0)
      45             : {
      46        3849 :     memcpy(mName, name, nameLength);
      47        3849 :     SetResolvedState(PARTIALLY_RESOLVED);
      48        3849 : }
      49             : 
      50             : bool
      51         386 : xptiInterfaceEntry::Resolve()
      52             : {
      53         772 :     MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock());
      54         772 :     return ResolveLocked();
      55             : }
      56             : 
      57             : bool
      58         430 : xptiInterfaceEntry::ResolveLocked()
      59             : {
      60         430 :     int resolvedState = GetResolveState();
      61             : 
      62         430 :     if(resolvedState == FULLY_RESOLVED)
      63           0 :         return true;
      64         430 :     if(resolvedState == RESOLVE_FAILED)
      65           0 :         return false;
      66             : 
      67         430 :     NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
      68             : 
      69             :     // Finish out resolution by finding parent and Resolving it so
      70             :     // we can set the info we get from it.
      71             : 
      72         430 :     uint16_t parent_index = mDescriptor->parent_interface;
      73             : 
      74         430 :     if(parent_index)
      75             :     {
      76             :         xptiInterfaceEntry* parent =
      77         427 :             mTypelib->GetEntryAt(parent_index - 1);
      78             : 
      79         427 :         if(!parent || !parent->EnsureResolvedLocked())
      80             :         {
      81           0 :             SetResolvedState(RESOLVE_FAILED);
      82           0 :             return false;
      83             :         }
      84             : 
      85         427 :         mParent = parent;
      86         427 :         if (parent->GetHasNotXPCOMFlag()) {
      87          23 :             SetHasNotXPCOMFlag();
      88             :         } else {
      89        3864 :             for (uint16_t idx = 0; idx < mDescriptor->num_methods; ++idx) {
      90             :                 nsXPTMethodInfo* method = reinterpret_cast<nsXPTMethodInfo*>(
      91        3486 :                     mDescriptor->method_descriptors + idx);
      92        3486 :                 if (method->IsNotXPCOM()) {
      93          26 :                     SetHasNotXPCOMFlag();
      94          26 :                     break;
      95             :                 }
      96             :             }
      97             :         }
      98             : 
      99             : 
     100         427 :         mMethodBaseIndex =
     101         854 :             parent->mMethodBaseIndex +
     102         427 :             parent->mDescriptor->num_methods;
     103             : 
     104         427 :         mConstantBaseIndex =
     105         854 :             parent->mConstantBaseIndex +
     106         427 :             parent->mDescriptor->num_constants;
     107             : 
     108             :     }
     109             :     LOG_RESOLVE(("+ complete resolve of %s\n", mName));
     110             : 
     111         430 :     SetResolvedState(FULLY_RESOLVED);
     112         430 :     return true;
     113             : }
     114             : 
     115             : /**************************************************/
     116             : // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
     117             : 
     118             : nsresult
     119        1171 : xptiInterfaceEntry::GetName(char **name)
     120             : {
     121             :     // It is not necessary to Resolve because this info is read from manifest.
     122        1171 :     *name = (char*) nsMemory::Clone(mName, strlen(mName)+1);
     123        1171 :     return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     124             : }
     125             : 
     126             : nsresult
     127           0 : xptiInterfaceEntry::GetIID(nsIID **iid)
     128             : {
     129             :     // It is not necessary to Resolve because this info is read from manifest.
     130           0 :     *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
     131           0 :     return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     132             : }
     133             : 
     134             : nsresult
     135        2869 : xptiInterfaceEntry::IsScriptable(bool* result)
     136             : {
     137             :     // It is not necessary to Resolve because this info is read from manifest.
     138        2869 :     *result = GetScriptableFlag();
     139        2869 :     return NS_OK;
     140             : }
     141             : 
     142             : nsresult
     143         758 : xptiInterfaceEntry::IsFunction(bool* result)
     144             : {
     145         758 :     if(!EnsureResolved())
     146           0 :         return NS_ERROR_UNEXPECTED;
     147             : 
     148         758 :     *result = XPT_ID_IS_FUNCTION(mDescriptor->flags);
     149         758 :     return NS_OK;
     150             : }
     151             : 
     152             : nsresult
     153        1915 : xptiInterfaceEntry::GetMethodCount(uint16_t* count)
     154             : {
     155        1915 :     if(!EnsureResolved())
     156           0 :         return NS_ERROR_UNEXPECTED;
     157             : 
     158        3830 :     *count = mMethodBaseIndex +
     159        1915 :              mDescriptor->num_methods;
     160        1915 :     return NS_OK;
     161             : }
     162             : 
     163             : nsresult
     164        1823 : xptiInterfaceEntry::GetConstantCount(uint16_t* count)
     165             : {
     166        1823 :     if(!EnsureResolved())
     167           0 :         return NS_ERROR_UNEXPECTED;
     168             : 
     169        1823 :     if(!count)
     170           0 :         return NS_ERROR_UNEXPECTED;
     171             : 
     172        3646 :     *count = mConstantBaseIndex +
     173        1823 :              mDescriptor->num_constants;
     174        1823 :     return NS_OK;
     175             : }
     176             : 
     177             : nsresult
     178       37034 : xptiInterfaceEntry::GetMethodInfo(uint16_t index, const nsXPTMethodInfo** info)
     179             : {
     180       37034 :     if(!EnsureResolved())
     181           0 :         return NS_ERROR_UNEXPECTED;
     182             : 
     183       37034 :     if(index < mMethodBaseIndex)
     184        8084 :         return mParent->GetMethodInfo(index, info);
     185             : 
     186       57900 :     if(index >= mMethodBaseIndex +
     187       28950 :                 mDescriptor->num_methods)
     188             :     {
     189           0 :         NS_ERROR("bad param");
     190           0 :         *info = nullptr;
     191           0 :         return NS_ERROR_INVALID_ARG;
     192             :     }
     193             : 
     194             :     // else...
     195       28950 :     *info = reinterpret_cast<nsXPTMethodInfo*>
     196       28950 :        (&mDescriptor->method_descriptors[index - mMethodBaseIndex]);
     197       28950 :     return NS_OK;
     198             : }
     199             : 
     200             : nsresult
     201           0 : xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index,
     202             :                                          const nsXPTMethodInfo** result)
     203             : {
     204           0 :     if(!EnsureResolved())
     205           0 :         return NS_ERROR_UNEXPECTED;
     206             : 
     207             :     // This is a slow algorithm, but this is not expected to be called much.
     208           0 :     for(uint16_t i = 0; i < mDescriptor->num_methods; ++i)
     209             :     {
     210             :         const nsXPTMethodInfo* info;
     211           0 :         info = reinterpret_cast<nsXPTMethodInfo*>
     212           0 :                                (&mDescriptor->
     213           0 :                                         method_descriptors[i]);
     214           0 :         if (PL_strcmp(methodName, info->GetName()) == 0) {
     215           0 :             *index = i + mMethodBaseIndex;
     216           0 :             *result = info;
     217           0 :             return NS_OK;
     218             :         }
     219             :     }
     220             : 
     221           0 :     if(mParent)
     222           0 :         return mParent->GetMethodInfoForName(methodName, index, result);
     223             :     else
     224             :     {
     225           0 :         *index = 0;
     226           0 :         *result = 0;
     227           0 :         return NS_ERROR_INVALID_ARG;
     228             :     }
     229             : }
     230             : 
     231             : nsresult
     232        4608 : xptiInterfaceEntry::GetConstant(uint16_t index, JS::MutableHandleValue constant,
     233             :                                 char** name)
     234             : {
     235        4608 :     if(!EnsureResolved())
     236           0 :         return NS_ERROR_UNEXPECTED;
     237             : 
     238        4608 :     if(index < mConstantBaseIndex)
     239         594 :         return mParent->GetConstant(index, constant, name);
     240             : 
     241        8028 :     if(index >= mConstantBaseIndex +
     242        4014 :                 mDescriptor->num_constants)
     243             :     {
     244           0 :         NS_PRECONDITION(0, "bad param");
     245           0 :         return NS_ERROR_INVALID_ARG;
     246             :     }
     247             : 
     248        4014 :     const auto& c = mDescriptor->const_descriptors[index - mConstantBaseIndex];
     249        8028 :     AutoJSContext cx;
     250        8028 :     JS::Rooted<JS::Value> v(cx);
     251        4014 :     v.setUndefined();
     252             : 
     253        4014 :     switch (c.type.prefix.flags) {
     254             :       case nsXPTType::T_I8:
     255             :       {
     256           0 :         v.setInt32(c.value.i8);
     257           0 :         break;
     258             :       }
     259             :       case nsXPTType::T_U8:
     260             :       {
     261           0 :         v.setInt32(c.value.ui8);
     262           0 :         break;
     263             :       }
     264             :       case nsXPTType::T_I16:
     265             :       {
     266         168 :         v.setInt32(c.value.i16);
     267         168 :         break;
     268             :       }
     269             :       case nsXPTType::T_U16:
     270             :       {
     271         449 :         v.setInt32(c.value.ui16);
     272         449 :         break;
     273             :       }
     274             :       case nsXPTType::T_I32:
     275             :       {
     276         656 :         v = JS_NumberValue(c.value.i32);
     277         656 :         break;
     278             :       }
     279             :       case nsXPTType::T_U32:
     280             :       {
     281        2741 :         v = JS_NumberValue(c.value.ui32);
     282        2741 :         break;
     283             :       }
     284             :       default:
     285             :       {
     286             : #ifdef DEBUG
     287           0 :         NS_ERROR("Non-numeric constant found in interface.");
     288             : #endif
     289             :       }
     290             :     }
     291             : 
     292        4014 :     constant.set(v);
     293        4014 :     *name = ToNewCString(nsDependentCString(c.name));
     294             : 
     295        4014 :     return NS_OK;
     296             : }
     297             : 
     298             : // this is a private helper
     299             : 
     300             : nsresult
     301        5676 : xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex,
     302             :                                               const nsXPTParamInfo* param,
     303             :                                               uint16_t* interfaceIndex)
     304             : {
     305        5676 :     if(!EnsureResolved())
     306           0 :         return NS_ERROR_UNEXPECTED;
     307             : 
     308        5676 :     if(methodIndex < mMethodBaseIndex)
     309           0 :         return mParent->GetInterfaceIndexForParam(methodIndex, param,
     310           0 :                                                   interfaceIndex);
     311             : 
     312       11352 :     if(methodIndex >= mMethodBaseIndex +
     313        5676 :                       mDescriptor->num_methods)
     314             :     {
     315           0 :         NS_ERROR("bad param");
     316           0 :         return NS_ERROR_INVALID_ARG;
     317             :     }
     318             : 
     319        5676 :     const XPTTypeDescriptor *td = &param->type;
     320             : 
     321        5688 :     while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
     322           6 :         td = &mDescriptor->additional_types[td->u.array.additional_type];
     323             :     }
     324             : 
     325        5676 :     if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
     326           0 :         NS_ERROR("not an interface");
     327           0 :         return NS_ERROR_INVALID_ARG;
     328             :     }
     329             : 
     330        5676 :     *interfaceIndex = (td->u.iface.iface_hi8 << 8) | td->u.iface.iface_lo8;
     331        5676 :     return NS_OK;
     332             : }
     333             : 
     334             : nsresult
     335        6401 : xptiInterfaceEntry::GetEntryForParam(uint16_t methodIndex,
     336             :                                      const nsXPTParamInfo * param,
     337             :                                      xptiInterfaceEntry** entry)
     338             : {
     339        6401 :     if(!EnsureResolved())
     340           0 :         return NS_ERROR_UNEXPECTED;
     341             : 
     342        6401 :     if(methodIndex < mMethodBaseIndex)
     343         791 :         return mParent->GetEntryForParam(methodIndex, param, entry);
     344             : 
     345        5610 :     uint16_t interfaceIndex = 0;
     346        5610 :     nsresult rv = GetInterfaceIndexForParam(methodIndex, param,
     347        5610 :                                             &interfaceIndex);
     348        5610 :     if (NS_FAILED(rv)) {
     349           0 :         return rv;
     350             :     }
     351             : 
     352        5610 :     xptiInterfaceEntry* theEntry = mTypelib->GetEntryAt(interfaceIndex - 1);
     353             : 
     354             :     // This can happen if a declared interface is not available at runtime.
     355        5610 :     if(!theEntry)
     356             :     {
     357          66 :         *entry = nullptr;
     358          66 :         return NS_ERROR_FAILURE;
     359             :     }
     360             : 
     361        5544 :     *entry = theEntry;
     362        5544 :     return NS_OK;
     363             : }
     364             : 
     365             : already_AddRefed<ShimInterfaceInfo>
     366          66 : xptiInterfaceEntry::GetShimForParam(uint16_t methodIndex,
     367             :                                     const nsXPTParamInfo* param)
     368             : {
     369          66 :     if(methodIndex < mMethodBaseIndex) {
     370           0 :         return mParent->GetShimForParam(methodIndex, param);
     371             :     }
     372             : 
     373          66 :     uint16_t interfaceIndex = 0;
     374          66 :     nsresult rv = GetInterfaceIndexForParam(methodIndex, param,
     375          66 :                                             &interfaceIndex);
     376          66 :     if (NS_FAILED(rv)) {
     377           0 :         return nullptr;
     378             :     }
     379             : 
     380          66 :     const char* shimName = mTypelib->GetEntryNameAt(interfaceIndex - 1);
     381             :     RefPtr<ShimInterfaceInfo> shim =
     382         132 :         ShimInterfaceInfo::MaybeConstruct(shimName, nullptr);
     383          66 :     return shim.forget();
     384             : }
     385             : 
     386             : nsresult
     387           0 : xptiInterfaceEntry::GetInfoForParam(uint16_t methodIndex,
     388             :                                     const nsXPTParamInfo *param,
     389             :                                     nsIInterfaceInfo** info)
     390             : {
     391             :     xptiInterfaceEntry* entry;
     392           0 :     nsresult rv = GetEntryForParam(methodIndex, param, &entry);
     393           0 :     if (NS_FAILED(rv)) {
     394           0 :         RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
     395           0 :         if (!shim) {
     396           0 :             return rv;
     397             :         }
     398             : 
     399           0 :         shim.forget(info);
     400           0 :         return NS_OK;
     401             :     }
     402             : 
     403           0 :     *info = entry->InterfaceInfo().take();
     404             : 
     405           0 :     return NS_OK;
     406             : }
     407             : 
     408             : nsresult
     409           0 : xptiInterfaceEntry::GetIIDForParam(uint16_t methodIndex,
     410             :                                    const nsXPTParamInfo* param, nsIID** iid)
     411             : {
     412             :     xptiInterfaceEntry* entry;
     413           0 :     nsresult rv = GetEntryForParam(methodIndex, param, &entry);
     414           0 :     if (NS_FAILED(rv)) {
     415           0 :         RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
     416           0 :         if (!shim) {
     417           0 :             return rv;
     418             :         }
     419             : 
     420           0 :         return shim->GetInterfaceIID(iid);
     421             :     }
     422           0 :     return entry->GetIID(iid);
     423             : }
     424             : 
     425             : nsresult
     426        5610 : xptiInterfaceEntry::GetIIDForParamNoAlloc(uint16_t methodIndex,
     427             :                                           const nsXPTParamInfo * param,
     428             :                                           nsIID *iid)
     429             : {
     430             :     xptiInterfaceEntry* entry;
     431        5610 :     nsresult rv = GetEntryForParam(methodIndex, param, &entry);
     432        5610 :     if (NS_FAILED(rv)) {
     433         132 :         RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
     434          66 :         if (!shim) {
     435           0 :             return rv;
     436             :         }
     437             : 
     438             :         const nsIID* shimIID;
     439         132 :         DebugOnly<nsresult> rv2 = shim->GetIIDShared(&shimIID);
     440          66 :         MOZ_ASSERT(NS_SUCCEEDED(rv2));
     441          66 :         *iid = *shimIID;
     442          66 :         return NS_OK;
     443             :     }
     444        5544 :     *iid = entry->mIID;
     445        5544 :     return NS_OK;
     446             : }
     447             : 
     448             : // this is a private helper
     449             : nsresult
     450          90 : xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
     451             :                                   uint16_t dimension,
     452             :                                   const XPTTypeDescriptor** type)
     453             : {
     454          90 :     NS_ASSERTION(IsFullyResolved(), "bad state");
     455             : 
     456          90 :     const XPTTypeDescriptor *td = &param->type;
     457             :     const XPTTypeDescriptor *additional_types =
     458          90 :                 mDescriptor->additional_types;
     459             : 
     460         180 :     for (uint16_t i = 0; i < dimension; i++) {
     461          90 :         if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
     462           0 :             NS_ERROR("bad dimension");
     463           0 :             return NS_ERROR_INVALID_ARG;
     464             :         }
     465          90 :         td = &additional_types[td->u.array.additional_type];
     466             :     }
     467             : 
     468          90 :     *type = td;
     469          90 :     return NS_OK;
     470             : }
     471             : 
     472             : nsresult
     473          96 : xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex,
     474             :                                     const nsXPTParamInfo* param,
     475             :                                     uint16_t dimension,
     476             :                                     nsXPTType* type)
     477             : {
     478          96 :     if(!EnsureResolved())
     479           0 :         return NS_ERROR_UNEXPECTED;
     480             : 
     481          96 :     if(methodIndex < mMethodBaseIndex)
     482           6 :         return mParent->
     483          12 :             GetTypeForParam(methodIndex, param, dimension, type);
     484             : 
     485         180 :     if(methodIndex >= mMethodBaseIndex +
     486          90 :                       mDescriptor->num_methods)
     487             :     {
     488           0 :         NS_ERROR("bad index");
     489           0 :         return NS_ERROR_INVALID_ARG;
     490             :     }
     491             : 
     492             :     const XPTTypeDescriptor *td;
     493             : 
     494          90 :     if(dimension) {
     495          90 :         nsresult rv = GetTypeInArray(param, dimension, &td);
     496          90 :         if(NS_FAILED(rv))
     497           0 :             return rv;
     498             :     }
     499             :     else
     500           0 :         td = &param->type;
     501             : 
     502          90 :     *type = nsXPTType(td->prefix);
     503          90 :     return NS_OK;
     504             : }
     505             : 
     506             : nsresult
     507          71 : xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex,
     508             :                                                const nsXPTParamInfo* param,
     509             :                                                uint16_t dimension,
     510             :                                                uint8_t* argnum)
     511             : {
     512          71 :     if(!EnsureResolved())
     513           0 :         return NS_ERROR_UNEXPECTED;
     514             : 
     515          71 :     if(methodIndex < mMethodBaseIndex)
     516           6 :         return mParent->
     517          12 :             GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
     518             : 
     519         130 :     if(methodIndex >= mMethodBaseIndex +
     520          65 :                       mDescriptor->num_methods)
     521             :     {
     522           0 :         NS_ERROR("bad index");
     523           0 :         return NS_ERROR_INVALID_ARG;
     524             :     }
     525             : 
     526             :     const XPTTypeDescriptor *td;
     527             : 
     528          65 :     if(dimension) {
     529           0 :         nsresult rv = GetTypeInArray(param, dimension, &td);
     530           0 :         if(NS_FAILED(rv))
     531           0 :             return rv;
     532             :     }
     533             :     else
     534          65 :         td = &param->type;
     535             : 
     536             :     // verify that this is a type that has size_is
     537          65 :     switch (XPT_TDP_TAG(td->prefix)) {
     538             :       case TD_ARRAY:
     539          65 :         *argnum = td->u.array.argnum;
     540          65 :         break;
     541             :       case TD_PSTRING_SIZE_IS:
     542             :       case TD_PWSTRING_SIZE_IS:
     543           0 :         *argnum = td->u.pstring_is.argnum;
     544           0 :         break;
     545             :       default:
     546           0 :         NS_ERROR("not a size_is");
     547           0 :         return NS_ERROR_INVALID_ARG;
     548             :     }
     549             : 
     550          65 :     return NS_OK;
     551             : }
     552             : 
     553             : nsresult
     554         105 : xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex,
     555             :                                                     const nsXPTParamInfo* param,
     556             :                                                     uint8_t* argnum)
     557             : {
     558         105 :     if(!EnsureResolved())
     559           0 :         return NS_ERROR_UNEXPECTED;
     560             : 
     561         105 :     if(methodIndex < mMethodBaseIndex)
     562           0 :         return mParent->
     563           0 :             GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
     564             : 
     565         210 :     if(methodIndex >= mMethodBaseIndex +
     566         105 :                       mDescriptor->num_methods)
     567             :     {
     568           0 :         NS_ERROR("bad index");
     569           0 :         return NS_ERROR_INVALID_ARG;
     570             :     }
     571             : 
     572         105 :     const XPTTypeDescriptor *td = &param->type;
     573             : 
     574         105 :     while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
     575           0 :         td = &mDescriptor->additional_types[td->u.array.additional_type];
     576             :     }
     577             : 
     578         105 :     if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
     579           0 :         NS_ERROR("not an iid_is");
     580           0 :         return NS_ERROR_INVALID_ARG;
     581             :     }
     582             : 
     583         105 :     *argnum = td->u.interface_is.argnum;
     584         105 :     return NS_OK;
     585             : }
     586             : 
     587             : nsresult
     588         482 : xptiInterfaceEntry::IsIID(const nsIID * iid, bool *_retval)
     589             : {
     590             :     // It is not necessary to Resolve because this info is read from manifest.
     591         482 :     *_retval = mIID.Equals(*iid);
     592         482 :     return NS_OK;
     593             : }
     594             : 
     595             : nsresult
     596        3838 : xptiInterfaceEntry::GetNameShared(const char **name)
     597             : {
     598             :     // It is not necessary to Resolve because this info is read from manifest.
     599        3838 :     *name = mName;
     600        3838 :     return NS_OK;
     601             : }
     602             : 
     603             : nsresult
     604       22957 : xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
     605             : {
     606             :     // It is not necessary to Resolve because this info is read from manifest.
     607       22957 :     *iid = &mIID;
     608       22957 :     return NS_OK;
     609             : }
     610             : 
     611             : nsresult
     612        2433 : xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval)
     613             : {
     614        2433 :     *_retval = false;
     615             : 
     616        5408 :     for(xptiInterfaceEntry* current = this;
     617        5408 :         current;
     618        2975 :         current = current->mParent)
     619             :     {
     620        4890 :         if(current->mIID.Equals(*iid))
     621             :         {
     622        1915 :             *_retval = true;
     623        1915 :             break;
     624             :         }
     625        2975 :         if(!current->EnsureResolved())
     626           0 :             return NS_ERROR_UNEXPECTED;
     627             :     }
     628             : 
     629        2433 :     return NS_OK;
     630             : }
     631             : 
     632             : /***************************************************/
     633             : 
     634             : already_AddRefed<xptiInterfaceInfo>
     635        1539 : xptiInterfaceEntry::InterfaceInfo()
     636             : {
     637             : #ifdef DEBUG
     638        1539 :     XPTInterfaceInfoManager::GetSingleton()->mWorkingSet.mTableReentrantMonitor.
     639        1539 :         AssertCurrentThreadIn();
     640             : #endif
     641             : 
     642        1539 :     if(!mInfo)
     643             :     {
     644         458 :         mInfo = new xptiInterfaceInfo(this);
     645             :     }
     646             : 
     647        3078 :     RefPtr<xptiInterfaceInfo> info = mInfo;
     648        3078 :     return info.forget();
     649             : }
     650             : 
     651             : void
     652           0 : xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
     653             : {
     654           0 :     if(mInfo)
     655             :     {
     656           0 :         mInfo->Invalidate();
     657           0 :         mInfo = nullptr;
     658             :     }
     659           0 : }
     660             : 
     661             : bool
     662          21 : xptiInterfaceInfo::BuildParent()
     663             : {
     664          21 :     mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::GetSingleton()->
     665          42 :                                     mWorkingSet.mTableReentrantMonitor);
     666          21 :     NS_ASSERTION(mEntry &&
     667             :                  mEntry->IsFullyResolved() &&
     668             :                  !mParent &&
     669             :                  mEntry->Parent(),
     670             :                 "bad BuildParent call");
     671          21 :     mParent = mEntry->Parent()->InterfaceInfo();
     672          42 :     return true;
     673             : }
     674             : 
     675             : /***************************************************************************/
     676             : 
     677        4190 : NS_IMPL_QUERY_INTERFACE(xptiInterfaceInfo, nsIInterfaceInfo)
     678             : 
     679         458 : xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
     680         458 :     : mEntry(entry)
     681             : {
     682         458 : }
     683             : 
     684         130 : xptiInterfaceInfo::~xptiInterfaceInfo()
     685             : {
     686          65 :     NS_ASSERTION(!mEntry, "bad state in dtor");
     687          65 : }
     688             : 
     689             : void
     690           0 : xptiInterfaceInfo::Invalidate()
     691             : {
     692           0 :   mParent = nullptr;
     693           0 :   mEntry = nullptr;
     694           0 : }
     695             : 
     696             : MozExternalRefCountType
     697        8422 : xptiInterfaceInfo::AddRef(void)
     698             : {
     699        8422 :     nsrefcnt cnt = ++mRefCnt;
     700        8422 :     NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
     701        8422 :     return cnt;
     702             : }
     703             : 
     704             : MozExternalRefCountType
     705        7352 : xptiInterfaceInfo::Release(void)
     706             : {
     707        7352 :     xptiInterfaceEntry* entry = mEntry;
     708        7352 :     nsrefcnt cnt = --mRefCnt;
     709        7352 :     NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
     710        7352 :     if(!cnt)
     711             :     {
     712             :         mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::
     713          65 :                                           GetSingleton()->mWorkingSet.
     714         130 :                                           mTableReentrantMonitor);
     715             : 
     716             :         // If InterfaceInfo added and *released* a reference before we
     717             :         // acquired the monitor then 'this' might already be dead. In that
     718             :         // case we would not want to try to access any instance data. We
     719             :         // would want to bail immediately. If 'this' is already dead then the
     720             :         // entry will no longer have a pointer to 'this'. So, we can protect
     721             :         // ourselves from danger without more aggressive locking.
     722          65 :         if(entry && !entry->InterfaceInfoEquals(this))
     723           0 :             return 0;
     724             : 
     725             :         // If InterfaceInfo added a reference before we acquired the monitor
     726             :         // then we want to bail out of here without destorying the object.
     727          65 :         if(mRefCnt)
     728           0 :             return 1;
     729             : 
     730          65 :         if(mEntry)
     731             :         {
     732          65 :             mEntry->LockedInterfaceInfoDeathNotification();
     733          65 :             mEntry = nullptr;
     734             :         }
     735             : 
     736          65 :         delete this;
     737          65 :         return 0;
     738             :     }
     739        7287 :     return cnt;
     740             : }
     741             : 
     742             : /***************************************************************************/

Generated by: LCOV version 1.13