LCOV - code coverage report
Current view: top level - xpcom/reflect/xptinfo - xptiprivate.h (source / functions) Hit Total Coverage
Test: output.info Lines: 88 93 94.6 %
Date: 2017-07-14 16:53:18 Functions: 49 53 92.5 %
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             : /* Library-private header for Interface Info system. */
       7             : 
       8             : #ifndef xptiprivate_h___
       9             : #define xptiprivate_h___
      10             : 
      11             : #include "nscore.h"
      12             : #include <new>
      13             : #include "nsISupports.h"
      14             : 
      15             : // this after nsISupports, to pick up IID
      16             : // so that xpt stuff doesn't try to define it itself...
      17             : #include "xpt_struct.h"
      18             : #include "xpt_xdr.h"
      19             : 
      20             : #include "nsIInterfaceInfo.h"
      21             : #include "nsIInterfaceInfoManager.h"
      22             : #include "xptinfo.h"
      23             : #include "ShimInterfaceInfo.h"
      24             : 
      25             : #include "nsIServiceManager.h"
      26             : #include "nsIFile.h"
      27             : #include "nsIDirectoryService.h"
      28             : #include "nsDirectoryServiceDefs.h"
      29             : #include "nsAppDirectoryServiceDefs.h"
      30             : #include "nsIWeakReference.h"
      31             : 
      32             : #include "mozilla/ReentrantMonitor.h"
      33             : #include "mozilla/Mutex.h"
      34             : #include "mozilla/Attributes.h"
      35             : 
      36             : #include "js/TypeDecls.h"
      37             : 
      38             : #include "nsCRT.h"
      39             : #include "nsMemory.h"
      40             : 
      41             : #include "nsCOMArray.h"
      42             : #include "nsQuickSort.h"
      43             : 
      44             : #include "nsXPIDLString.h"
      45             : 
      46             : #include "nsIInputStream.h"
      47             : 
      48             : #include "nsHashKeys.h"
      49             : #include "nsDataHashtable.h"
      50             : #include "plstr.h"
      51             : #include "prprf.h"
      52             : #include "prio.h"
      53             : #include "prtime.h"
      54             : #include "prenv.h"
      55             : 
      56             : #include <stdio.h>
      57             : #include <stdarg.h>
      58             : 
      59             : /***************************************************************************/
      60             : 
      61             : #if 0 && defined(DEBUG_jband)
      62             : #define LOG_RESOLVE(x) printf x
      63             : #define LOG_LOAD(x)    printf x
      64             : #define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
      65             : #else
      66             : #define LOG_RESOLVE(x) ((void)0)
      67             : #define LOG_LOAD(x)    ((void)0)
      68             : #define LOG_AUTOREG(x) ((void)0)
      69             : #endif
      70             : 
      71             : #if 1 && defined(DEBUG_jband)
      72             : #define SHOW_INFO_COUNT_STATS
      73             : #endif
      74             : 
      75             : /***************************************************************************/
      76             : 
      77             : class xptiInterfaceInfo;
      78             : class xptiInterfaceEntry;
      79             : class xptiTypelibGuts;
      80             : 
      81             : extern XPTArena* gXPTIStructArena;
      82             : 
      83             : /***************************************************************************/
      84             : 
      85             : /***************************************************************************/
      86             : 
      87             : // No virtuals.
      88             : // These are always constructed in the struct arena using placement new.
      89             : // dtor need not be called.
      90             : 
      91             : class xptiTypelibGuts
      92             : {
      93             : public:
      94             :     static xptiTypelibGuts* Create(XPTHeader* aHeader);
      95             : 
      96             :     XPTHeader*          GetHeader()           {return mHeader;}
      97       10157 :     uint16_t            GetEntryCount() const {return mHeader->num_interfaces;}
      98             : 
      99        4054 :     void                SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr)
     100             :     {
     101        4054 :         NS_ASSERTION(mHeader,"bad state!");
     102        4054 :         NS_ASSERTION(i < GetEntryCount(),"bad param!");
     103        4054 :         mEntryArray[i] = ptr;
     104        4054 :     }
     105             : 
     106             :     xptiInterfaceEntry* GetEntryAt(uint16_t i);
     107             :     const char* GetEntryNameAt(uint16_t i);
     108             : 
     109             : private:
     110         522 :     explicit xptiTypelibGuts(XPTHeader* aHeader)
     111         522 :         : mHeader(aHeader)
     112         522 :     { }
     113             :     ~xptiTypelibGuts();
     114             : 
     115             : private:
     116             :     XPTHeader*           mHeader;        // hold pointer into arena
     117             :     xptiInterfaceEntry*  mEntryArray[1]; // Always last. Sized to fit.
     118             : };
     119             : 
     120             : /***************************************************************************/
     121             : 
     122             : /***************************************************************************/
     123             : 
     124             : // This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
     125             : // and a set of bitflags in one 8bit value. See below.
     126             : 
     127             : class xptiInfoFlags
     128             : {
     129             :     enum {STATE_MASK = 3};
     130             : public:
     131        3849 :     explicit xptiInfoFlags(uint8_t n) : mData(n) {}
     132             :     xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
     133             : 
     134       79780 :     static uint8_t GetStateMask()
     135       79780 :         {return uint8_t(STATE_MASK);}
     136             : 
     137             :     void Clear()
     138             :         {mData = 0;}
     139             : 
     140             :     uint8_t GetData() const
     141             :         {return mData;}
     142             : 
     143       63905 :     uint8_t GetState() const
     144       63905 :         {return mData & GetStateMask();}
     145             : 
     146        4279 :     void SetState(uint8_t state)
     147        4279 :         {mData &= ~GetStateMask(); mData |= state;}
     148             : 
     149       11596 :     void SetFlagBit(uint8_t flag, bool on)
     150       11596 :         {if(on)
     151        4378 :             mData |= ~GetStateMask() & flag;
     152             :          else
     153        7218 :             mData &= GetStateMask() | ~flag;}
     154             : 
     155        7309 :     bool GetFlagBit(uint8_t flag) const
     156        7309 :         {return (mData & flag) ? true : false;}
     157             : 
     158             : private:
     159             :     uint8_t mData;
     160             : };
     161             : 
     162             : /****************************************************/
     163             : 
     164             : // No virtual methods.
     165             : // We always create in the struct arena and construct using "placement new".
     166             : // No members need dtor calls.
     167             : 
     168             : class xptiInterfaceEntry
     169             : {
     170             : public:
     171             :     static xptiInterfaceEntry* Create(const char* name,
     172             :                                       const nsID& iid,
     173             :                                       XPTInterfaceDescriptor* aDescriptor,
     174             :                                       xptiTypelibGuts* aTypelib);
     175             : 
     176             :     enum {
     177             :         PARTIALLY_RESOLVED    = 1,
     178             :         FULLY_RESOLVED        = 2,
     179             :         RESOLVE_FAILED        = 3
     180             :     };
     181             : 
     182             :     // Additional bit flags...
     183             :     enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16,
     184             :           MAIN_PROCESS_SCRIPTABLE_ONLY = 32};
     185             : 
     186       63905 :     uint8_t GetResolveState() const {return mFlags.GetState();}
     187             : 
     188       63045 :     bool IsFullyResolved() const
     189       63045 :         {return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
     190             : 
     191        3849 :     void SetScriptableFlag(bool on)
     192        3849 :                 {mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);}
     193        2869 :     bool GetScriptableFlag() const
     194        2869 :                 {return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));}
     195        3849 :     void SetBuiltinClassFlag(bool on)
     196        3849 :                 {mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);}
     197        1250 :     bool GetBuiltinClassFlag() const
     198        1250 :                 {return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));}
     199        3849 :     void SetMainProcessScriptableOnlyFlag(bool on)
     200        3849 :                 {mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);}
     201        1823 :     bool GetMainProcessScriptableOnlyFlag() const
     202        1823 :                 {return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));}
     203             : 
     204             : 
     205             :     // AddRef/Release are special and are not considered for the NOTXPCOM flag.
     206          49 :     void SetHasNotXPCOMFlag()
     207             :     {
     208          49 :         mFlags.SetFlagBit(HASNOTXPCOM, true);
     209          49 :     }
     210        1367 :     bool GetHasNotXPCOMFlag() const
     211             :     {
     212        1367 :         return mFlags.GetFlagBit(HASNOTXPCOM);
     213             :     }
     214             : 
     215             :     const nsID* GetTheIID()  const {return &mIID;}
     216        3849 :     const char* GetTheName() const {return mName;}
     217             : 
     218       62423 :     bool EnsureResolved()
     219       62423 :         {return IsFullyResolved() ? true : Resolve();}
     220             : 
     221             :     already_AddRefed<xptiInterfaceInfo> InterfaceInfo();
     222          65 :     bool     InterfaceInfoEquals(const xptiInterfaceInfo* info) const
     223          65 :         {return info == mInfo;}
     224             : 
     225             :     void     LockedInvalidateInterfaceInfo();
     226          65 :     void     LockedInterfaceInfoDeathNotification() {mInfo = nullptr;}
     227             : 
     228          63 :     xptiInterfaceEntry* Parent() const {
     229          63 :         NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?");
     230          63 :         return mParent;
     231             :     }
     232             : 
     233        6004 :     const nsID& IID() const { return mIID; }
     234             : 
     235             :     //////////////////////
     236             :     // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
     237             : 
     238             :     nsresult GetName(char * *aName);
     239             :     nsresult GetIID(nsIID * *aIID);
     240             :     nsresult IsScriptable(bool *_retval);
     241         310 :     nsresult IsBuiltinClass(bool *_retval) {
     242         310 :         *_retval = GetBuiltinClassFlag();
     243         310 :         return NS_OK;
     244             :     }
     245        1823 :     nsresult IsMainProcessScriptableOnly(bool *_retval) {
     246        1823 :         *_retval = GetMainProcessScriptableOnlyFlag();
     247        1823 :         return NS_OK;
     248             :     }
     249             :     // Except this one.
     250             :     //nsresult GetParent(nsIInterfaceInfo * *aParent);
     251             :     nsresult GetMethodCount(uint16_t *aMethodCount);
     252             :     nsresult GetConstantCount(uint16_t *aConstantCount);
     253             :     nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info);
     254             :     nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info);
     255             :     nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant);
     256             :     nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
     257             :     nsresult GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
     258             :     nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval);
     259             :     nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval);
     260             :     nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval);
     261             :     nsresult IsIID(const nsIID * IID, bool *_retval);
     262             :     nsresult GetNameShared(const char **name);
     263             :     nsresult GetIIDShared(const nsIID * *iid);
     264             :     nsresult IsFunction(bool *_retval);
     265             :     nsresult HasAncestor(const nsIID * iid, bool *_retval);
     266             :     nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
     267             : 
     268             : private:
     269             :     xptiInterfaceEntry(const char* name,
     270             :                        size_t nameLength,
     271             :                        const nsID& iid,
     272             :                        XPTInterfaceDescriptor* aDescriptor,
     273             :                        xptiTypelibGuts* aTypelib);
     274             :     ~xptiInterfaceEntry();
     275             : 
     276        4279 :     void SetResolvedState(int state)
     277        4279 :         {mFlags.SetState(uint8_t(state));}
     278             : 
     279             :     bool Resolve();
     280             : 
     281             :     // We only call these "*Locked" variants after locking. This is done to
     282             :     // allow reentrace as files are loaded and various interfaces resolved
     283             :     // without having to worry about the locked state.
     284             : 
     285         427 :     bool EnsureResolvedLocked()
     286         427 :         {return IsFullyResolved() ? true : ResolveLocked();}
     287             :     bool ResolveLocked();
     288             : 
     289             :     // private helpers
     290             : 
     291             :     nsresult GetEntryForParam(uint16_t methodIndex,
     292             :                               const nsXPTParamInfo * param,
     293             :                               xptiInterfaceEntry** entry);
     294             : 
     295             :     nsresult GetTypeInArray(const nsXPTParamInfo* param,
     296             :                             uint16_t dimension,
     297             :                             const XPTTypeDescriptor** type);
     298             : 
     299             :     nsresult GetInterfaceIndexForParam(uint16_t methodIndex,
     300             :                                        const nsXPTParamInfo* param,
     301             :                                        uint16_t* interfaceIndex);
     302             : 
     303             :     already_AddRefed<ShimInterfaceInfo>
     304             :     GetShimForParam(uint16_t methodIndex, const nsXPTParamInfo* param);
     305             : 
     306             : private:
     307             :     nsID                    mIID;
     308             :     XPTInterfaceDescriptor* mDescriptor;
     309             : 
     310             :     xptiTypelibGuts* mTypelib;
     311             : 
     312             :     xptiInterfaceEntry*     mParent;      // Valid only when fully resolved
     313             : 
     314             :     xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured "
     315             :                                       "by the semantics of xptiWorkingSet.")
     316             :                             mInfo;        // May come and go.
     317             : 
     318             :     uint16_t mMethodBaseIndex;
     319             :     uint16_t mConstantBaseIndex;
     320             : 
     321             :     xptiInfoFlags           mFlags;
     322             : 
     323             :     char                    mName[1];     // Always last. Sized to fit.
     324             : };
     325             : 
     326             : class xptiInterfaceInfo final : public nsIInterfaceInfo
     327             : {
     328             : public:
     329             :     NS_DECL_THREADSAFE_ISUPPORTS
     330             : 
     331             :     // Use delegation to implement (most!) of nsIInterfaceInfo.
     332        1171 :     NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
     333           0 :     NS_IMETHOD GetInterfaceIID(nsIID * *aIID) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
     334        2869 :     NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
     335         310 :     NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
     336        1823 :     NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); }
     337             :     // Except this one.
     338          21 :     NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override
     339             :     {
     340          21 :         if(!EnsureResolved() || !EnsureParent())
     341           0 :             return NS_ERROR_UNEXPECTED;
     342          21 :         NS_IF_ADDREF(*aParent = mParent);
     343          21 :         return NS_OK;
     344             :     }
     345        1915 :     NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
     346        1823 :     NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
     347       28270 :     NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
     348           0 :     NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
     349        4014 :     NS_IMETHOD GetConstant(uint16_t index, JS::MutableHandleValue constant, char** name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant, name); }
     350           0 :     NS_IMETHOD GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
     351           0 :     NS_IMETHOD GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
     352          90 :     NS_IMETHOD GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
     353          65 :     NS_IMETHOD GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
     354         105 :     NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
     355         482 :     NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
     356        3838 :     NS_IMETHOD GetNameShared(const char **name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
     357       22957 :     NS_IMETHOD GetIIDShared(const nsIID * *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
     358         758 :     NS_IMETHOD IsFunction(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
     359        2433 :     NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
     360        5610 :     NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
     361             : 
     362             : public:
     363             :     explicit xptiInterfaceInfo(xptiInterfaceEntry* entry);
     364             : 
     365             :     void Invalidate();
     366             : 
     367             : private:
     368             : 
     369             :     ~xptiInterfaceInfo();
     370             : 
     371             :     // Note that mParent might still end up as nullptr if we don't have one.
     372          21 :     bool EnsureParent()
     373             :     {
     374          21 :         NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
     375          21 :         return mParent || !mEntry->Parent() || BuildParent();
     376             :     }
     377             : 
     378          21 :     bool EnsureResolved()
     379             :     {
     380          21 :         return mEntry && mEntry->EnsureResolved();
     381             :     }
     382             : 
     383             :     bool BuildParent();
     384             : 
     385             :     xptiInterfaceInfo();  // not implemented
     386             : 
     387             : private:
     388             :     xptiInterfaceEntry* mEntry;
     389             :     RefPtr<xptiInterfaceInfo> mParent;
     390             : };
     391             : 
     392             : /***************************************************************************/
     393             : 
     394             : #endif /* xptiprivate_h___ */

Generated by: LCOV version 1.13