summaryrefslogtreecommitdiffstats
path: root/xpcom/reflect/xptinfo/xptiprivate.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/reflect/xptinfo/xptiprivate.h')
-rw-r--r--xpcom/reflect/xptinfo/xptiprivate.h394
1 files changed, 394 insertions, 0 deletions
diff --git a/xpcom/reflect/xptinfo/xptiprivate.h b/xpcom/reflect/xptinfo/xptiprivate.h
new file mode 100644
index 000000000..c32ef9c77
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptiprivate.h
@@ -0,0 +1,394 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Library-private header for Interface Info system. */
+
+#ifndef xptiprivate_h___
+#define xptiprivate_h___
+
+#include "nscore.h"
+#include <new>
+#include "nsISupports.h"
+
+// this after nsISupports, to pick up IID
+// so that xpt stuff doesn't try to define it itself...
+#include "xpt_struct.h"
+#include "xpt_xdr.h"
+
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+#include "ShimInterfaceInfo.h"
+
+#include "nsIServiceManager.h"
+#include "nsIFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIWeakReference.h"
+
+#include "mozilla/ReentrantMonitor.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/Attributes.h"
+
+#include "js/TypeDecls.h"
+
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsCOMArray.h"
+#include "nsQuickSort.h"
+
+#include "nsXPIDLString.h"
+
+#include "nsIInputStream.h"
+
+#include "nsHashKeys.h"
+#include "nsDataHashtable.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prio.h"
+#include "prtime.h"
+#include "prenv.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/***************************************************************************/
+
+#if 0 && defined(DEBUG_jband)
+#define LOG_RESOLVE(x) printf x
+#define LOG_LOAD(x) printf x
+#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
+#else
+#define LOG_RESOLVE(x) ((void)0)
+#define LOG_LOAD(x) ((void)0)
+#define LOG_AUTOREG(x) ((void)0)
+#endif
+
+#if 1 && defined(DEBUG_jband)
+#define SHOW_INFO_COUNT_STATS
+#endif
+
+/***************************************************************************/
+
+class xptiInterfaceInfo;
+class xptiInterfaceEntry;
+class xptiTypelibGuts;
+
+extern XPTArena* gXPTIStructArena;
+
+/***************************************************************************/
+
+/***************************************************************************/
+
+// No virtuals.
+// These are always constructed in the struct arena using placement new.
+// dtor need not be called.
+
+class xptiTypelibGuts
+{
+public:
+ static xptiTypelibGuts* Create(XPTHeader* aHeader);
+
+ XPTHeader* GetHeader() {return mHeader;}
+ uint16_t GetEntryCount() const {return mHeader->num_interfaces;}
+
+ void SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr)
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ mEntryArray[i] = ptr;
+ }
+
+ xptiInterfaceEntry* GetEntryAt(uint16_t i);
+ const char* GetEntryNameAt(uint16_t i);
+
+private:
+ explicit xptiTypelibGuts(XPTHeader* aHeader)
+ : mHeader(aHeader)
+ { }
+ ~xptiTypelibGuts();
+
+private:
+ XPTHeader* mHeader; // hold pointer into arena
+ xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
+};
+
+/***************************************************************************/
+
+/***************************************************************************/
+
+// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
+// and a set of bitflags in one 8bit value. See below.
+
+class xptiInfoFlags
+{
+ enum {STATE_MASK = 3};
+public:
+ explicit xptiInfoFlags(uint8_t n) : mData(n) {}
+ xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
+
+ static uint8_t GetStateMask()
+ {return uint8_t(STATE_MASK);}
+
+ void Clear()
+ {mData = 0;}
+
+ uint8_t GetData() const
+ {return mData;}
+
+ uint8_t GetState() const
+ {return mData & GetStateMask();}
+
+ void SetState(uint8_t state)
+ {mData &= ~GetStateMask(); mData |= state;}
+
+ void SetFlagBit(uint8_t flag, bool on)
+ {if(on)
+ mData |= ~GetStateMask() & flag;
+ else
+ mData &= GetStateMask() | ~flag;}
+
+ bool GetFlagBit(uint8_t flag) const
+ {return (mData & flag) ? true : false;}
+
+private:
+ uint8_t mData;
+};
+
+/****************************************************/
+
+// No virtual methods.
+// We always create in the struct arena and construct using "placement new".
+// No members need dtor calls.
+
+class xptiInterfaceEntry
+{
+public:
+ static xptiInterfaceEntry* Create(const char* name,
+ const nsID& iid,
+ XPTInterfaceDescriptor* aDescriptor,
+ xptiTypelibGuts* aTypelib);
+
+ enum {
+ PARTIALLY_RESOLVED = 1,
+ FULLY_RESOLVED = 2,
+ RESOLVE_FAILED = 3
+ };
+
+ // Additional bit flags...
+ enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16,
+ MAIN_PROCESS_SCRIPTABLE_ONLY = 32};
+
+ uint8_t GetResolveState() const {return mFlags.GetState();}
+
+ bool IsFullyResolved() const
+ {return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
+
+ void SetScriptableFlag(bool on)
+ {mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);}
+ bool GetScriptableFlag() const
+ {return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));}
+ void SetBuiltinClassFlag(bool on)
+ {mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);}
+ bool GetBuiltinClassFlag() const
+ {return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));}
+ void SetMainProcessScriptableOnlyFlag(bool on)
+ {mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);}
+ bool GetMainProcessScriptableOnlyFlag() const
+ {return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));}
+
+
+ // AddRef/Release are special and are not considered for the NOTXPCOM flag.
+ void SetHasNotXPCOMFlag()
+ {
+ mFlags.SetFlagBit(HASNOTXPCOM, true);
+ }
+ bool GetHasNotXPCOMFlag() const
+ {
+ return mFlags.GetFlagBit(HASNOTXPCOM);
+ }
+
+ const nsID* GetTheIID() const {return &mIID;}
+ const char* GetTheName() const {return mName;}
+
+ bool EnsureResolved()
+ {return IsFullyResolved() ? true : Resolve();}
+
+ already_AddRefed<xptiInterfaceInfo> InterfaceInfo();
+ bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
+ {return info == mInfo;}
+
+ void LockedInvalidateInterfaceInfo();
+ void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;}
+
+ xptiInterfaceEntry* Parent() const {
+ NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?");
+ return mParent;
+ }
+
+ const nsID& IID() const { return mIID; }
+
+ //////////////////////
+ // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+ nsresult GetName(char * *aName);
+ nsresult GetIID(nsIID * *aIID);
+ nsresult IsScriptable(bool *_retval);
+ nsresult IsBuiltinClass(bool *_retval) {
+ *_retval = GetBuiltinClassFlag();
+ return NS_OK;
+ }
+ nsresult IsMainProcessScriptableOnly(bool *_retval) {
+ *_retval = GetMainProcessScriptableOnlyFlag();
+ return NS_OK;
+ }
+ // Except this one.
+ //nsresult GetParent(nsIInterfaceInfo * *aParent);
+ nsresult GetMethodCount(uint16_t *aMethodCount);
+ nsresult GetConstantCount(uint16_t *aConstantCount);
+ nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info);
+ nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info);
+ nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant);
+ nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
+ nsresult GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
+ nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval);
+ nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval);
+ nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval);
+ nsresult IsIID(const nsIID * IID, bool *_retval);
+ nsresult GetNameShared(const char **name);
+ nsresult GetIIDShared(const nsIID * *iid);
+ nsresult IsFunction(bool *_retval);
+ nsresult HasAncestor(const nsIID * iid, bool *_retval);
+ nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
+
+private:
+ xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ XPTInterfaceDescriptor* aDescriptor,
+ xptiTypelibGuts* aTypelib);
+ ~xptiInterfaceEntry();
+
+ void SetResolvedState(int state)
+ {mFlags.SetState(uint8_t(state));}
+
+ bool Resolve();
+
+ // We only call these "*Locked" variants after locking. This is done to
+ // allow reentrace as files are loaded and various interfaces resolved
+ // without having to worry about the locked state.
+
+ bool EnsureResolvedLocked()
+ {return IsFullyResolved() ? true : ResolveLocked();}
+ bool ResolveLocked();
+
+ // private helpers
+
+ nsresult GetEntryForParam(uint16_t methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry);
+
+ nsresult GetTypeInArray(const nsXPTParamInfo* param,
+ uint16_t dimension,
+ const XPTTypeDescriptor** type);
+
+ nsresult GetInterfaceIndexForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param,
+ uint16_t* interfaceIndex);
+
+ already_AddRefed<ShimInterfaceInfo>
+ GetShimForParam(uint16_t methodIndex, const nsXPTParamInfo* param);
+
+private:
+ nsID mIID;
+ XPTInterfaceDescriptor* mDescriptor;
+
+ xptiTypelibGuts* mTypelib;
+
+ xptiInterfaceEntry* mParent; // Valid only when fully resolved
+
+ xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured "
+ "by the semantics of xptiWorkingSet.")
+ mInfo; // May come and go.
+
+ uint16_t mMethodBaseIndex;
+ uint16_t mConstantBaseIndex;
+
+ xptiInfoFlags mFlags;
+
+ char mName[1]; // Always last. Sized to fit.
+};
+
+class xptiInterfaceInfo final : public nsIInterfaceInfo
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ // Use delegation to implement (most!) of nsIInterfaceInfo.
+ NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
+ NS_IMETHOD GetInterfaceIID(nsIID * *aIID) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
+ NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
+ NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
+ NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); }
+ // Except this one.
+ NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override
+ {
+ if(!EnsureResolved() || !EnsureParent())
+ return NS_ERROR_UNEXPECTED;
+ NS_IF_ADDREF(*aParent = mParent);
+ return NS_OK;
+ }
+ NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
+ NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
+ NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
+ NS_IMETHOD GetConstant(uint16_t index, JS::MutableHandleValue constant, char** name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant, name); }
+ NS_IMETHOD GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
+ 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); }
+ 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); }
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
+ NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
+ NS_IMETHOD GetNameShared(const char **name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
+ NS_IMETHOD GetIIDShared(const nsIID * *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
+ NS_IMETHOD IsFunction(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
+ NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
+ NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
+
+public:
+ explicit xptiInterfaceInfo(xptiInterfaceEntry* entry);
+
+ void Invalidate();
+
+private:
+
+ ~xptiInterfaceInfo();
+
+ // Note that mParent might still end up as nullptr if we don't have one.
+ bool EnsureParent()
+ {
+ NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
+ return mParent || !mEntry->Parent() || BuildParent();
+ }
+
+ bool EnsureResolved()
+ {
+ return mEntry && mEntry->EnsureResolved();
+ }
+
+ bool BuildParent();
+
+ xptiInterfaceInfo(); // not implemented
+
+private:
+ xptiInterfaceEntry* mEntry;
+ RefPtr<xptiInterfaceInfo> mParent;
+};
+
+/***************************************************************************/
+
+#endif /* xptiprivate_h___ */