summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom/reflect/xptinfo
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/reflect/xptinfo')
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in66
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl137
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl85
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl100
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h281
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in75
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO20
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp819
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp2126
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp710
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp63
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp432
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp102
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h981
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp146
24 files changed, 6645 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in
new file mode 100644
index 00000000..d7e3b9c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in
new file mode 100644
index 00000000..dbf13d8b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in
@@ -0,0 +1,66 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+XPIDL_MODULE = xpcom_xpti
+
+GRE_MODULE = 1
+
+EXPORTS = \
+ xptinfo.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIInterfaceInfo.idl \
+ nsIInterfaceInfoManager.idl \
+ nsIXPTLoader.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+include $(topsrcdir)/config/rules.mk
+
+CFLAGS += -DEXPORT_XPCI_API
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl
new file mode 100644
index 00000000..f77dbcfc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The nsIInterfaceInfo public declaration. */
+
+
+#include "nsISupports.idl"
+
+// forward declaration of non-XPCOM types
+
+[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo);
+[ptr] native nsXPTConstantPtr(nsXPTConstant);
+[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo);
+ native nsXPTType(nsXPTType);
+
+// We bend the rules to do a [shared] nsIID (but this is never scriptable)
+[ptr] native nsIIDPtrShared(nsIID);
+
+%{C++
+class nsXPTMethodInfo;
+class nsXPTConstant;
+class nsXPTParamInfo;
+class nsXPTType;
+%}
+
+/* this is NOT intended to be scriptable */
+[uuid(215DBE04-94A7-11d2-BA58-00805F8A5DD7)]
+interface nsIInterfaceInfo : nsISupports
+{
+ readonly attribute string name;
+ readonly attribute nsIIDPtr InterfaceIID;
+
+ PRBool isScriptable();
+
+ readonly attribute nsIInterfaceInfo parent;
+
+ /**
+ * These include counts for parent (and all ancestors).
+ */
+ readonly attribute PRUint16 methodCount;
+ readonly attribute PRUint16 constantCount;
+
+ /**
+ * These include methods and constants for parent (and all ancestors).
+ *
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ void getMethodInfo(in PRUint16 index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getMethodInfoForName(in string methodName, out PRUint16 index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getConstant(in PRUint16 index,
+ [shared, retval] out nsXPTConstantPtr constant);
+
+
+ /**
+ * Get the interface information or iid associated with a param of some
+ * method in this interface.
+ */
+
+ nsIInterfaceInfo getInfoForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ nsIIDPtr getIIDForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+
+ /**
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ nsXPTType getTypeForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getSizeIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getLengthIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getInterfaceIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ PRBool isIID(in nsIIDPtr IID);
+
+ void getNameShared([shared,retval] out string name);
+ void getIIDShared([shared,retval] out nsIIDPtrShared iid);
+
+ PRBool isFunction();
+
+ PRBool hasAncestor(in nsIIDPtr iid);
+
+ [notxpcom] nsresult getIIDForParamNoAlloc(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ out nsIID iid);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl
new file mode 100644
index 00000000..48277691
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The nsIInterfaceInfoManager public declaration. */
+
+
+#include "nsISupports.idl"
+#include "nsIInterfaceInfo.idl"
+#include "nsIEnumerator.idl"
+#include "nsISimpleEnumerator.idl"
+
+/* this is NOT intended to be scriptable */
+[uuid(8B161900-BE2B-11d2-9831-006008962422)]
+interface nsIInterfaceInfoManager : nsISupports
+{
+ nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid);
+ nsIInterfaceInfo getInfoForName(in string name);
+
+ nsIIDPtr getIIDForName(in string name);
+ string getNameForIID(in nsIIDPtr iid);
+
+ nsIEnumerator enumerateInterfaces();
+
+ void autoRegisterInterfaces();
+
+ nsIEnumerator enumerateInterfacesWhoseNamesStartWith(in string prefix);
+};
+
+[uuid(0ee22850-bc6a-11d5-9134-0010a4e73d9a)]
+interface nsIInterfaceInfoSuperManager : nsIInterfaceInfoManager
+{
+ void addAdditionalManager(in nsIInterfaceInfoManager manager);
+ void removeAdditionalManager(in nsIInterfaceInfoManager manager);
+
+ PRBool hasAdditionalManagers();
+ nsISimpleEnumerator enumerateAdditionalManagers();
+};
+
+%{C++
+#define NS_INTERFACEINFOMANAGER_SERVICE_CLASSNAME \
+ "Interface Information Manager Service"
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CID \
+ { /* 13bef784-f8e0-4f96-85c1-09f9ef4f9a19 */ \
+ 0x13bef784, 0xf8e0, 0x4f96, \
+ {0x85, 0xc1, 0x09, 0xf9, 0xef, 0x4f, 0x9a, 0x19} }
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID \
+ "@mozilla.org/xpti/interfaceinfomanager-service;1"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl
new file mode 100644
index 00000000..8918daa3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl
@@ -0,0 +1,100 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the external XPT loader interface.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+#include "nsILocalFile.idl"
+#include "nsIInputStream.idl"
+
+/**
+ * Implement nsIXPTLoaderSink if you want to enumerate the entries in
+ * an XPT archive of some kind
+ */
+[scriptable, uuid(6E48C500-8682-4730-ADD6-7DB693B9E7BA)]
+interface nsIXPTLoaderSink : nsISupports {
+
+ /**
+ * called by the loader for each entry in the archive
+ * @param itemName the name of this particular item in the archive
+ * @param index the index of the item inthe archive
+ * @param stream contains the contents of the xpt file
+ */
+ void foundEntry(in string itemName,
+ in long index,
+ in nsIInputStream xptData);
+};
+
+/**
+ * The XPT loader interface: implemented by a loader to grab an input
+ * stream which will be consumed by the interface loader.
+ */
+[scriptable, uuid(368A15D9-17A9-4c2b-AC3D-A35B3A22B876)]
+interface nsIXPTLoader : nsISupports {
+ /**
+ * enumerate entries in the given archive
+ * for each entry found, the loader will call the sink's
+ * foundEntry() method with the appropriate information and a
+ * stream that the consumer can read from
+ * @param file the file to read from
+ * @param sink an object which will be called with each file found
+ * in the file
+ */
+ void enumerateEntries(in nsILocalFile file,
+ in nsIXPTLoaderSink sink );
+
+ /**
+ * Load a specific entry from the archive
+ * @param file the file to read from
+ * @param name the name of the xpt within the file
+ * @return an input stream that will read the raw xpt data from
+ * the file
+ */
+ nsIInputStream loadEntry(in nsILocalFile file,
+ in string name);
+};
+
+
+%{C++
+
+// the first part of the contractID for any loader
+// append the type of loader that you need, such as "zip"
+#define NS_XPTLOADER_CONTRACTID_PREFIX \
+ "@mozilla.org/xptinfo/loader;1&type="
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h
new file mode 100644
index 00000000..076482a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* XPTI_PUBLIC_API and XPTI_GetInterfaceInfoManager declarations. */
+
+#ifndef xptiinfo_h___
+#define xptiinfo_h___
+
+#include "prtypes.h"
+#include "xpt_struct.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPTI_GetInterfaceInfoManager VBoxNsxpXPTI_GetInterfaceInfoManager
+#define XPTI_FreeInterfaceInfoManager VBoxNsxpXPTI_FreeInterfaceInfoManager
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*
+ * The linkage of XPTI API functions differs depending on whether the file is
+ * used within the XPTI library or not. Any source file within the XPTI
+ * library should define EXPORT_XPTI_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPTI_API
+#define XPTI_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPTI_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#if defined(_WIN32)
+# define XPTI_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTI_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2_VACPP)
+# define XPTI_EXPORT extern
+#else
+# define XPTI_EXPORT
+#endif
+#else
+#if defined(_WIN32)
+# define XPTI_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTI_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTI_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTI_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTI_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTI_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2_VACPP)
+# define XPTI_PUBLIC_API(t) extern t
+# define XPTI_PUBLIC_DATA(t) extern t
+# define XPTI_EXPORT extern
+#else
+# define XPTI_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPTI_PUBLIC_DATA(t) t
+# define XPTI_EXPORT
+#endif
+#endif
+#define XPTI_FRIEND_API(t) XPTI_PUBLIC_API(t)
+#define XPTI_FRIEND_DATA(t) XPTI_PUBLIC_DATA(t)
+
+class nsIInterfaceInfoManager;
+PR_BEGIN_EXTERN_C
+// Even if this is a service, it is cool to provide a direct accessor
+XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
+XPTI_GetInterfaceInfoManager();
+
+// Even if this is a service, it is cool to provide a direct accessor
+XPTI_PUBLIC_API(void)
+XPTI_FreeInterfaceInfoManager();
+PR_END_EXTERN_C
+
+
+
+// Flyweight wrapper classes for xpt_struct.h structs.
+// Everything here is dependent upon - and sensitive to changes in -
+// xpcom/typelib/xpt/public/xpt_struct.h!
+
+class nsXPTType : public XPTTypeDescriptorPrefix
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTType()
+ {} // random contents
+ nsXPTType(const XPTTypeDescriptorPrefix& prefix)
+ {*(XPTTypeDescriptorPrefix*)this = prefix;}
+
+ nsXPTType(const uint8& prefix)
+ {*(uint8*)this = prefix;}
+
+ nsXPTType& operator=(uint8 val)
+ {flags = val; return *this;}
+
+ nsXPTType& operator=(const nsXPTType& other)
+ {flags = other.flags; return *this;}
+
+ operator uint8() const
+ {return flags;}
+
+ PRBool IsPointer() const
+ {return 0 != (XPT_TDP_IS_POINTER(flags));}
+
+ PRBool IsUniquePointer() const
+ {return 0 != (XPT_TDP_IS_UNIQUE_POINTER(flags));}
+
+ PRBool IsReference() const
+ {return 0 != (XPT_TDP_IS_REFERENCE(flags));}
+
+ PRBool IsArithmetic() const // terminology from Harbison/Steele
+ {return flags <= T_WCHAR;}
+
+ PRBool IsInterfacePointer() const
+ { switch (TagPart()) {
+ default:
+ return PR_FALSE;
+ case T_INTERFACE:
+ case T_INTERFACE_IS:
+ return PR_TRUE;
+ }
+ }
+
+ PRBool IsArray() const
+ {return (PRBool) TagPart() == T_ARRAY;}
+
+ // 'Dependent' means that params of this type are dependent upon other
+ // params. e.g. an T_INTERFACE_IS is dependent upon some other param at
+ // runtime to say what the interface type of this param really is.
+ PRBool IsDependent() const
+ { switch (TagPart()) {
+ default:
+ return PR_FALSE;
+ case T_INTERFACE_IS:
+ case TD_ARRAY:
+ case T_PSTRING_SIZE_IS:
+ case T_PWSTRING_SIZE_IS:
+ return PR_TRUE;
+ }
+ }
+
+ uint8 TagPart() const
+ {return (uint8) (flags & XPT_TDP_TAGMASK);}
+
+ enum
+ {
+ T_I8 = TD_INT8 ,
+ T_I16 = TD_INT16 ,
+ T_I32 = TD_INT32 ,
+ T_I64 = TD_INT64 ,
+ T_U8 = TD_UINT8 ,
+ T_U16 = TD_UINT16 ,
+ T_U32 = TD_UINT32 ,
+ T_U64 = TD_UINT64 ,
+ T_FLOAT = TD_FLOAT ,
+ T_DOUBLE = TD_DOUBLE ,
+ T_BOOL = TD_BOOL ,
+ T_CHAR = TD_CHAR ,
+ T_WCHAR = TD_WCHAR ,
+ T_VOID = TD_VOID ,
+ T_IID = TD_PNSIID ,
+ T_DOMSTRING = TD_DOMSTRING ,
+ T_CHAR_STR = TD_PSTRING ,
+ T_WCHAR_STR = TD_PWSTRING ,
+ T_INTERFACE = TD_INTERFACE_TYPE ,
+ T_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
+ T_ARRAY = TD_ARRAY ,
+ T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS ,
+ T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
+ T_UTF8STRING = TD_UTF8STRING ,
+ T_CSTRING = TD_CSTRING ,
+ T_ASTRING = TD_ASTRING
+ };
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTParamInfo : public XPTParamDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTParamInfo(const XPTParamDescriptor& desc)
+ {*(XPTParamDescriptor*)this = desc;}
+
+
+ PRBool IsIn() const {return 0 != (XPT_PD_IS_IN(flags));}
+ PRBool IsOut() const {return 0 != (XPT_PD_IS_OUT(flags));}
+ PRBool IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));}
+ PRBool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
+ PRBool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(flags));}
+ const nsXPTType GetType() const {return type.prefix;}
+
+ // NOTE: other activities on types are done via methods on nsIInterfaceInfo
+
+private:
+ nsXPTParamInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTMethodInfo : public XPTMethodDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTMethodInfo(const XPTMethodDescriptor& desc)
+ {*(XPTMethodDescriptor*)this = desc;}
+
+ PRBool IsGetter() const {return 0 != (XPT_MD_IS_GETTER(flags) );}
+ PRBool IsSetter() const {return 0 != (XPT_MD_IS_SETTER(flags) );}
+ PRBool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));}
+ PRBool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );}
+ PRBool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
+ const char* GetName() const {return name;}
+ uint8 GetParamCount() const {return num_args;}
+ /* idx was index before I got _sick_ of the warnings on Unix, sorry jband */
+ const nsXPTParamInfo GetParam(uint8 idx) const
+ {
+ NS_PRECONDITION(idx < GetParamCount(),"bad arg");
+ return params[idx];
+ }
+ const nsXPTParamInfo GetResult() const
+ {return *result;}
+private:
+ nsXPTMethodInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+
+// forward declaration
+struct nsXPTCMiniVariant;
+
+class nsXPTConstant : public XPTConstDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTConstant(const XPTConstDescriptor& desc)
+ {*(XPTConstDescriptor*)this = desc;}
+
+ const char* GetName() const
+ {return name;}
+
+ const nsXPTType GetType() const
+ {return type.prefix;}
+
+ // XXX this is ugly. But sometimes you gotta do what you gotta do.
+ // A reinterpret_cast won't do the trick here. And this plain C cast
+ // works correctly and is safe enough.
+ // See http://bugzilla.mozilla.org/show_bug.cgi?id=49641
+ const nsXPTCMiniVariant* GetValue() const
+ {return (nsXPTCMiniVariant*) &value;}
+private:
+ nsXPTConstant(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+#endif /* xptiinfo_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in
new file mode 100644
index 00000000..de5fd9b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in
@@ -0,0 +1,75 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xptinfo
+REQUIRES = \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ xptiFile.cpp \
+ xptiInterfaceInfo.cpp \
+ xptiInterfaceInfoManager.cpp \
+ xptiManifest.cpp \
+ xptiMisc.cpp \
+ xptiTypelibGuts.cpp \
+ xptiWorkingSet.cpp \
+ xptiZipItem.cpp \
+ xptiZipLoader.cpp \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+# For nsManifestLineReader class.
+LOCAL_INCLUDES = -I$(srcdir)/../../../ds
+
+DEFINES += -DEXPORT_XPTI_API -DEXPORT_XPT_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO
new file mode 100644
index 00000000..c5bb1c64
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO
@@ -0,0 +1,20 @@
+/* jband - 03/24/00 - */
+
+- DOCS
+- improve error handling
+ - should some errors really be warnings?
+ - should autoreg support additional channel to recieve warnings so that
+ an installer can decide whether or not to accept the consequences of
+ leaving the newly installed files in place?
+- verification of interfaces (warnings and/or errors)
+ - verify that repeated interfaces are identical in all ways
+ - verify that interface names are always one-to-one with iids
+- check for truncated xpt files and version problems
+ - http://bugzilla.mozilla.org/show_bug.cgi?id=33193
+- TESTS!
+ - e.g. verify the merge stuff really works for various inputs.
+ - we really need a set of .xpt and .zip files and code that does an array
+ of autoreg and interfaceinof use activitities to test various corners
+ of the system.
+- better autoreg logging
+- use only 32 bits for file size?
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp
new file mode 100644
index 00000000..50362c75
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiFile. */
+
+#include "xptiprivate.h"
+
+MOZ_DECL_CTOR_COUNTER(xptiFile)
+
+xptiFile::xptiFile()
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(nsnull),
+#endif
+ mSize(),
+ mDate(),
+ mName(nsnull),
+ mGuts(nsnull),
+ mDirectory(0)
+{
+ // empty
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mSize(aSize),
+ mDate(aDate),
+ mName(aName),
+ mGuts(nsnull),
+ mDirectory(aDirectory)
+{
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
+
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mSize(r.mSize),
+ mDate(r.mDate),
+ mName(nsnull),
+ mGuts(nsnull),
+ mDirectory(r.mDirectory)
+{
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
+
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::~xptiFile()
+{
+ MOZ_COUNT_DTOR(xptiFile);
+}
+
+PRBool
+xptiFile::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(!mGuts,"bad state");
+ NS_ASSERTION(aHeader,"bad param");
+ NS_ASSERTION(aWorkingSet,"bad param");
+
+ mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
+ return mGuts != nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp
new file mode 100644
index 00000000..69bf86df
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp
@@ -0,0 +1,819 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
+
+#include "xptiprivate.h"
+
+/***************************************************************************/
+// Debug Instrumentation...
+
+#ifdef SHOW_INFO_COUNT_STATS
+static int DEBUG_TotalInfos = 0;
+static int DEBUG_CurrentInfos = 0;
+static int DEBUG_MaxInfos = 0;
+static int DEBUG_MonitorEntryCount = 0;
+
+#define LOG_INFO_CREATE(t) \
+ DEBUG_TotalInfos++; \
+ DEBUG_CurrentInfos++; \
+ if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \
+ DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */
+
+#define LOG_INFO_DESTROY(t) \
+ DEBUG_CurrentInfos-- /* no ';' */
+
+#define LOG_INFO_MONITOR_ENTRY \
+ DEBUG_MonitorEntryCount++ /* no ';' */
+
+#else /* SHOW_INFO_COUNT_STATS */
+
+#define LOG_INFO_CREATE(t) ((void)0)
+#define LOG_INFO_DESTROY(t) ((void)0)
+#define LOG_INFO_MONITOR_ENTRY ((void)0)
+#endif /* SHOW_INFO_COUNT_STATS */
+
+#ifdef DEBUG
+// static
+void xptiInterfaceInfo::DEBUG_ShutdownNotification()
+{
+#ifdef SHOW_INFO_COUNT_STATS
+ printf("iiii %d total xptiInterfaceInfos created\n", DEBUG_TotalInfos);
+ printf("iiii %d max xptiInterfaceInfos alive at one time\n", DEBUG_MaxInfos);
+ printf("iiii %d xptiInterfaceInfos still alive\n", DEBUG_CurrentInfos);
+ printf("iiii %d times locked\n", DEBUG_MonitorEntryCount);
+#endif
+}
+#endif /* DEBUG */
+
+/***************************************************************************/
+
+// static
+xptiInterfaceEntry*
+xptiInterfaceEntry::NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet)
+{
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceEntry) + nameLength);
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceEntry(name, nameLength, iid, typelib);
+}
+
+// static
+xptiInterfaceEntry*
+xptiInterfaceEntry::NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet)
+{
+ size_t nameLength = PL_strlen(r.mName);
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceEntry) + nameLength);
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceEntry(r, nameLength, typelib);
+}
+
+
+xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib)
+ : mIID(iid),
+ mTypelib(typelib),
+ mInfo(nsnull),
+ mFlags(uint8(0))
+{
+ memcpy(mName, name, nameLength);
+}
+
+xptiInterfaceEntry::xptiInterfaceEntry(const xptiInterfaceEntry& r,
+ size_t nameLength,
+ const xptiTypelib& typelib)
+ : mIID(r.mIID),
+ mTypelib(typelib),
+ mInfo(nsnull),
+ mFlags(r.mFlags)
+{
+ SetResolvedState(NOT_RESOLVED);
+ memcpy(mName, r.mName, nameLength);
+}
+
+PRBool
+xptiInterfaceEntry::Resolve(xptiWorkingSet* aWorkingSet /* = nsnull */)
+{
+ nsAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
+ return ResolveLocked(aWorkingSet);
+}
+
+PRBool
+xptiInterfaceEntry::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
+{
+ int resolvedState = GetResolveState();
+
+ if(resolvedState == FULLY_RESOLVED)
+ return PR_TRUE;
+ if(resolvedState == RESOLVE_FAILED)
+ return PR_FALSE;
+
+ xptiInterfaceInfoManager* mgr =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+
+ if(!mgr)
+ return PR_FALSE;
+
+ if(!aWorkingSet)
+ {
+ aWorkingSet = mgr->GetWorkingSet();
+ }
+
+ if(resolvedState == NOT_RESOLVED)
+ {
+ LOG_RESOLVE(("! begin resolve of %s\n", mName));
+ // Make a copy of mTypelib because the underlying memory will change!
+ xptiTypelib typelib = mTypelib;
+
+ // We expect our PartiallyResolveLocked() to get called before
+ // this returns.
+ if(!mgr->LoadFile(typelib, aWorkingSet))
+ {
+ SetResolvedState(RESOLVE_FAILED);
+ return PR_FALSE;
+ }
+ // The state was changed by LoadFile to PARTIALLY_RESOLVED, so this
+ // ...falls through...
+ }
+
+ NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
+
+ // Finish out resolution by finding parent and Resolving it so
+ // we can set the info we get from it.
+
+ PRUint16 parent_index = mInterface->mDescriptor->parent_interface;
+
+ if(parent_index)
+ {
+ xptiInterfaceEntry* parent =
+ aWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
+ GetEntryAt(parent_index - 1);
+
+ if(!parent || !parent->EnsureResolvedLocked())
+ {
+ xptiTypelib aTypelib = mInterface->mTypelib;
+ mInterface = nsnull;
+ mTypelib = aTypelib;
+ SetResolvedState(RESOLVE_FAILED);
+ return PR_FALSE;
+ }
+
+ mInterface->mParent = parent;
+
+ mInterface->mMethodBaseIndex =
+ parent->mInterface->mMethodBaseIndex +
+ parent->mInterface->mDescriptor->num_methods;
+
+ mInterface->mConstantBaseIndex =
+ parent->mInterface->mConstantBaseIndex +
+ parent->mInterface->mDescriptor->num_constants;
+
+ }
+ LOG_RESOLVE(("+ complete resolve of %s\n", mName));
+
+ SetResolvedState(FULLY_RESOLVED);
+ return PR_TRUE;
+}
+
+// This *only* gets called by xptiInterfaceInfoManager::LoadFile (while locked).
+PRBool
+xptiInterfaceEntry::PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(GetResolveState() == NOT_RESOLVED, "bad state");
+
+ LOG_RESOLVE(("~ partial resolve of %s\n", mName));
+
+ xptiInterfaceGuts* iface =
+ xptiInterfaceGuts::NewGuts(aDescriptor, mTypelib, aWorkingSet);
+
+ if(!iface)
+ return PR_FALSE;
+
+ mInterface = iface;
+
+#ifdef DEBUG
+ if(!DEBUG_ScriptableFlagIsValid())
+ {
+ NS_ERROR("unexpected scriptable flag!");
+ SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags));
+ }
+#endif
+
+ SetResolvedState(PARTIALLY_RESOLVED);
+ return PR_TRUE;
+}
+
+/**************************************************/
+// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+nsresult
+xptiInterfaceEntry::GetName(char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
+ return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::GetIID(nsIID **iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
+ return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::IsScriptable(PRBool* result)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ NS_ASSERTION(DEBUG_ScriptableFlagIsValid(), "scriptable flag out of sync!");
+ *result = GetScriptableFlag();
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::IsFunction(PRBool* result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *result = XPT_ID_IS_FUNCTION(GetInterfaceGuts()->mDescriptor->flags);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodCount(uint16* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetConstantCount(uint16* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mInterface->mConstantBaseIndex +
+ mInterface->mDescriptor->num_constants;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->GetMethodInfo(index, info);
+
+ if(index >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ *info = NULL;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
+ &mInterface->mDescriptor->
+ method_descriptors[index -
+ mInterface->mMethodBaseIndex]);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16 *index,
+ const nsXPTMethodInfo** result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ // This is a slow algorithm, but this is not expected to be called much.
+ for(uint16 i = 0; i < mInterface->mDescriptor->num_methods; ++i)
+ {
+ const nsXPTMethodInfo* info;
+ info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
+ &mInterface->mDescriptor->
+ method_descriptors[i]);
+ if (PL_strcmp(methodName, info->GetName()) == 0) {
+ *index = i + mInterface->mMethodBaseIndex;
+ *result = info;
+ return NS_OK;
+ }
+ }
+
+ if(mInterface->mParent)
+ return mInterface->mParent->GetMethodInfoForName(methodName, index, result);
+ else
+ {
+ *index = 0;
+ *result = 0;
+ return NS_ERROR_INVALID_ARG;
+ }
+}
+
+nsresult
+xptiInterfaceEntry::GetConstant(uint16 index, const nsXPTConstant** constant)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mInterface->mConstantBaseIndex)
+ return mInterface->mParent->GetConstant(index, constant);
+
+ if(index >= mInterface->mConstantBaseIndex +
+ mInterface->mDescriptor->num_constants)
+ {
+ NS_PRECONDITION(0, "bad param");
+ *constant = NULL;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *constant =
+ NS_REINTERPRET_CAST(nsXPTConstant*,
+ &mInterface->mDescriptor->
+ const_descriptors[index -
+ mInterface->mConstantBaseIndex]);
+ return NS_OK;
+}
+
+// this is a private helper
+
+nsresult
+xptiInterfaceEntry::GetEntryForParam(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->GetEntryForParam(methodIndex, param, entry);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mInterface->mDescriptor->additional_types[td->type.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
+ NS_ERROR("not an interface");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ xptiInterfaceEntry* theEntry =
+ mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
+ GetEntryAt(td->type.iface - 1);
+
+ // This can happen if a declared interface is not available at runtime.
+ if(!theEntry)
+ {
+ NS_WARNING("Declared InterfaceInfo not found");
+ *entry = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ *entry = theEntry;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInfoForParam(uint16 methodIndex,
+ const nsXPTParamInfo *param,
+ nsIInterfaceInfo** info)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+
+ xptiInterfaceInfo* theInfo;
+ rv = entry->GetInterfaceInfo(&theInfo);
+ if(NS_FAILED(rv))
+ return rv;
+
+ *info = NS_STATIC_CAST(nsIInterfaceInfo*, theInfo);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param, nsIID** iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+ return entry->GetIID(iid);
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParamNoAlloc(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ nsIID *iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+ *iid = entry->mIID;
+ return NS_OK;
+}
+
+// this is a private helper
+nsresult
+xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
+ uint16 dimension,
+ const XPTTypeDescriptor** type)
+{
+ NS_ASSERTION(IsFullyResolved(), "bad state");
+
+ const XPTTypeDescriptor *td = &param->type;
+ const XPTTypeDescriptor *additional_types =
+ mInterface->mDescriptor->additional_types;
+
+ for (uint16 i = 0; i < dimension; i++) {
+ if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
+ NS_ERROR("bad dimension");
+ return NS_ERROR_INVALID_ARG;
+ }
+ td = &additional_types[td->type.additional_type];
+ }
+
+ *type = td;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetTypeForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ nsXPTType* type)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetTypeForParam(methodIndex, param, dimension, type);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ *type = nsXPTType(td->prefix);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has size_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ break;
+ default:
+ NS_ERROR("not a size_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetLengthIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetLengthIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has length_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ break;
+ default:
+ NS_ERROR("not a length_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum2;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mInterface->mDescriptor->
+ additional_types[td->type.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
+ NS_ERROR("not an iid_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum;
+ return NS_OK;
+}
+
+/* PRBool isIID (in nsIIDPtr IID); */
+nsresult
+xptiInterfaceEntry::IsIID(const nsIID * IID, PRBool *_retval)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *_retval = mIID.Equals(*IID);
+ return NS_OK;
+}
+
+/* void getNameShared ([shared, retval] out string name); */
+nsresult
+xptiInterfaceEntry::GetNameShared(const char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = mName;
+ return NS_OK;
+}
+
+/* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */
+nsresult
+xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = &mIID;
+ return NS_OK;
+}
+
+/* PRBool hasAncestor (in nsIIDPtr iid); */
+nsresult
+xptiInterfaceEntry::HasAncestor(const nsIID * iid, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ for(xptiInterfaceEntry* current = this;
+ current;
+ current = current->mInterface->mParent)
+ {
+ if(current->mIID.Equals(*iid))
+ {
+ *_retval = PR_TRUE;
+ break;
+ }
+ if(!current->EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+/***************************************************/
+
+nsresult
+xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
+{
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ LOG_INFO_MONITOR_ENTRY;
+
+#ifdef SHOW_INFO_COUNT_STATS
+ static int callCount = 0;
+ if(!(++callCount%100))
+ printf("iiii %d xptiInterfaceInfos currently alive\n", DEBUG_CurrentInfos);
+#endif
+
+ if(!mInfo)
+ {
+ mInfo = new xptiInterfaceInfo(this);
+ if(!mInfo)
+ {
+ *info = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ NS_ADDREF(*info = mInfo);
+ return NS_OK;
+}
+
+void
+xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
+{
+ if(mInfo)
+ {
+ mInfo->Invalidate();
+ mInfo = nsnull;
+ }
+}
+
+/***************************************************************************/
+
+NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
+
+xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
+ : mEntry(entry), mParent(nsnull)
+{
+ LOG_INFO_CREATE(this);
+}
+
+xptiInterfaceInfo::~xptiInterfaceInfo()
+{
+ LOG_INFO_DESTROY(this);
+ NS_IF_RELEASE(mParent);
+ NS_ASSERTION(!mEntry, "bad state in dtor");
+}
+
+nsrefcnt
+xptiInterfaceInfo::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
+ return cnt;
+}
+
+nsrefcnt
+xptiInterfaceInfo::Release(void)
+{
+ xptiInterfaceEntry* entry = mEntry;
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+ NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
+ if(!cnt)
+ {
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ LOG_INFO_MONITOR_ENTRY;
+
+ // If GetInterfaceInfo added and *released* a reference before we
+ // acquired the monitor then 'this' might already be dead. In that
+ // case we would not want to try to access any instance data. We
+ // would want to bail immediately. If 'this' is already dead then the
+ // entry will no longer have a pointer to 'this'. So, we can protect
+ // ourselves from danger without more aggressive locking.
+ if(entry && !entry->InterfaceInfoEquals(this))
+ return 0;
+
+ // If GetInterfaceInfo added a reference before we acquired the monitor
+ // then we want to bail out of here without destorying the object.
+ if(mRefCnt)
+ return 1;
+
+ if(mEntry)
+ {
+ mEntry->LockedInterfaceInfoDeathNotification();
+ mEntry = nsnull;
+ }
+
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return cnt;
+}
+
+/***************************************************************************/
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
new file mode 100644
index 00000000..5ae06914
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
@@ -0,0 +1,2126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiInterfaceInfoManager. */
+
+#include "xptiprivate.h"
+#include "nsDependentString.h"
+#include "nsString.h"
+
+#define NS_ZIPLOADER_CONTRACTID NS_XPTLOADER_CONTRACTID_PREFIX "zip"
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(xptiInterfaceInfoManager,
+ nsIInterfaceInfoManager,
+ nsIInterfaceInfoSuperManager)
+
+static xptiInterfaceInfoManager* gInterfaceInfoManager = nsnull;
+#ifdef DEBUG
+static int gCallCount = 0;
+#endif
+
+// static
+xptiInterfaceInfoManager*
+xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef()
+{
+ if(!gInterfaceInfoManager)
+ {
+ nsCOMPtr<nsISupportsArray> searchPath;
+ BuildFileSearchPath(getter_AddRefs(searchPath));
+ if(!searchPath)
+ {
+ NS_ERROR("can't get xpt search path!");
+ return nsnull;
+ }
+
+ gInterfaceInfoManager = new xptiInterfaceInfoManager(searchPath);
+ if(gInterfaceInfoManager)
+ NS_ADDREF(gInterfaceInfoManager);
+ if(!gInterfaceInfoManager->IsValid())
+ {
+ NS_RELEASE(gInterfaceInfoManager);
+ }
+ else
+ {
+ PRBool mustAutoReg =
+ !xptiManifest::Read(gInterfaceInfoManager,
+ &gInterfaceInfoManager->mWorkingSet);
+#ifdef DEBUG
+ {
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(gInterfaceInfoManager,
+ gInterfaceInfoManager->mAutoRegLogFile, PR_TRUE);
+ LOG_AUTOREG(("debug build forced autoreg after %s load of manifest\n", mustAutoReg ? "FAILED" : "successful"));
+
+ mustAutoReg = PR_TRUE;
+ }
+#endif // DEBUG
+ if(mustAutoReg)
+ gInterfaceInfoManager->AutoRegisterInterfaces();
+ }
+ }
+ return gInterfaceInfoManager;
+}
+
+void
+xptiInterfaceInfoManager::FreeInterfaceInfoManager()
+{
+ if(gInterfaceInfoManager)
+ gInterfaceInfoManager->LogStats();
+
+ NS_IF_RELEASE(gInterfaceInfoManager);
+}
+
+PRBool
+xptiInterfaceInfoManager::IsValid()
+{
+ return mWorkingSet.IsValid() &&
+ mResolveLock &&
+ mAutoRegLock &&
+ mInfoMonitor &&
+ mAdditionalManagersLock;
+}
+
+xptiInterfaceInfoManager::xptiInterfaceInfoManager(nsISupportsArray* aSearchPath)
+ : mWorkingSet(aSearchPath),
+ mOpenLogFile(nsnull),
+ mResolveLock(PR_NewLock()),
+ mAutoRegLock(PR_NewLock()),
+ mInfoMonitor(nsAutoMonitor::NewMonitor("xptiInfoMonitor")),
+ mAdditionalManagersLock(PR_NewLock()),
+ mSearchPath(aSearchPath)
+{
+ const char* statsFilename = PR_GetEnv("MOZILLA_XPTI_STATS");
+ if(statsFilename)
+ {
+ mStatsLogFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if(mStatsLogFile &&
+ NS_SUCCEEDED(mStatsLogFile->InitWithNativePath(nsDependentCString(statsFilename))))
+ {
+ printf("* Logging xptinfo stats to: %s\n", statsFilename);
+ }
+ else
+ {
+ printf("* Failed to create xptinfo stats file: %s\n", statsFilename);
+ mStatsLogFile = nsnull;
+ }
+ }
+
+ const char* autoRegFilename = PR_GetEnv("MOZILLA_XPTI_REGLOG");
+ if(autoRegFilename)
+ {
+ mAutoRegLogFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if(mAutoRegLogFile &&
+ NS_SUCCEEDED(mAutoRegLogFile->InitWithNativePath(nsDependentCString(autoRegFilename))))
+ {
+ printf("* Logging xptinfo autoreg to: %s\n", autoRegFilename);
+ }
+ else
+ {
+ printf("* Failed to create xptinfo autoreg file: %s\n", autoRegFilename);
+ mAutoRegLogFile = nsnull;
+ }
+ }
+}
+
+xptiInterfaceInfoManager::~xptiInterfaceInfoManager()
+{
+ // We only do this on shutdown of the service.
+ mWorkingSet.InvalidateInterfaceInfos();
+
+ if(mResolveLock)
+ PR_DestroyLock(mResolveLock);
+ if(mAutoRegLock)
+ PR_DestroyLock(mAutoRegLock);
+ if(mInfoMonitor)
+ nsAutoMonitor::DestroyMonitor(mInfoMonitor);
+ if(mAdditionalManagersLock)
+ PR_DestroyLock(mAdditionalManagersLock);
+
+ gInterfaceInfoManager = nsnull;
+#ifdef DEBUG
+ xptiInterfaceInfo::DEBUG_ShutdownNotification();
+ gCallCount = 0;
+#endif
+}
+
+static nsresult
+GetDirectoryFromDirService(const char* codename, nsILocalFile** aDir)
+{
+ NS_ASSERTION(codename,"loser!");
+ NS_ASSERTION(aDir,"loser!");
+
+ nsresult rv;
+ nsCOMPtr<nsIProperties> dirService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ return dirService->Get(codename, NS_GET_IID(nsILocalFile), (void**) aDir);
+}
+
+static PRBool
+AppendFromDirServiceList(const char* codename, nsISupportsArray* aPath)
+{
+ NS_ASSERTION(codename,"loser!");
+ NS_ASSERTION(aPath,"loser!");
+
+ nsCOMPtr<nsIProperties> dirService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+ if(!dirService)
+ return PR_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> fileList;
+ dirService->Get(codename, NS_GET_IID(nsISimpleEnumerator),
+ getter_AddRefs(fileList));
+ if(!fileList)
+ return PR_FALSE;
+
+ PRBool more;
+ while(NS_SUCCEEDED(fileList->HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ fileList->GetNext(getter_AddRefs(dir));
+ if(!dir || !aPath->AppendElement(dir))
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+// static
+PRBool xptiInterfaceInfoManager::BuildFileSearchPath(nsISupportsArray** aPath)
+{
+#ifdef DEBUG
+ NS_ASSERTION(!gCallCount++, "Expected only one call!");
+#endif
+
+ nsCOMPtr<nsISupportsArray> searchPath;
+ NS_NewISupportsArray(getter_AddRefs(searchPath));
+ if(!searchPath)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> compDir;
+
+ // Always put components directory first
+
+ if(NS_FAILED(GetDirectoryFromDirService(NS_XPCOM_COMPONENT_DIR,
+ getter_AddRefs(compDir))) ||
+ !searchPath->AppendElement(compDir))
+ {
+ return PR_FALSE;
+ }
+
+ // Add additional plugins dirs
+ // No error checking here since this is optional in some embeddings
+
+ // Add the GRE's component directory to searchPath if the
+ // application is using an GRE.
+ // An application indicates that it's using an GRE by returning
+ // a valid nsIFile via it's directory service provider interface.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/MRE.html
+ // for more info. on GREs
+ //
+ nsCOMPtr<nsILocalFile> greComponentDirectory;
+ nsresult rv = GetDirectoryFromDirService(NS_GRE_COMPONENT_DIR,
+ getter_AddRefs(greComponentDirectory));
+ if(NS_SUCCEEDED(rv) && greComponentDirectory)
+ {
+ // make sure we only append a directory if its a different one
+ PRBool equalsCompDir = PR_FALSE;
+ greComponentDirectory->Equals(compDir, &equalsCompDir);
+
+ if(!equalsCompDir)
+ searchPath->AppendElement(greComponentDirectory);
+ }
+
+ (void)AppendFromDirServiceList(NS_XPCOM_COMPONENT_DIR_LIST, searchPath);
+ (void)AppendFromDirServiceList(NS_APP_PLUGINS_DIR_LIST, searchPath);
+
+ NS_ADDREF(*aPath = searchPath);
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::GetCloneOfManifestLocation(nsILocalFile** aFile)
+{
+ // We *trust* that this will not change!
+ nsCOMPtr<nsILocalFile> lf;
+ nsresult rv = GetDirectoryFromDirService(NS_XPCOM_XPTI_REGISTRY_FILE,
+ getter_AddRefs(lf));
+
+ if (NS_FAILED(rv)) return PR_FALSE;
+
+ rv = xptiCloneLocalFile(lf, aFile);
+ if (NS_FAILED(rv)) return PR_FALSE;
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::GetApplicationDir(nsILocalFile** aDir)
+{
+ // We *trust* that this will not change!
+ return NS_SUCCEEDED(GetDirectoryFromDirService(NS_XPCOM_CURRENT_PROCESS_DIR, aDir));
+}
+
+PRBool
+xptiInterfaceInfoManager::BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList)
+{
+ NS_ASSERTION(aFileList, "loser!");
+
+ nsresult rv;
+
+ nsCOMPtr<nsISupportsArray> fileList =
+ do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
+ if(!fileList)
+ return PR_FALSE;
+
+ PRUint32 pathCount;
+ if(NS_FAILED(aSearchPath->Count(&pathCount)))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < pathCount; i++)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ rv = xptiCloneElementAsLocalFile(aSearchPath, i, getter_AddRefs(dir));
+ if(NS_FAILED(rv) || !dir)
+ return PR_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
+ if(NS_FAILED(rv) || !entries)
+ continue;
+
+ PRUint32 count = 0;
+ PRBool hasMore;
+ while(NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> sup;
+ entries->GetNext(getter_AddRefs(sup));
+ if(!sup)
+ return PR_FALSE;
+ nsCOMPtr<nsILocalFile> file = do_QueryInterface(sup);
+ if(!file)
+ return PR_FALSE;
+
+ PRBool isFile;
+ if(NS_FAILED(file->IsFile(&isFile)) || !isFile)
+ {
+ continue;
+ }
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ if(xptiFileType::IsUnknown(name.get()))
+ continue;
+
+ LOG_AUTOREG(("found file: %s\n", name.get()));
+
+ if(!fileList->InsertElementAt(file, count))
+ return PR_FALSE;
+ ++count;
+ }
+ }
+
+ NS_ADDREF(*aFileList = fileList);
+ return PR_TRUE;
+}
+
+XPTHeader*
+xptiInterfaceInfoManager::ReadXPTFile(nsILocalFile* aFile,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aFile, "loser!");
+
+ XPTHeader *header = nsnull;
+ char *whole = nsnull;
+ PRFileDesc* fd = nsnull;
+ XPTState *state = nsnull;
+ XPTCursor cursor;
+ PRInt32 flen;
+ PRInt64 fileSize;
+
+ PRBool saveFollowLinks;
+ aFile->GetFollowLinks(&saveFollowLinks);
+ aFile->SetFollowLinks(PR_TRUE);
+
+ if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
+ {
+ aFile->SetFollowLinks(saveFollowLinks);
+ return nsnull;
+ }
+
+ whole = new char[flen];
+ if (!whole)
+ {
+ aFile->SetFollowLinks(saveFollowLinks);
+ return nsnull;
+ }
+
+ // all exits from on here should be via 'goto out'
+
+ if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
+ {
+ goto out;
+ }
+
+ if(flen > PR_Read(fd, whole, flen))
+ {
+ goto out;
+ }
+
+ if(!(state = XPT_NewXDRState(XPT_DECODE, whole, flen)))
+ {
+ goto out;
+ }
+
+ if(!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor))
+ {
+ goto out;
+ }
+
+ if (!XPT_DoHeader(aWorkingSet->GetStructArena(), &cursor, &header))
+ {
+ header = nsnull;
+ goto out;
+ }
+
+ out:
+ if(fd)
+ PR_Close(fd);
+ if(state)
+ XPT_DestroyXDRState(state);
+ if(whole)
+ delete [] whole;
+ aFile->SetFollowLinks(saveFollowLinks);
+ return header;
+}
+
+PRBool
+xptiInterfaceInfoManager::LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet)
+{
+ if(!aWorkingSet)
+ aWorkingSet = &mWorkingSet;
+
+ if(!aWorkingSet->IsValid())
+ return PR_FALSE;
+
+ xptiFile* fileRecord = &aWorkingSet->GetFileAt(aTypelibRecord.GetFileIndex());
+ xptiZipItem* zipItem = nsnull;
+
+ nsCOMPtr<nsILocalFile> file;
+ if(NS_FAILED(aWorkingSet->GetCloneOfDirectoryAt(fileRecord->GetDirectory(),
+ getter_AddRefs(file))) || !file)
+ return PR_FALSE;
+
+ if(NS_FAILED(file->AppendNative(nsDependentCString(fileRecord->GetName()))))
+ return PR_FALSE;
+
+ XPTHeader* header;
+
+ if(aTypelibRecord.IsZip())
+ {
+ zipItem = &aWorkingSet->GetZipItemAt(aTypelibRecord.GetZipItemIndex());
+
+ // See the big comment below in the 'non-zip' case...
+ if(zipItem->GetGuts())
+ {
+ NS_ERROR("Trying to load an xpt file from a zip twice");
+
+ // Force an autoreg on next run
+ (void) xptiManifest::Delete(this);
+
+ return PR_FALSE;
+ }
+
+ LOG_LOAD(("# loading zip item %s::%s\n", fileRecord->GetName(), zipItem->GetName()));
+
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIInputStream> stream;
+ rv = loader->LoadEntry(file, zipItem->GetName(),
+ getter_AddRefs(stream));
+
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+
+ header =
+ xptiZipLoader::ReadXPTFileFromInputStream(stream, aWorkingSet);
+ } else {
+ header = nsnull;
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ else
+ {
+ // The file would only have guts already if we previously failed to
+ // find an interface info in a file where the manifest claimed it was
+ // going to be.
+ //
+ // Normally, when the file gets loaded (and the guts set) then all
+ // interfaces would also be resolved. So, if we are here again for
+ // the same file then there must have been some interface that was
+ // expected but not present. Now we are explicitly trying to find it
+ // and it isn't going to be there this time either.
+ //
+ // This is an assertion style error in a DEBUG build because it shows
+ // that we failed to detect this in autoreg. For release builds (where
+ // autoreg is not run on every startup) it is just bad. But by returning
+ // PR_FALSE we mark this interface as RESOLVE_FAILED and get on with
+ // things without crashing or anything.
+ //
+ // We don't want to do an autoreg here because this is too much of an
+ // edge case (and in that odd case it might autoreg multiple times if
+ // many interfaces had been removed). But, by deleting the manifest we
+ // force the system to get it right on the next run.
+
+ if(fileRecord->GetGuts())
+ {
+ NS_ERROR("Trying to load an xpt file twice");
+
+ // Force an autoreg on next run
+ (void) xptiManifest::Delete(this);
+
+ return PR_FALSE;
+ }
+
+ LOG_LOAD(("^ loading file %s\n", fileRecord->GetName()));
+ header = ReadXPTFile(file, aWorkingSet);
+ }
+
+ if(!header)
+ return PR_FALSE;
+
+
+ if(aTypelibRecord.IsZip())
+ {
+ // This also allocs zipItem.GetGuts() used below.
+ if(!zipItem->SetHeader(header, aWorkingSet))
+ return PR_FALSE;
+ }
+ else
+ {
+ // This also allocs fileRecord.GetGuts() used below.
+ if(!fileRecord->SetHeader(header, aWorkingSet))
+ return PR_FALSE;
+ }
+
+ // For each interface in the header we want to find the xptiInterfaceInfo
+ // object and set its resolution info.
+
+ for(PRUint16 i = 0; i < header->num_interfaces; i++)
+ {
+ static const nsID zeroIID =
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+ XPTInterfaceDirectoryEntry* iface = header->interface_directory + i;
+
+ xptiHashEntry* hashEntry;
+
+ if(!iface->iid.Equals(zeroIID))
+ {
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ &iface->iid, PL_DHASH_LOOKUP);
+ }
+ else
+ {
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ iface->name, PL_DHASH_LOOKUP);
+ }
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ // This one is just not resolved anywhere!
+ continue;
+ }
+
+ if(aTypelibRecord.IsZip())
+ zipItem->GetGuts()->SetEntryAt(i, entry);
+ else
+ fileRecord->GetGuts()->SetEntryAt(i, entry);
+
+ XPTInterfaceDescriptor* descriptor = iface->interface_descriptor;
+
+ if(descriptor && aTypelibRecord.Equals(entry->GetTypelibRecord()))
+ entry->PartiallyResolveLocked(descriptor, aWorkingSet);
+ }
+ return PR_TRUE;
+}
+
+static int
+IndexOfFileWithName(const char* aName, const xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aName, "loser!");
+
+ for(PRUint32 i = 0; i < aWorkingSet->GetFileCount(); ++i)
+ {
+ if(0 == PL_strcmp(aName, aWorkingSet->GetFileAt(i).GetName()))
+ return i;
+ }
+ return -1;
+}
+
+static int
+IndexOfDirectoryOfFile(nsISupportsArray* aSearchPath, nsILocalFile* aFile)
+{
+ nsCOMPtr<nsIFile> parent;
+ aFile->GetParent(getter_AddRefs(parent));
+ if(parent)
+ {
+ PRUint32 count = 0;
+ aSearchPath->Count(&count);
+ NS_ASSERTION(count, "broken search path! bad count");
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIFile> current;
+ aSearchPath->QueryElementAt(i, NS_GET_IID(nsIFile),
+ getter_AddRefs(current));
+ NS_ASSERTION(current, "broken search path! bad element");
+ PRBool same;
+ if(NS_SUCCEEDED(parent->Equals(current, &same)) && same)
+ return (int) i;
+ }
+ }
+ NS_ERROR("file not in search directory!");
+ return -1;
+}
+
+struct SortData
+{
+ nsISupportsArray* mSearchPath;
+ xptiWorkingSet* mWorkingSet;
+};
+
+PR_STATIC_CALLBACK(int)
+xptiSortFileList(const void * p1, const void *p2, void * closure)
+{
+ nsILocalFile* pFile1 = *((nsILocalFile**) p1);
+ nsILocalFile* pFile2 = *((nsILocalFile**) p2);
+ SortData* data = (SortData*) closure;
+
+ nsCAutoString name1;
+ nsCAutoString name2;
+
+ if(NS_FAILED(pFile1->GetNativeLeafName(name1)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+ if(NS_FAILED(pFile2->GetNativeLeafName(name2)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+
+ int index1 = IndexOfFileWithName(name1.get(), data->mWorkingSet);
+ int index2 = IndexOfFileWithName(name2.get(), data->mWorkingSet);
+
+ // Get these now in case we need them later.
+ PRBool isXPT1 = xptiFileType::IsXPT(name1.get());
+ PRBool isXPT2 = xptiFileType::IsXPT(name2.get());
+ int nameOrder = Compare(name1, name2);
+
+ // both in workingSet, preserve old order
+ if(index1 != -1 && index2 != -1)
+ return index1 - index2;
+
+ if(index1 != -1)
+ return 1;
+
+ if(index2 != -1)
+ return -1;
+
+ // neither is in workingset
+
+ // check how they compare in search path order
+
+ int dirIndex1 = IndexOfDirectoryOfFile(data->mSearchPath, pFile1);
+ int dirIndex2 = IndexOfDirectoryOfFile(data->mSearchPath, pFile2);
+
+ if(dirIndex1 != dirIndex2)
+ return dirIndex1 - dirIndex2;
+
+ // .xpt files come before archives (.zip, .jar, etc)
+ if(isXPT1 &&!isXPT2)
+ return -1;
+
+ if(!isXPT1 && isXPT2)
+ return 1;
+
+ // neither element is in the workingSet and both are same type and in
+ // the same directory, sort by size
+
+ PRInt64 size1;
+ PRInt64 size2;
+
+ if(NS_FAILED(pFile1->GetFileSize(&size1)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+ if(NS_FAILED(pFile2->GetFileSize(&size2)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+
+ // by size with largest first, or by name if size is the same
+ int sizeDiff = int(PRInt32(nsInt64(size2) - nsInt64(size1)));
+ return sizeDiff != 0 ? sizeDiff : nameOrder;
+}
+
+nsILocalFile**
+xptiInterfaceInfoManager::BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ // We want to end up with a file list that starts with the files from
+ // aWorkingSet (but only those that are in aFileList) in the order in
+ // which they appeared in aWorkingSet-> Following those files will be those
+ // files in aFileList which are not in aWorkingSet-> These additional
+ // files will be ordered by file size (larger first) but all .xpt files
+ // will preceed all zipfile of those files not already in the working set.
+ // To do this we will do a fancy sort on a copy of aFileList.
+
+ nsILocalFile** orderedFileList = nsnull;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)) ||
+ 0 == countOfFilesInFileList)
+ return nsnull;
+
+ orderedFileList = (nsILocalFile**)
+ XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(nsILocalFile*) * countOfFilesInFileList);
+
+ if(!orderedFileList)
+ return nsnull;
+
+ // fill our list for sorting
+ for(i = 0; i < countOfFilesInFileList; ++i)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ // Intentionally NOT addref'd cuz we know these are pinned in aFileList.
+ orderedFileList[i] = file.get();
+ }
+
+ // sort the filelist
+
+ SortData sortData = {aSearchPath, aWorkingSet};
+ NS_QuickSort(orderedFileList, countOfFilesInFileList, sizeof(nsILocalFile*),
+ xptiSortFileList, &sortData);
+
+ return orderedFileList;
+}
+
+xptiInterfaceInfoManager::AutoRegMode
+xptiInterfaceInfoManager::DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ PRUint32 countOfFilesInWorkingSet = aWorkingSet->GetFileCount();
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+ PRUint32 k;
+
+ if(0 == countOfFilesInWorkingSet)
+ {
+ // Loading manifest might have failed. Better safe...
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ if(countOfFilesInFileList == countOfFilesInWorkingSet)
+ {
+ // try to determine if *no* files are new or changed.
+
+ PRBool same = PR_TRUE;
+ for(i = 0; i < countOfFilesInFileList && same; ++i)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ PRInt64 size;
+ PRInt64 date;
+ nsCAutoString name;
+ PRUint32 directory;
+
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &directory))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ for(k = 0; k < countOfFilesInWorkingSet; ++k)
+ {
+ xptiFile& target = aWorkingSet->GetFileAt(k);
+
+ if(directory == target.GetDirectory() &&
+ name.Equals(target.GetName()))
+ {
+ if(nsInt64(size) != target.GetSize() ||
+ nsInt64(date) != target.GetDate())
+ same = PR_FALSE;
+ break;
+ }
+ }
+ // failed to find our file in the workingset?
+ if(k == countOfFilesInWorkingSet)
+ same = PR_FALSE;
+ }
+ if(same)
+ return NO_FILES_CHANGED;
+ }
+ else if(countOfFilesInFileList > countOfFilesInWorkingSet)
+ {
+ // try to determine if the only changes are additional new files
+ // XXX Wimping out and doing this as a separate walk through the lists.
+
+ PRBool same = PR_TRUE;
+
+ for(i = 0; i < countOfFilesInWorkingSet && same; ++i)
+ {
+ xptiFile& target = aWorkingSet->GetFileAt(i);
+
+ for(k = 0; k < countOfFilesInFileList; ++k)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(k, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ PRBool sameName = name.Equals(target.GetName());
+ if(sameName)
+ {
+ if(nsInt64(size) != target.GetSize() ||
+ nsInt64(date) != target.GetDate())
+ same = PR_FALSE;
+ break;
+ }
+ }
+ // failed to find our file in the file list?
+ if(k == countOfFilesInFileList)
+ same = PR_FALSE;
+ }
+ if(same)
+ return FILES_ADDED_ONLY;
+ }
+
+ return FULL_VALIDATION_REQUIRED;
+}
+
+PRBool
+xptiInterfaceInfoManager::AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ nsILocalFile** orderedFileArray;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ return PR_FALSE;
+ NS_ASSERTION(countOfFilesInFileList, "loser!");
+ NS_ASSERTION(countOfFilesInFileList > aWorkingSet->GetFileCount(), "loser!");
+
+ orderedFileArray = BuildOrderedFileArray(aSearchPath, aFileList, aWorkingSet);
+
+ if(!orderedFileArray)
+ return PR_FALSE;
+
+ // Make enough space in aWorkingset for additions to xptiFile array.
+
+ if(!aWorkingSet->ExtendFileArray(countOfFilesInFileList))
+ return PR_FALSE;
+
+ // For each file that is not already in our working set, add any valid
+ // interfaces that don't conflict with previous interfaces added.
+ for(i = 0; i < countOfFilesInFileList; i++)
+ {
+ nsILocalFile* file = orderedFileArray[i];
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ PRUint32 dir;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &dir))
+ {
+ return PR_FALSE;
+ }
+
+
+ if(xptiWorkingSet::NOT_FOUND != aWorkingSet->FindFile(dir, name.get()))
+ {
+ // This file was found in the working set, so skip it.
+ continue;
+ }
+
+ LOG_AUTOREG((" finding interfaces in new file: %s\n", name.get()));
+
+ xptiFile fileRecord;
+ fileRecord = xptiFile(nsInt64(size), nsInt64(date), dir,
+ name.get(), aWorkingSet);
+
+ if(xptiFileType::IsXPT(fileRecord.GetName()))
+ {
+ XPTHeader* header = ReadXPTFile(file, aWorkingSet);
+ if(!header)
+ {
+ // XXX do something!
+ NS_ERROR("");
+ continue;
+ }
+
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount());
+
+ PRBool AddedFile = PR_FALSE;
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this file then
+ // setup the fileRecord for the header and infos.
+ if(!AddedFile)
+ {
+ if(!fileRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ AddedFile = PR_TRUE;
+ }
+ fileRecord.GetGuts()->SetEntryAt(k, entry);
+ }
+
+ // This will correspond to typelibRecord above.
+ aWorkingSet->AppendFile(fileRecord);
+ }
+ else // its another kind of archive
+ {
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIXPTLoaderSink> sink =
+ new xptiZipLoaderSink(this, aWorkingSet);
+ if (!sink)
+ return PR_FALSE;
+
+ rv = loader->EnumerateEntries(file, sink);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+ // This will correspond to typelibRecord used in
+ // xptiInterfaceInfoManager::FoundEntry.
+ aWorkingSet->AppendFile(fileRecord);
+ } else {
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ nsILocalFile** orderedFileArray;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+
+ if(!aWorkingSet->IsValid())
+ return PR_FALSE;
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ return PR_FALSE;
+
+ if(!countOfFilesInFileList)
+ {
+ // maybe there are no xpt files to register.
+ // a minimal install would have this case.
+ return PR_TRUE;
+ }
+
+ orderedFileArray = BuildOrderedFileArray(aSearchPath, aFileList, aWorkingSet);
+
+ if(!orderedFileArray)
+ return PR_FALSE;
+
+ // DEBUG_DumpFileArray(orderedFileArray, countOfFilesInFileList);
+
+ // Make space in aWorkingset for a new xptiFile array.
+
+ if(!aWorkingSet->NewFileArray(countOfFilesInFileList))
+ return PR_FALSE;
+
+ aWorkingSet->ClearZipItems();
+ aWorkingSet->ClearHashTables();
+
+ // For each file, add any valid interfaces that don't conflict with
+ // previous interfaces added.
+ for(i = 0; i < countOfFilesInFileList; i++)
+ {
+ nsILocalFile* file = orderedFileArray[i];
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ PRUint32 dir;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &dir))
+ {
+ return PR_FALSE;
+ }
+
+ LOG_AUTOREG((" finding interfaces in file: %s\n", name.get()));
+
+ xptiFile fileRecord;
+ fileRecord = xptiFile(nsInt64(size), nsInt64(date), dir,
+ name.get(), aWorkingSet);
+
+// printf("* found %s\n", fileRecord.GetName());
+
+
+ if(xptiFileType::IsXPT(fileRecord.GetName()))
+ {
+ XPTHeader* header = ReadXPTFile(file, aWorkingSet);
+ if(!header)
+ {
+ // XXX do something!
+ NS_ERROR("Unable to read an XPT file, turn logging on to see which file");
+ LOG_AUTOREG((" unable to read file\n"));
+ continue;
+ }
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount());
+
+ PRBool AddedFile = PR_FALSE;
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this file then
+ // setup the fileRecord for the header and infos.
+ if(!AddedFile)
+ {
+ if(!fileRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ AddedFile = PR_TRUE;
+ }
+ fileRecord.GetGuts()->SetEntryAt(k, entry);
+ }
+
+ // This will correspond to typelibRecord above.
+ aWorkingSet->AppendFile(fileRecord);
+ }
+
+ else
+ {
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIXPTLoaderSink> sink =
+ new xptiZipLoaderSink(this, aWorkingSet);
+ if (!sink)
+ return PR_FALSE;
+
+ rv = loader->EnumerateEntries(file, sink);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+ // This will correspond to typelibRecord used in
+ // xptiInterfaceInfoManager::FoundEntry.
+ aWorkingSet->AppendFile(fileRecord);
+ } else {
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ }
+ return PR_TRUE;
+}
+
+NS_IMPL_ISUPPORTS1(xptiZipLoaderSink, nsIXPTLoaderSink)
+
+// implement nsIXPTLoader
+NS_IMETHODIMP
+xptiZipLoaderSink::FoundEntry(const char* entryName,
+ PRInt32 index,
+ nsIInputStream *aStream)
+{
+ XPTHeader *header =
+ xptiZipLoader::ReadXPTFileFromInputStream(aStream, mWorkingSet);
+ if (!header)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!mManager->FoundZipEntry(entryName, index, header, mWorkingSet))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+// implement xptiEntrySink
+PRBool
+xptiInterfaceInfoManager::FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet)
+{
+
+ NS_ASSERTION(entryName, "loser!");
+ NS_ASSERTION(header, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+
+ int countOfInterfacesAddedForItem = 0;
+ xptiZipItem zipItemRecord(entryName, aWorkingSet);
+
+ LOG_AUTOREG((" finding interfaces in file: %s\n", entryName));
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d. Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ if(!header->num_interfaces)
+ {
+ // We are not interested in files without interfaces.
+ return PR_TRUE;
+ }
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount(),
+ aWorkingSet->GetZipItemCount());
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this item
+ // then setup the zipItemRecord for the header and infos.
+ if(!countOfInterfacesAddedForItem)
+ {
+ // XXX fix this!
+ if(!zipItemRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ }
+
+ // zipItemRecord.GetGuts()->SetEntryAt(k, entry);
+ ++countOfInterfacesAddedForItem;
+ }
+
+ if(countOfInterfacesAddedForItem)
+ {
+ if(!aWorkingSet->GetZipItemFreeSpace())
+ {
+ if(!aWorkingSet->ExtendZipItemArray(
+ aWorkingSet->GetZipItemCount() + 20))
+ {
+ // out of space!
+ return PR_FALSE;
+ }
+ }
+ aWorkingSet->AppendZipItem(zipItemRecord);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded)
+{
+ NS_ASSERTION(iface, "loser!");
+ NS_ASSERTION(entryAdded, "loser!");
+
+ *entryAdded = nsnull;
+
+ if(!iface->interface_descriptor)
+ {
+ // Not resolved, ignore this one.
+ // XXX full logging might note this...
+ return PR_TRUE;
+ }
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable, &iface->iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(entry)
+ {
+ // XXX validate this info to find possible inconsistencies
+ LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name));
+ return PR_TRUE;
+ }
+
+ // Build a new xptiInterfaceEntry object and hook it up.
+
+ entry = xptiInterfaceEntry::NewEntry(iface->name, strlen(iface->name),
+ iface->iid,
+ typelibRecord, aWorkingSet);
+ if(!entry)
+ {
+ // XXX bad!
+ return PR_FALSE;
+ }
+
+ //XXX We should SetHeader too as part of the validation, no?
+ entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ entry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ entry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ *entryAdded = entry;
+
+ LOG_AUTOREG((" added interface: %s\n", iface->name));
+
+ return PR_TRUE;
+}
+
+// local struct used to pass two pointers as one pointer
+struct TwoWorkingSets
+{
+ TwoWorkingSets(xptiWorkingSet* src, xptiWorkingSet* dest)
+ : aSrcWorkingSet(src), aDestWorkingSet(dest) {}
+
+ xptiWorkingSet* aSrcWorkingSet;
+ xptiWorkingSet* aDestWorkingSet;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Merger(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* srcEntry = ((xptiHashEntry*)hdr)->value;
+ xptiWorkingSet* aSrcWorkingSet = ((TwoWorkingSets*)arg)->aSrcWorkingSet;
+ xptiWorkingSet* aDestWorkingSet = ((TwoWorkingSets*)arg)->aDestWorkingSet;
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
+ srcEntry->GetTheIID(), PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* destEntry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(destEntry)
+ {
+ // Let's see if this is referring to the same exact typelib
+
+ const char* destFilename =
+ aDestWorkingSet->GetTypelibFileName(destEntry->GetTypelibRecord());
+
+ const char* srcFilename =
+ aSrcWorkingSet->GetTypelibFileName(srcEntry->GetTypelibRecord());
+
+ if(0 == PL_strcmp(destFilename, srcFilename) &&
+ (destEntry->GetTypelibRecord().GetZipItemIndex() ==
+ srcEntry->GetTypelibRecord().GetZipItemIndex()))
+ {
+ // This is the same item.
+ // But... Let's make sure they didn't change the interface name.
+ // There are wacky developers that do stuff like that!
+ if(0 == PL_strcmp(destEntry->GetTheName(), srcEntry->GetTheName()))
+ return PL_DHASH_NEXT;
+ }
+ }
+
+ // Clone the xptiInterfaceEntry into our destination WorkingSet.
+
+ xptiTypelib typelibRecord;
+
+ uint16 fileIndex = srcEntry->GetTypelibRecord().GetFileIndex();
+ uint16 zipItemIndex = srcEntry->GetTypelibRecord().GetZipItemIndex();
+
+ fileIndex += aDestWorkingSet->mFileMergeOffsetMap[fileIndex];
+
+ // If it is not a zipItem, then the original index is fine.
+ if(srcEntry->GetTypelibRecord().IsZip())
+ zipItemIndex += aDestWorkingSet->mZipItemMergeOffsetMap[zipItemIndex];
+
+ typelibRecord.Init(fileIndex, zipItemIndex);
+
+ destEntry = xptiInterfaceEntry::NewEntry(*srcEntry, typelibRecord,
+ aDestWorkingSet);
+ if(!destEntry)
+ {
+ // XXX bad! should log
+ return PL_DHASH_NEXT;
+ }
+
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mNameTable,
+ destEntry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = destEntry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
+ destEntry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = destEntry;
+
+ return PL_DHASH_NEXT;
+}
+
+PRBool
+xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet)
+{
+
+ PRUint32 i;
+
+ // Combine file lists.
+
+ PRUint32 originalFileCount = aDestWorkingSet->GetFileCount();
+ PRUint32 additionalFileCount = aSrcWorkingSet->GetFileCount();
+
+ // Create a new array big enough to hold both lists and copy existing files
+
+ if(additionalFileCount)
+ {
+ if(!aDestWorkingSet->ExtendFileArray(originalFileCount +
+ additionalFileCount))
+ return PR_FALSE;
+
+ // Now we are where we started, but we know we have enough space.
+
+ // Prepare offset array for later fixups.
+ // NOTE: Storing with dest, but alloc'ing from src. This is intentional.
+ aDestWorkingSet->mFileMergeOffsetMap = (PRUint32*)
+ XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
+ additionalFileCount * sizeof(PRUint32));
+ if(!aDestWorkingSet->mFileMergeOffsetMap)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < additionalFileCount; ++i)
+ {
+ xptiFile& srcFile = aSrcWorkingSet->GetFileAt(i);
+ PRUint32 k;
+ for(k = 0; k < originalFileCount; ++k)
+ {
+ // If file (with same name, date, and time) is in both lists
+ // then reuse that record.
+ xptiFile& destFile = aDestWorkingSet->GetFileAt(k);
+ if(srcFile.Equals(destFile))
+ {
+ aDestWorkingSet->mFileMergeOffsetMap[i] = k - i;
+ break;
+ }
+ }
+ if(k == originalFileCount)
+ {
+ // No match found, tack it on the end.
+
+ PRUint32 newIndex = aDestWorkingSet->GetFileCount();
+
+ aDestWorkingSet->AppendFile(xptiFile(srcFile, aDestWorkingSet));
+
+ // Fixup the merge offset map.
+ aDestWorkingSet->mFileMergeOffsetMap[i] = newIndex - i;
+ }
+ }
+
+ // Combine ZipItem lists.
+
+ PRUint32 originalZipItemCount = aDestWorkingSet->GetZipItemCount();
+ PRUint32 additionalZipItemCount = aSrcWorkingSet->GetZipItemCount();
+
+ // Create a new array big enough to hold both lists and copy existing ZipItems
+
+ if(additionalZipItemCount)
+ {
+ if(!aDestWorkingSet->ExtendZipItemArray(originalZipItemCount +
+ additionalZipItemCount))
+ return PR_FALSE;
+
+ // Now we are where we started, but we know we have enough space.
+
+ // Prepare offset array for later fixups.
+ // NOTE: Storing with dest, but alloc'ing from src. This is intentional.
+ aDestWorkingSet->mZipItemMergeOffsetMap = (PRUint32*)
+ XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
+ additionalZipItemCount * sizeof(PRUint32));
+ if(!aDestWorkingSet->mZipItemMergeOffsetMap)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < additionalZipItemCount; ++i)
+ {
+ xptiZipItem& srcZipItem = aSrcWorkingSet->GetZipItemAt(i);
+ PRUint32 k;
+ for(k = 0; k < originalZipItemCount; ++k)
+ {
+ // If ZipItem (with same name) is in both lists
+ // then reuse that record.
+ xptiZipItem& destZipItem = aDestWorkingSet->GetZipItemAt(k);
+ if(srcZipItem.Equals(destZipItem))
+ {
+ aDestWorkingSet->mZipItemMergeOffsetMap[i] = k - i;
+ break;
+ }
+ }
+ if(k == originalZipItemCount)
+ {
+ // No match found, tack it on the end.
+
+ PRUint32 newIndex = aDestWorkingSet->GetZipItemCount();
+
+ aDestWorkingSet->AppendZipItem(
+ xptiZipItem(srcZipItem, aDestWorkingSet));
+
+ // Fixup the merge offset map.
+ aDestWorkingSet->mZipItemMergeOffsetMap[i] = newIndex - i;
+ }
+ }
+
+ // Migrate xptiInterfaceInfos
+
+ TwoWorkingSets sets(aSrcWorkingSet, aDestWorkingSet);
+
+ PL_DHashTableEnumerate(aSrcWorkingSet->mNameTable, xpti_Merger, &sets);
+
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileList(nsISupportsArray* aFileList)
+{
+ PRUint32 count;
+
+ if(NS_FAILED(aFileList->Count(&count)))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ if(!file)
+ return PR_FALSE;
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ printf("* found %s\n", name.get());
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet)
+{
+ for(PRUint16 i = 0; i < aWorkingSet->GetFileCount(); ++i)
+ {
+ xptiFile& record = aWorkingSet->GetFileAt(i);
+
+ printf("! has %s\n", record.GetName());
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileArray(nsILocalFile** aFileArray,
+ PRUint32 count)
+{
+ // dump the sorted list
+ for(PRUint32 i = 0; i < count; ++i)
+ {
+ nsILocalFile* file = aFileArray[i];
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ printf("found file: %s\n", name.get());
+ }
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+
+// static
+void
+xptiInterfaceInfoManager::WriteToLog(const char *fmt, ...)
+{
+ if(!gInterfaceInfoManager)
+ return;
+
+ PRFileDesc* fd = gInterfaceInfoManager->GetOpenLogFile();
+ if(fd)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ PR_vfprintf(fd, fmt, ap);
+ va_end(ap);
+ }
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ResolvedFileNameLogger(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ xptiInterfaceInfoManager* mgr = (xptiInterfaceInfoManager*) arg;
+
+ if(entry->IsFullyResolved())
+ {
+ xptiWorkingSet* aWorkingSet = mgr->GetWorkingSet();
+ PRFileDesc* fd = mgr->GetOpenLogFile();
+
+ const xptiTypelib& typelib = entry->GetTypelibRecord();
+ const char* filename =
+ aWorkingSet->GetFileAt(typelib.GetFileIndex()).GetName();
+
+ if(typelib.IsZip())
+ {
+ const char* zipItemName =
+ aWorkingSet->GetZipItemAt(typelib.GetZipItemIndex()).GetName();
+ PR_fprintf(fd, "xpti used interface: %s from %s::%s\n",
+ entry->GetTheName(), filename, zipItemName);
+ }
+ else
+ {
+ PR_fprintf(fd, "xpti used interface: %s from %s\n",
+ entry->GetTheName(), filename);
+ }
+ }
+ return PL_DHASH_NEXT;
+}
+
+void
+xptiInterfaceInfoManager::LogStats()
+{
+ PRUint32 i;
+
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(this, mStatsLogFile, PR_FALSE);
+
+ PRFileDesc* fd = GetOpenLogFile();
+ if(!fd)
+ return;
+
+ // Show names of xpt (only) files from which at least one interface
+ // was resolved.
+
+ PRUint32 fileCount = mWorkingSet.GetFileCount();
+ for(i = 0; i < fileCount; ++i)
+ {
+ xptiFile& f = mWorkingSet.GetFileAt(i);
+ if(f.GetGuts())
+ PR_fprintf(fd, "xpti used file: %s\n", f.GetName());
+ }
+
+ PR_fprintf(fd, "\n");
+
+ // Show names of xptfiles loaded from zips from which at least
+ // one interface was resolved.
+
+ PRUint32 zipItemCount = mWorkingSet.GetZipItemCount();
+ for(i = 0; i < zipItemCount; ++i)
+ {
+ xptiZipItem& zi = mWorkingSet.GetZipItemAt(i);
+ if(zi.GetGuts())
+ PR_fprintf(fd, "xpti used file from zip: %s\n", zi.GetName());
+ }
+
+ PR_fprintf(fd, "\n");
+
+ // Show name of each interface that was fully resolved and the name
+ // of the file and (perhaps) zip from which it was loaded.
+
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable,
+ xpti_ResolvedFileNameLogger, this);
+
+}
+
+/***************************************************************************/
+
+// this is a private helper
+static nsresult
+EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
+{
+ xptiInterfaceInfo* info;
+ nsresult rv;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = entry->GetInterfaceInfo(&info);
+ if(NS_FAILED(rv))
+ return rv;
+
+ // Transfer the AddRef done by GetInterfaceInfo.
+ *_retval = NS_STATIC_CAST(nsIInterfaceInfo*, info);
+ return NS_OK;
+}
+
+/* nsIInterfaceInfo getInfoForIID (in nsIIDPtr iid); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ return EntryToInfo(entry, _retval);
+}
+
+/* nsIInterfaceInfo getInfoForName (in string name); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ return EntryToInfo(entry, _retval);
+}
+
+/* nsIIDPtr getIIDForName (in string name); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetIIDForName(const char *name, nsIID * *_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ return entry->GetIID(_retval);
+}
+
+/* string getNameForIID (in nsIIDPtr iid); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ return entry->GetName(_retval);
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ArrayAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ nsISupportsArray* array = (nsISupportsArray*) arg;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
+ array->AppendElement(ii);
+ return PL_DHASH_NEXT;
+}
+
+/* nsIEnumerator enumerateInterfaces (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator **_retval)
+{
+ // I didn't want to incur the size overhead of using nsHashtable just to
+ // make building an enumerator easier. So, this code makes a snapshot of
+ // the table using an nsISupportsArray and builds an enumerator for that.
+ // We can afford this transient cost.
+
+ nsCOMPtr<nsISupportsArray> array;
+ NS_NewISupportsArray(getter_AddRefs(array));
+ if(!array)
+ return NS_ERROR_UNEXPECTED;
+
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayAppender, array);
+
+ return array->Enumerate(_retval);
+}
+
+struct ArrayAndPrefix
+{
+ nsISupportsArray* array;
+ const char* prefix;
+ PRUint32 length;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ArrayPrefixAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ ArrayAndPrefix* args = (ArrayAndPrefix*) arg;
+
+ const char* name = entry->GetTheName();
+ if(name != PL_strnstr(name, args->prefix, args->length))
+ return PL_DHASH_NEXT;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
+ args->array->AppendElement(ii);
+ return PL_DHASH_NEXT;
+}
+
+/* nsIEnumerator enumerateInterfacesWhoseNamesStartWith (in string prefix); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(const char *prefix, nsIEnumerator **_retval)
+{
+ nsCOMPtr<nsISupportsArray> array;
+ NS_NewISupportsArray(getter_AddRefs(array));
+ if(!array)
+ return NS_ERROR_UNEXPECTED;
+
+ ArrayAndPrefix args = {array, prefix, PL_strlen(prefix)};
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayPrefixAppender, &args);
+
+ return array->Enumerate(_retval);
+}
+
+/* void autoRegisterInterfaces (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
+{
+ nsCOMPtr<nsISupportsArray> fileList;
+ AutoRegMode mode;
+ PRBool ok;
+
+ nsAutoLock lock(xptiInterfaceInfoManager::GetAutoRegLock(this));
+
+ xptiWorkingSet workingSet(mSearchPath);
+ if(!workingSet.IsValid())
+ return NS_ERROR_UNEXPECTED;
+
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(this, mAutoRegLogFile, PR_TRUE);
+
+ LOG_AUTOREG(("start AutoRegister\n"));
+
+ // We re-read the manifest rather than muck with the 'live' one.
+ // It is OK if this fails.
+ // XXX But we should track failure as a warning.
+ ok = xptiManifest::Read(this, &workingSet);
+
+ LOG_AUTOREG(("read of manifest %s\n", ok ? "successful" : "FAILED"));
+
+ // Grovel for all the typelibs we can find (in .xpt or .zip, .jar,...).
+ if(!BuildFileList(mSearchPath, getter_AddRefs(fileList)) || !fileList)
+ return NS_ERROR_UNEXPECTED;
+
+ // DEBUG_DumpFileList(fileList);
+
+ // Check to see how much work we need to do.
+ mode = DetermineAutoRegStrategy(mSearchPath, fileList, &workingSet);
+
+ switch(mode)
+ {
+ case NO_FILES_CHANGED:
+ LOG_AUTOREG(("autoreg strategy: no files changed\n"));
+ LOG_AUTOREG(("successful end of AutoRegister\n"));
+ return NS_OK;
+ case FILES_ADDED_ONLY:
+ LOG_AUTOREG(("autoreg strategy: files added only\n"));
+ if(!AddOnlyNewFilesFromFileList(mSearchPath, fileList, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to add new files\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ break;
+ case FULL_VALIDATION_REQUIRED:
+ LOG_AUTOREG(("autoreg strategy: doing full validation merge\n"));
+ if(!DoFullValidationMergeFromFileList(mSearchPath, fileList, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to do full validation\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ break;
+ default:
+ NS_ERROR("switch missing a case");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Failure to write the manifest is not fatal in production builds.
+ // However, this would require the next startup to find and read all the
+ // xpt files. This will make that startup slower. If this ever becomes a
+ // chronic problem for anyone, then we'll want to figure out why!
+
+ if(!xptiManifest::Write(this, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to write manifest\n"));
+ NS_ERROR("Failed to write xpti manifest!");
+ }
+
+ if(!MergeWorkingSets(&mWorkingSet, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to merge into live workingset\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+// DEBUG_DumpFileListInWorkingSet(mWorkingSet);
+
+ LOG_AUTOREG(("successful end of AutoRegister\n"));
+
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+class xptiAdditionalManagersEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ xptiAdditionalManagersEnumerator();
+
+ PRBool SizeTo(PRUint32 likelyCount) {return mArray.SizeTo(likelyCount);}
+ PRBool AppendElement(nsIInterfaceInfoManager* element);
+
+private:
+ ~xptiAdditionalManagersEnumerator() {}
+
+ nsSupportsArray mArray;
+ PRUint32 mIndex;
+ PRUint32 mCount;
+};
+
+NS_IMPL_ISUPPORTS1(xptiAdditionalManagersEnumerator, nsISimpleEnumerator)
+
+xptiAdditionalManagersEnumerator::xptiAdditionalManagersEnumerator()
+ : mIndex(0), mCount(0)
+{
+}
+
+PRBool xptiAdditionalManagersEnumerator::AppendElement(nsIInterfaceInfoManager* element)
+{
+ if(!mArray.AppendElement(NS_STATIC_CAST(nsISupports*, element)))
+ return PR_FALSE;
+ mCount++;
+ return PR_TRUE;
+}
+
+/* boolean hasMoreElements (); */
+NS_IMETHODIMP xptiAdditionalManagersEnumerator::HasMoreElements(PRBool *_retval)
+{
+ *_retval = mIndex < mCount;
+ return NS_OK;
+}
+
+/* nsISupports getNext (); */
+NS_IMETHODIMP xptiAdditionalManagersEnumerator::GetNext(nsISupports **_retval)
+{
+ if(!(mIndex < mCount))
+ {
+ NS_ERROR("Bad nsISimpleEnumerator caller!");
+ return NS_ERROR_FAILURE;
+ }
+
+ *_retval = mArray.ElementAt(mIndex++);
+ return *_retval ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/***************************************************************************/
+
+/* void addAdditionalManager (in nsIInterfaceInfoManager manager); */
+NS_IMETHODIMP xptiInterfaceInfoManager::AddAdditionalManager(nsIInterfaceInfoManager *manager)
+{
+ nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(manager);
+ nsISupports* ptrToAdd = weakRef ?
+ NS_STATIC_CAST(nsISupports*, weakRef) :
+ NS_STATIC_CAST(nsISupports*, manager);
+ { // scoped lock...
+ nsAutoLock lock(mAdditionalManagersLock);
+ PRInt32 index;
+ nsresult rv = mAdditionalManagers.GetIndexOf(ptrToAdd, &index);
+ if(NS_FAILED(rv) || -1 != index)
+ return NS_ERROR_FAILURE;
+ if(!mAdditionalManagers.AppendElement(ptrToAdd))
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+/* void removeAdditionalManager (in nsIInterfaceInfoManager manager); */
+NS_IMETHODIMP xptiInterfaceInfoManager::RemoveAdditionalManager(nsIInterfaceInfoManager *manager)
+{
+ nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(manager);
+ nsISupports* ptrToRemove = weakRef ?
+ NS_STATIC_CAST(nsISupports*, weakRef) :
+ NS_STATIC_CAST(nsISupports*, manager);
+ { // scoped lock...
+ nsAutoLock lock(mAdditionalManagersLock);
+ if(!mAdditionalManagers.RemoveElement(ptrToRemove))
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+/* PRBool hasAdditionalManagers (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::HasAdditionalManagers(PRBool *_retval)
+{
+ PRUint32 count;
+ nsresult rv = mAdditionalManagers.Count(&count);
+ *_retval = count != 0;
+ return rv;
+}
+
+/* nsISimpleEnumerator enumerateAdditionalManagers (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateAdditionalManagers(nsISimpleEnumerator **_retval)
+{
+ nsAutoLock lock(mAdditionalManagersLock);
+
+ PRUint32 count;
+ nsresult rv = mAdditionalManagers.Count(&count);
+ if(NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<xptiAdditionalManagersEnumerator> enumerator =
+ new xptiAdditionalManagersEnumerator();
+ if(!enumerator)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ enumerator->SizeTo(count);
+
+ for(PRUint32 i = 0; i < count; /* i incremented in the loop body */)
+ {
+ nsCOMPtr<nsISupports> raw =
+ dont_AddRef(mAdditionalManagers.ElementAt(i++));
+ if(!raw)
+ return NS_ERROR_FAILURE;
+ nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(raw);
+ if(weakRef)
+ {
+ nsCOMPtr<nsIInterfaceInfoManager> manager =
+ do_QueryReferent(weakRef);
+ if(manager)
+ {
+ if(!enumerator->AppendElement(manager))
+ return NS_ERROR_FAILURE;
+ }
+ else
+ {
+ // The manager is no more. Remove the element.
+ if(!mAdditionalManagers.RemoveElementAt(--i))
+ return NS_ERROR_FAILURE;
+ count--;
+ }
+ }
+ else
+ {
+ // We *know* we put a pointer to either a nsIWeakReference or
+ // an nsIInterfaceInfoManager into the array, so we can avoid an
+ // extra QI here and just do a cast.
+ if(!enumerator->AppendElement(
+ NS_REINTERPRET_CAST(nsIInterfaceInfoManager*, raw.get())))
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ NS_ADDREF(*_retval = enumerator);
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
+XPTI_GetInterfaceInfoManager()
+{
+ nsIInterfaceInfoManager* iim =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+ NS_IF_ADDREF(iim);
+ return iim;
+}
+
+XPTI_PUBLIC_API(void)
+XPTI_FreeInterfaceInfoManager()
+{
+ xptiInterfaceInfoManager::FreeInterfaceInfoManager();
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp
new file mode 100644
index 00000000..03ab7029
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp
@@ -0,0 +1,710 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiManifest. */
+
+#include "xptiprivate.h"
+#include "nsManifestLineReader.h"
+#include "nsString.h"
+
+static const char g_Disclaimer[] = "# Generated file. ** DO NOT EDIT! **";
+
+static const char g_TOKEN_Files[] = "Files";
+static const char g_TOKEN_ArchiveItems[] = "ArchiveItems";
+static const char g_TOKEN_Interfaces[] = "Interfaces";
+static const char g_TOKEN_Header[] = "Header";
+static const char g_TOKEN_Version[] = "Version";
+static const char g_TOKEN_AppDir[] = "AppDir";
+static const char g_TOKEN_Directories[] = "Directories";
+
+static const int g_VERSION_MAJOR = 2;
+static const int g_VERSION_MINOR = 0;
+
+/***************************************************************************/
+
+static PRBool
+GetCurrentAppDirString(xptiInterfaceInfoManager* aMgr, nsACString &aStr)
+{
+ nsCOMPtr<nsILocalFile> appDir;
+ aMgr->GetApplicationDir(getter_AddRefs(appDir));
+ if(appDir)
+ return NS_SUCCEEDED(appDir->GetPersistentDescriptor(aStr));
+ return PR_FALSE;
+}
+
+static PRBool
+CurrentAppDirMatchesPersistentDescriptor(xptiInterfaceInfoManager* aMgr,
+ const char *inStr)
+{
+ nsCOMPtr<nsILocalFile> appDir;
+ aMgr->GetApplicationDir(getter_AddRefs(appDir));
+
+ nsCOMPtr<nsILocalFile> descDir;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ rv = descDir->SetPersistentDescriptor(nsDependentCString(inStr));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ PRBool matches;
+ rv = appDir->Equals(descDir, &matches);
+ return NS_SUCCEEDED(rv) && matches;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_InterfaceWriter(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ PRFileDesc* fd = (PRFileDesc*) arg;
+
+ char* iidStr = entry->GetTheIID()->ToString();
+ if(!iidStr)
+ return PL_DHASH_STOP;
+
+ const xptiTypelib& typelib = entry->GetTypelibRecord();
+
+ PRBool success = PR_fprintf(fd, "%d,%s,%s,%d,%d,%d\n",
+ (int) number,
+ entry->GetTheName(),
+ iidStr,
+ (int) typelib.GetFileIndex(),
+ (int) (typelib.IsZip() ?
+ typelib.GetZipItemIndex() : -1),
+ (int) entry->GetScriptableFlag());
+
+ nsCRT::free(iidStr);
+
+ return success ? PL_DHASH_NEXT : PL_DHASH_STOP;
+}
+
+
+// static
+PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet)
+{
+
+ PRBool succeeded = PR_FALSE;
+ PRFileDesc* fd = nsnull;
+ PRUint32 i;
+ PRUint32 size32;
+ PRIntn interfaceCount = 0;
+ nsCAutoString appDirString;
+
+ nsCOMPtr<nsILocalFile> tempFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(tempFile)) || !tempFile)
+ return PR_FALSE;
+
+ nsCAutoString originalLeafName;
+ tempFile->GetNativeLeafName(originalLeafName);
+
+ nsCAutoString leafName;
+ leafName.Assign(originalLeafName + NS_LITERAL_CSTRING(".tmp"));
+
+ tempFile->SetNativeLeafName(leafName);
+
+ // All exits via "goto out;" from here on...
+ if(NS_FAILED(tempFile->
+ OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0600, &fd)) || !fd)
+ {
+ goto out;
+ }
+
+ // write file header comments
+
+ if(!PR_fprintf(fd, "%s\n", g_Disclaimer))
+ goto out;
+
+ // write the [Header] block, version number, and appdir.
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n", g_TOKEN_Header, 2))
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s,%d,%d\n",
+ 0, g_TOKEN_Version, g_VERSION_MAJOR, g_VERSION_MINOR))
+ goto out;
+
+ GetCurrentAppDirString(aMgr, appDirString);
+ if(appDirString.IsEmpty())
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s,%s\n",
+ 1, g_TOKEN_AppDir, appDirString.get()))
+ goto out;
+
+ // write Directories list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Directories,
+ (int) aWorkingSet->GetDirectoryCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetDirectoryCount(); i++)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ nsCAutoString str;
+
+ aWorkingSet->GetDirectoryAt(i, getter_AddRefs(dir));
+ if(!dir)
+ goto out;
+
+ dir->GetPersistentDescriptor(str);
+ if(str.IsEmpty())
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s\n", (int) i, str.get()))
+ goto out;
+ }
+
+ // write Files list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Files,
+ (int) aWorkingSet->GetFileCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetFileCount(); i++)
+ {
+ const xptiFile& file = aWorkingSet->GetFileAt(i);
+
+ LL_L2UI(size32, file.GetSize());
+
+ if(!PR_fprintf(fd, "%d,%s,%d,%u,%lld\n",
+ (int) i,
+ file.GetName(),
+ (int) file.GetDirectory(),
+ size32, PRInt64(file.GetDate())))
+ goto out;
+ }
+
+ // write ArchiveItems list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_ArchiveItems,
+ (int) aWorkingSet->GetZipItemCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetZipItemCount(); i++)
+ {
+ if(!PR_fprintf(fd, "%d,%s\n",
+ (int) i,
+ aWorkingSet->GetZipItemAt(i).GetName()))
+ goto out;
+ }
+
+ // write the Interfaces list
+
+ interfaceCount = aWorkingSet->mNameTable->entryCount;
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Interfaces,
+ (int) interfaceCount))
+ goto out;
+
+ if(interfaceCount != (PRIntn)
+ PL_DHashTableEnumerate(aWorkingSet->mNameTable,
+ xpti_InterfaceWriter, fd))
+ goto out;
+
+
+ if(PR_SUCCESS == PR_Close(fd))
+ {
+ succeeded = PR_TRUE;
+ }
+ fd = nsnull;
+
+out:
+ if(fd)
+ PR_Close(fd);
+
+ if(succeeded)
+ {
+ // delete the old file and rename this
+ nsCOMPtr<nsILocalFile> mainFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(mainFile)) || !mainFile)
+ return PR_FALSE;
+
+ PRBool exists;
+ if(NS_FAILED(mainFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(mainFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> parent;
+ mainFile->GetParent(getter_AddRefs(parent));
+
+ // MoveTo means rename.
+ if(NS_FAILED(tempFile->MoveToNative(parent, originalLeafName)))
+ return PR_FALSE;
+ }
+
+ return succeeded;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+
+static char*
+ReadManifestIntoMemory(xptiInterfaceInfoManager* aMgr,
+ PRUint32* pLength)
+{
+ PRFileDesc* fd = nsnull;
+ PRInt32 flen;
+ PRInt64 fileSize;
+ char* whole = nsnull;
+ PRBool success = PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> aFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(aFile)) || !aFile)
+ return nsnull;
+
+#ifdef DEBUG
+ {
+ static PRBool shown = PR_FALSE;
+
+ nsCAutoString path;
+ if(!shown && NS_SUCCEEDED(aFile->GetNativePath(path)) && !path.IsEmpty())
+ {
+ fprintf(stderr, "Type Manifest File: %s\n", path.get());
+ shown = PR_TRUE;
+ }
+ }
+#endif
+
+ if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
+ return nsnull;
+
+ whole = new char[flen];
+ if (!whole)
+ return nsnull;
+
+ // All exits from on here should be via 'goto out'
+
+ if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
+ goto out;
+
+ if(flen > PR_Read(fd, whole, flen))
+ goto out;
+
+ success = PR_TRUE;
+
+ out:
+ if(fd)
+ PR_Close(fd);
+
+ if(!success)
+ {
+ delete [] whole;
+ return nsnull;
+ }
+
+ *pLength = flen;
+ return whole;
+}
+
+static
+PRBool ReadSectionHeader(nsManifestLineReader& reader,
+ const char *token, int minCount, int* count)
+{
+ while(1)
+ {
+ if(!reader.NextLine())
+ break;
+ if(*reader.LinePtr() == '[')
+ {
+ char* p = reader.LinePtr() + (reader.LineLength() - 1);
+ if(*p != ']')
+ break;
+ *p = 0;
+
+ char* values[2];
+ int lengths[2];
+ if(2 != reader.ParseLine(values, lengths, 2))
+ break;
+
+ // ignore the leading '['
+ if(0 != PL_strcmp(values[0]+1, token))
+ break;
+
+ if((*count = atoi(values[1])) < minCount)
+ break;
+
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+
+// static
+PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet)
+{
+ int i;
+ char* whole = nsnull;
+ PRBool succeeded = PR_FALSE;
+ PRUint32 flen = 0;
+ nsManifestLineReader reader;
+ xptiHashEntry* hashEntry;
+ int headerCount = 0;
+ int dirCount = 0;
+ int fileCount = 0;
+ int zipItemCount = -1;
+ int interfaceCount = 0;
+ int dir;
+ int flags;
+ char* values[6]; // 6 is currently the max items we need to parse
+ int lengths[6];
+ PRUint32 size32;
+ PRInt64 size;
+ PRInt64 date;
+
+ whole = ReadManifestIntoMemory(aMgr, &flen);
+ if(!whole)
+ return PR_FALSE;
+
+ reader.Init(whole, flen);
+
+ // All exits from here on should be via 'goto out'
+
+ // Look for "Header" section
+
+ // This version accepts only version 1,0. We also freak if the header
+ // has more than one entry. The rationale is that we want to force an
+ // autoreg if the xpti.dat file was written by *any* other version of
+ // the software. Future versions may wish to support updating older
+ // manifests in some interesting way.
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Header, 2, &headerCount))
+ goto out;
+
+ if(headerCount != 2)
+ goto out;
+
+ // Verify the version number
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,VersionLiteral,major,minor
+ if(4 != reader.ParseLine(values, lengths, 4))
+ goto out;
+
+ // index
+ if(0 != atoi(values[0]))
+ goto out;
+
+ // VersionLiteral
+ if(0 != PL_strcmp(values[1], g_TOKEN_Version))
+ goto out;
+
+ // major
+ if(g_VERSION_MAJOR != atoi(values[2]))
+ goto out;
+
+ // minor
+ if(g_VERSION_MINOR != atoi(values[3]))
+ goto out;
+
+ // Verify the application directory
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,AppDirLiteral,directoryname
+ if(3 != reader.ParseLine(values, lengths, 3))
+ goto out;
+
+ // index
+ if(1 != atoi(values[0]))
+ goto out;
+
+ // AppDirLiteral
+ if(0 != PL_strcmp(values[1], g_TOKEN_AppDir))
+ goto out;
+
+ if(!CurrentAppDirMatchesPersistentDescriptor(aMgr, values[2]))
+ goto out;
+
+ // Look for "Directories" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Directories, 1, &dirCount))
+ goto out;
+ else
+ {
+ // To validate that the directory list matches the current search path
+ // we first confirm that the list lengths match.
+
+ nsCOMPtr<nsISupportsArray> searchPath;
+ aMgr->GetSearchPath(getter_AddRefs(searchPath));
+
+ PRUint32 searchPathCount;
+ searchPath->Count(&searchPathCount);
+
+ if(dirCount != (int) searchPathCount)
+ goto out;
+ }
+
+ // Read the directory records
+
+ for(i = 0; i < dirCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,directoryname
+ if(2 != reader.ParseLine(values, lengths, 2))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // directoryname
+ if(!aWorkingSet->DirectoryAtMatchesPersistentDescriptor(i, values[1]))
+ goto out;
+ }
+
+ // Look for "Files" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Files, 1, &fileCount))
+ goto out;
+
+
+ // Alloc room in the WorkingSet for the filearray.
+
+ if(!aWorkingSet->NewFileArray(fileCount))
+ goto out;
+
+ // Read the file records
+
+ for(i = 0; i < fileCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,filename,dirIndex,dilesSize,filesDate
+ if(5 != reader.ParseLine(values, lengths, 5))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // filename
+ if(!*values[1])
+ goto out;
+
+ // dirIndex
+ dir = atoi(values[2]);
+ if(dir < 0 || dir > dirCount)
+ goto out;
+
+ // fileSize
+ size32 = atoi(values[3]);
+ if(size32 <= 0)
+ goto out;
+ LL_UI2L(size, size32);
+
+ // fileDate
+ date = nsCRT::atoll(values[4]);
+ if(LL_IS_ZERO(date))
+ goto out;
+
+ // Append a new file record to the array.
+
+ aWorkingSet->AppendFile(
+ xptiFile(nsInt64(size), nsInt64(date), dir, values[1], aWorkingSet));
+ }
+
+ // Look for "ZipItems" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_ArchiveItems, 0, &zipItemCount))
+ goto out;
+
+ // Alloc room in the WorkingSet for the zipItemarray.
+
+ if(zipItemCount)
+ if(!aWorkingSet->NewZipItemArray(zipItemCount))
+ goto out;
+
+ // Read the zipItem records
+
+ for(i = 0; i < zipItemCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,filename
+ if(2 != reader.ParseLine(values, lengths, 2))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // filename
+ if(!*values[1])
+ goto out;
+
+ // Append a new zipItem record to the array.
+
+ aWorkingSet->AppendZipItem(xptiZipItem(values[1], aWorkingSet));
+ }
+
+ // Look for "Interfaces" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Interfaces, 1, &interfaceCount))
+ goto out;
+
+ // Read the interface records
+
+ for(i = 0; i < interfaceCount; ++i)
+ {
+ int fileIndex;
+ int zipItemIndex;
+ nsIID iid;
+ xptiInterfaceEntry* entry;
+ xptiTypelib typelibRecord;
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,interfaceName,iid,fileIndex,zipIndex,flags
+ if(6 != reader.ParseLine(values, lengths, 6))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // interfaceName
+ if(!*values[1])
+ goto out;
+
+ // iid
+ if(!iid.Parse(values[2]))
+ goto out;
+
+ // fileIndex
+ fileIndex = atoi(values[3]);
+ if(fileIndex < 0 || fileIndex >= fileCount)
+ goto out;
+
+ // zipIndex (NOTE: -1 is a valid value)
+ zipItemIndex = atoi(values[4]);
+ if(zipItemIndex < -1 || zipItemIndex >= zipItemCount)
+ goto out;
+
+ // flags
+ flags = atoi(values[5]);
+ if(flags != 0 && flags != 1)
+ goto out;
+
+ // Build an InterfaceInfo and hook it in.
+
+ if(zipItemIndex == -1)
+ typelibRecord.Init(fileIndex);
+ else
+ typelibRecord.Init(fileIndex, zipItemIndex);
+
+ entry = xptiInterfaceEntry::NewEntry(values[1], lengths[1],
+ iid, typelibRecord,
+ aWorkingSet);
+ if(!entry)
+ goto out;
+
+ entry->SetScriptableFlag(flags==1);
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ entry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ entry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+ }
+
+ // success!
+
+ succeeded = PR_TRUE;
+
+ out:
+ if(whole)
+ delete [] whole;
+
+ if(!succeeded)
+ {
+ // Cleanup the WorkingSet on failure.
+ aWorkingSet->InvalidateInterfaceInfos();
+ aWorkingSet->ClearHashTables();
+ aWorkingSet->ClearFiles();
+ }
+ return succeeded;
+}
+
+// static
+PRBool xptiManifest::Delete(xptiInterfaceInfoManager* aMgr)
+{
+ nsCOMPtr<nsILocalFile> aFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(aFile)) || !aFile)
+ return PR_FALSE;
+
+ PRBool exists;
+ if(NS_FAILED(aFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(aFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp
new file mode 100644
index 00000000..a1dbf5c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of misc. xpti stuff. */
+
+#include "xptiprivate.h"
+
+struct xptiFileTypeEntry
+{
+ const char* name;
+ int len;
+ xptiFileType::Type type;
+};
+
+static const xptiFileTypeEntry g_Entries[] =
+ {
+ {".xpt", 4, xptiFileType::XPT},
+ {".zip", 4, xptiFileType::ZIP},
+ {".jar", 4, xptiFileType::ZIP},
+ {nsnull, 0, xptiFileType::UNKNOWN}
+ };
+
+// static
+xptiFileType::Type xptiFileType::GetType(const char* name)
+{
+ NS_ASSERTION(name, "loser!");
+ int len = PL_strlen(name);
+ for(const xptiFileTypeEntry* p = g_Entries; p->name; p++)
+ {
+ if(len > p->len && 0 == PL_strcasecmp(p->name, &(name[len - p->len])))
+ return p->type;
+ }
+ return UNKNOWN;
+}
+
+/***************************************************************************/
+
+MOZ_DECL_CTOR_COUNTER(xptiAutoLog)
+
+xptiAutoLog::xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append)
+ : mMgr(nsnull), mOldFileDesc(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiAutoLog);
+
+ if(mgr && logfile)
+ {
+ PRFileDesc* fd;
+ if(NS_SUCCEEDED(logfile->
+ OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_APPEND |
+ (append ? 0 : PR_TRUNCATE),
+ 0600, &fd)) && fd)
+ {
+#ifdef DEBUG
+ m_DEBUG_FileDesc = fd;
+#endif
+ mMgr = mgr;
+ mOldFileDesc = mMgr->SetOpenLogFile(fd);
+ if(append)
+ PR_Seek(fd, 0, PR_SEEK_END);
+ WriteTimestamp(fd, "++++ start logging ");
+
+ }
+ else
+ {
+#ifdef DEBUG
+ printf("xpti failed to open log file for writing\n");
+#endif
+ }
+ }
+}
+
+xptiAutoLog::~xptiAutoLog()
+{
+ MOZ_COUNT_DTOR(xptiAutoLog);
+
+ if(mMgr)
+ {
+ PRFileDesc* fd = mMgr->SetOpenLogFile(mOldFileDesc);
+ NS_ASSERTION(fd == m_DEBUG_FileDesc, "bad unravel");
+ if(fd)
+ {
+ WriteTimestamp(fd, "---- end logging ");
+ PR_Close(fd);
+ }
+ }
+}
+
+void xptiAutoLog::WriteTimestamp(PRFileDesc* fd, const char* msg)
+{
+ PRExplodedTime expTime;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &expTime);
+ char time[128];
+ PR_FormatTimeUSEnglish(time, 128, "%Y-%m-%d-%H:%M:%S", &expTime);
+ PR_fprintf(fd, "\n%s %s\n\n", msg, time);
+}
+
+/***************************************************************************/
+
+nsresult
+xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> cloneRaw;
+
+ rv = aLocalFile->Clone(getter_AddRefs(cloneRaw));
+ if(NS_FAILED(rv))
+ return rv;
+
+ return CallQueryInterface(cloneRaw, aCloneLocalFile);
+}
+
+
+nsresult
+xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> original;
+
+ rv = aArray->QueryElementAt(aIndex, NS_GET_IID(nsILocalFile),
+ getter_AddRefs(original));
+ if(NS_FAILED(rv))
+ return rv;
+
+ return xptiCloneLocalFile(original, aLocalFile);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp
new file mode 100644
index 00000000..50956585
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiTypelibGuts. */
+
+#include "xptiprivate.h"
+
+// static
+xptiTypelibGuts*
+xptiTypelibGuts::NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aHeader, "bad param");
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiTypelibGuts) +
+ (sizeof(xptiInterfaceEntry*) *
+ (aHeader->num_interfaces - 1)));
+ if(!place)
+ return nsnull;
+ return new(place) xptiTypelibGuts(aHeader);
+}
+
+xptiTypelibGuts::xptiTypelibGuts(XPTHeader* aHeader)
+ : mHeader(aHeader)
+{
+ // empty
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp
new file mode 100644
index 00000000..b9602726
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp
@@ -0,0 +1,432 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiWorkingSet. */
+
+#include "xptiprivate.h"
+#include "nsString.h"
+
+#define XPTI_STRING_ARENA_BLOCK_SIZE (1024 * 1)
+#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1)
+#define XPTI_HASHTABLE_SIZE 128
+
+/***************************************************************************/
+
+PR_STATIC_CALLBACK(const void*)
+IIDGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ return ((xptiHashEntry*)entry)->value->GetTheIID();
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+IIDHash(PLDHashTable *table, const void *key)
+{
+ return (PLDHashNumber) ((const nsIID*)key)->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+IIDMatch(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const nsIID* iid1 = ((xptiHashEntry*)entry)->value->GetTheIID();
+ const nsIID* iid2 = (const nsIID*)key;
+
+ return iid1 == iid2 || iid1->Equals(*iid2);
+}
+
+const static struct PLDHashTableOps IIDTableOps =
+{
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ IIDGetKey,
+ IIDHash,
+ IIDMatch,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub
+};
+
+/***************************************************************************/
+
+PR_STATIC_CALLBACK(const void*)
+NameGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ return ((xptiHashEntry*)entry)->value->GetTheName();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+NameMatch(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const char* str1 = ((xptiHashEntry*)entry)->value->GetTheName();
+ const char* str2 = (const char*) key;
+ return str1 == str2 || 0 == PL_strcmp(str1, str2);
+}
+
+static const struct PLDHashTableOps NameTableOps =
+{
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ NameGetKey,
+ PL_DHashStringKey,
+ NameMatch,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub
+};
+
+/***************************************************************************/
+
+MOZ_DECL_CTOR_COUNTER(xptiWorkingSet)
+
+xptiWorkingSet::xptiWorkingSet(nsISupportsArray* aDirectories)
+ : mFileCount(0),
+ mMaxFileCount(0),
+ mFileArray(nsnull),
+ mZipItemCount(0),
+ mMaxZipItemCount(0),
+ mZipItemArray(nsnull),
+ mStringArena(XPT_NewArena(XPTI_STRING_ARENA_BLOCK_SIZE, sizeof(char),
+ "xptiWorkingSet strings")),
+ mStructArena(XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double),
+ "xptiWorkingSet structs")),
+ mDirectories(aDirectories),
+ mNameTable(PL_NewDHashTable(&NameTableOps, nsnull, sizeof(xptiHashEntry),
+ XPTI_HASHTABLE_SIZE)),
+ mIIDTable(PL_NewDHashTable(&IIDTableOps, nsnull, sizeof(xptiHashEntry),
+ XPTI_HASHTABLE_SIZE)),
+ mFileMergeOffsetMap(nsnull),
+ mZipItemMergeOffsetMap(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiWorkingSet);
+ // do nothing else...
+}
+
+PRBool
+xptiWorkingSet::IsValid() const
+{
+ return (mFileCount == 0 || mFileArray) &&
+ (mZipItemCount == 0 || mZipItemArray) &&
+ mStringArena &&
+ mStructArena &&
+ mNameTable &&
+ mIIDTable;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Remover(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ return PL_DHASH_REMOVE;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Invalidator(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ entry->LockedInvalidateInterfaceInfo();
+ return PL_DHASH_NEXT;
+}
+
+void
+xptiWorkingSet::InvalidateInterfaceInfos()
+{
+ if(mNameTable)
+ {
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ PL_DHashTableEnumerate(mNameTable, xpti_Invalidator, nsnull);
+ }
+}
+
+void
+xptiWorkingSet::ClearHashTables()
+{
+ if(mNameTable)
+ PL_DHashTableEnumerate(mNameTable, xpti_Remover, nsnull);
+
+ if(mIIDTable)
+ PL_DHashTableEnumerate(mIIDTable, xpti_Remover, nsnull);
+}
+
+void
+xptiWorkingSet::ClearFiles()
+{
+ if(mFileArray)
+ delete [] mFileArray;
+ mFileArray = nsnull;
+ mMaxFileCount = 0;
+ mFileCount = 0;
+}
+
+void
+xptiWorkingSet::ClearZipItems()
+{
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+ mZipItemArray = nsnull;
+ mMaxZipItemCount = 0;
+ mZipItemCount = 0;
+}
+
+xptiWorkingSet::~xptiWorkingSet()
+{
+ MOZ_COUNT_DTOR(xptiWorkingSet);
+
+ ClearFiles();
+ ClearZipItems();
+ ClearHashTables();
+
+ if(mNameTable)
+ PL_DHashTableDestroy(mNameTable);
+
+ if(mIIDTable)
+ PL_DHashTableDestroy(mIIDTable);
+
+ if(mFileArray)
+ delete [] mFileArray;
+
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+
+ // Destroy arenas last in case they are referenced in other members' dtors.
+
+ if(mStringArena)
+ {
+#ifdef DEBUG
+ XPT_DumpStats(mStringArena);
+#endif
+ XPT_DestroyArena(mStringArena);
+ }
+
+ if(mStructArena)
+ {
+#ifdef DEBUG
+ XPT_DumpStats(mStructArena);
+#endif
+ XPT_DestroyArena(mStructArena);
+ }
+}
+
+PRUint32
+xptiWorkingSet::FindFile(PRUint32 dir, const char* name)
+{
+ if(mFileArray)
+ {
+ for(PRUint32 i = 0; i < mFileCount;++i)
+ {
+ xptiFile& file = mFileArray[i];
+ if(file.GetDirectory() == dir &&
+ 0 == PL_strcmp(name, file.GetName()))
+ {
+ return i;
+ }
+ }
+ }
+ return NOT_FOUND;
+}
+
+PRBool
+xptiWorkingSet::NewFileArray(PRUint32 count)
+{
+ if(mFileArray)
+ delete [] mFileArray;
+ mFileCount = 0;
+ mFileArray = new xptiFile[count];
+ if(!mFileArray)
+ {
+ mMaxFileCount = 0;
+ return PR_FALSE;
+ }
+ mMaxFileCount = count;
+ return PR_TRUE;
+}
+
+PRBool
+xptiWorkingSet::ExtendFileArray(PRUint32 count)
+{
+ if(mFileArray && count < mMaxFileCount)
+ return PR_TRUE;
+
+ xptiFile* newArray = new xptiFile[count];
+ if(!newArray)
+ return PR_FALSE;
+
+ if(mFileArray)
+ {
+ for(PRUint32 i = 0; i < mFileCount; ++i)
+ newArray[i] = mFileArray[i];
+ delete [] mFileArray;
+ }
+ mFileArray = newArray;
+ mMaxFileCount = count;
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+
+PRUint32
+xptiWorkingSet::FindZipItemWithName(const char* name)
+{
+ if(mZipItemArray)
+ {
+ for(PRUint32 i = 0; i < mZipItemCount;++i)
+ if(0 == PL_strcmp(name, mZipItemArray[i].GetName()))
+ return i;
+ }
+ return NOT_FOUND;
+}
+
+PRBool
+xptiWorkingSet::NewZipItemArray(PRUint32 count)
+{
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+ mZipItemCount = 0;
+ mZipItemArray = new xptiZipItem[count];
+ if(!mZipItemArray)
+ {
+ mMaxZipItemCount = 0;
+ return PR_FALSE;
+ }
+ mMaxZipItemCount = count;
+ return PR_TRUE;
+}
+
+PRBool
+xptiWorkingSet::ExtendZipItemArray(PRUint32 count)
+{
+ if(mZipItemArray && count < mMaxZipItemCount)
+ return PR_TRUE;
+
+ xptiZipItem* newArray = new xptiZipItem[count];
+ if(!newArray)
+ return PR_FALSE;
+
+ if(mZipItemArray)
+ {
+ for(PRUint32 i = 0; i < mZipItemCount; ++i)
+ newArray[i] = mZipItemArray[i];
+ delete [] mZipItemArray;
+ }
+ mZipItemArray = newArray;
+ mMaxZipItemCount = count;
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+// Directory stuff...
+
+PRUint32 xptiWorkingSet::GetDirectoryCount()
+{
+ PRUint32 count = 0;
+ mDirectories->Count(&count);
+ return count;
+}
+
+nsresult xptiWorkingSet::GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir)
+{
+ return xptiCloneElementAsLocalFile(mDirectories, i, dir);
+}
+
+nsresult xptiWorkingSet::GetDirectoryAt(PRUint32 i, nsILocalFile** dir)
+{
+ return mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile), (void**)dir);
+}
+
+PRBool xptiWorkingSet::FindDirectory(nsILocalFile* dir, PRUint32* index)
+{
+ PRUint32 count;
+ nsresult rv = mDirectories->Count(&count);
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ PRBool same;
+ nsCOMPtr<nsILocalFile> current;
+ mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile),
+ getter_AddRefs(current));
+ if(!current || NS_FAILED(current->Equals(dir, &same)))
+ break;
+ if(same)
+ {
+ *index = i;
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool xptiWorkingSet::FindDirectoryOfFile(nsILocalFile* file, PRUint32* index)
+{
+ nsCOMPtr<nsIFile> dirAbstract;
+ file->GetParent(getter_AddRefs(dirAbstract));
+ if(!dirAbstract)
+ return PR_FALSE;
+ nsCOMPtr<nsILocalFile> dir = do_QueryInterface(dirAbstract);
+ if(!dir)
+ return PR_FALSE;
+ return FindDirectory(dir, index);
+}
+
+PRBool xptiWorkingSet::DirectoryAtMatchesPersistentDescriptor(PRUint32 i,
+ const char* inDesc)
+{
+ nsCOMPtr<nsILocalFile> dir;
+ GetDirectoryAt(i, getter_AddRefs(dir));
+ if(!dir)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> descDir;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ rv = descDir->SetPersistentDescriptor(nsDependentCString(inDesc));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ PRBool matches;
+ rv = dir->Equals(descDir, &matches);
+ return NS_SUCCEEDED(rv) && matches;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp
new file mode 100644
index 00000000..c9a6178b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiZipItem. */
+
+#include "xptiprivate.h"
+
+MOZ_DECL_CTOR_COUNTER(xptiZipItem)
+
+xptiZipItem::xptiZipItem()
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(nsnull),
+#endif
+ mName(nsnull),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+ // empty
+}
+
+xptiZipItem::xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet)
+
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mName(aName),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
+}
+
+xptiZipItem::xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mName(nsnull),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
+}
+
+xptiZipItem::~xptiZipItem()
+{
+ MOZ_COUNT_DTOR(xptiZipItem);
+}
+
+PRBool
+xptiZipItem::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(!mGuts,"bad state");
+ NS_ASSERTION(aHeader,"bad param");
+ NS_ASSERTION(aWorkingSet,"bad param");
+
+ mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
+ return mGuts != nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
new file mode 100644
index 00000000..caba49d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiZipLoader. */
+
+#include "xptiprivate.h"
+
+XPTHeader*
+xptiZipLoader::ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet)
+{
+ XPTCursor cursor;
+ PRUint32 totalRead = 0;
+ XPTState *state = nsnull;
+ XPTHeader *header = nsnull;
+
+ PRUint32 flen;
+ stream->Available(&flen);
+
+ char *whole = new char[flen];
+ if (!whole)
+ {
+ return nsnull;
+ }
+
+ // all exits from on here should be via 'goto out'
+
+ while(flen - totalRead)
+ {
+ PRUint32 avail;
+ PRUint32 read;
+
+ if(NS_FAILED(stream->Available(&avail)))
+ {
+ goto out;
+ }
+
+ if(avail > flen)
+ {
+ goto out;
+ }
+
+ if(NS_FAILED(stream->Read(whole+totalRead, avail, &read)))
+ {
+ goto out;
+ }
+
+ totalRead += read;
+ }
+
+ // Go ahead and close the stream now.
+ stream = nsnull;
+
+ if(!(state = XPT_NewXDRState(XPT_DECODE, whole, flen)))
+ {
+ goto out;
+ }
+
+ if(!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor))
+ {
+ goto out;
+ }
+
+ if (!XPT_DoHeader(aWorkingSet->GetStructArena(), &cursor, &header))
+ {
+ header = nsnull;
+ goto out;
+ }
+
+ out:
+ if(state)
+ XPT_DestroyXDRState(state);
+ if(whole)
+ delete [] whole;
+ return header;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
new file mode 100644
index 00000000..3d159c2c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
@@ -0,0 +1,981 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Library-private header for Interface Info system. */
+
+#ifndef xptiprivate_h___
+#define xptiprivate_h___
+
+#include "nscore.h"
+#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 "nsIXPTLoader.h"
+
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIWeakReference.h"
+
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsISupportsArray.h"
+#include "nsSupportsArray.h"
+#include "nsInt64.h"
+
+#include "nsQuickSort.h"
+
+#include "nsXPIDLString.h"
+
+#include "nsIInputStream.h"
+
+#include "nsAutoLock.h"
+
+#include "pldhash.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) xptiInterfaceInfoManager::WriteToLog x
+#endif
+
+#if 1 && defined(DEBUG_jband)
+#define SHOW_INFO_COUNT_STATS
+#endif
+
+/***************************************************************************/
+
+class xptiFile;
+class xptiInterfaceInfo;
+class xptiInterfaceInfoManager;
+class xptiInterfaceEntry;
+class xptiInterfaceGuts;
+class xptiTypelibGuts;
+class xptiWorkingSet;
+
+/***************************************************************************/
+
+class xptiTypelib
+{
+public:
+ // No ctors or dtors so that we can be in a union in xptiInterfaceInfo.
+ // Allow automatic shallow copies.
+
+ uint16 GetFileIndex() const {return mFileIndex;}
+ uint16 GetZipItemIndex() const {return mZipItemIndex;}
+
+ enum {NOT_ZIP = 0xffff};
+
+ PRBool IsZip() const {return mZipItemIndex != NOT_ZIP;}
+
+ void Init(uint16 aFileIndex, uint16 aZipItemIndex = NOT_ZIP)
+ {mFileIndex = aFileIndex; mZipItemIndex = aZipItemIndex;}
+
+ PRBool Equals(const xptiTypelib& r) const
+ {return mFileIndex == r.mFileIndex &&
+ mZipItemIndex == r.mZipItemIndex;}
+
+private:
+ uint16 mFileIndex;
+ uint16 mZipItemIndex;
+};
+
+/***************************************************************************/
+
+// No virtuals.
+// These are always constructed in the struct arena using placement new.
+// dtor need not be called.
+
+class xptiTypelibGuts
+{
+public:
+ static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* GetHeader() {return mHeader;}
+ PRUint16 GetEntryCount() const {return mHeader->num_interfaces;}
+
+ void SetEntryAt(PRUint16 i, xptiInterfaceEntry* ptr)
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ mEntryArray[i] = ptr;
+ }
+
+ xptiInterfaceEntry* GetEntryAt(PRUint16 i) const
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ return mEntryArray[i];
+ }
+
+private:
+ xptiTypelibGuts(); // not implemented
+ xptiTypelibGuts(XPTHeader* aHeader);
+ ~xptiTypelibGuts() {}
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+private:
+ XPTHeader* mHeader; // hold pointer into arena
+ xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
+};
+
+/***************************************************************************/
+
+class xptiFile
+{
+public:
+ const nsInt64& GetSize() const {return mSize;}
+ const nsInt64& GetDate() const {return mDate;}
+ const char* GetName() const {return mName;}
+ /*const*/ PRUint32 GetDirectory() const {return mDirectory;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiFile();
+
+ xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiFile();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiFile& r) const
+ {
+ return mDirectory == r.mDirectory &&
+ mSize == r.mSize &&
+ mDate == r.mDate &&
+ 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiFile(const xptiFile& r) {CopyFields(r);}
+ xptiFile& operator= (const xptiFile& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+private:
+ void CopyFields(const xptiFile& r)
+ {
+#ifdef DEBUG
+ // If 'this' has a workingset then it better match that of the assigner.
+ NS_ASSERTION(!mDEBUG_WorkingSet ||
+ mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
+ "illegal xptiFile assignment");
+ mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
+#endif
+
+ mSize = r.mSize;
+ mDate = r.mDate;
+ mName = r.mName;
+ mDirectory = r.mDirectory;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ nsInt64 mSize;
+ nsInt64 mDate;
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+ PRUint32 mDirectory;
+};
+
+/***************************************************************************/
+
+class xptiZipItem
+{
+public:
+ const char* GetName() const {return mName;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiZipItem();
+
+ xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiZipItem();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiZipItem& r) const
+ {
+ return 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiZipItem(const xptiZipItem& r) {CopyFields(r);}
+ xptiZipItem& operator= (const xptiZipItem& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+private:
+ void CopyFields(const xptiZipItem& r)
+ {
+#ifdef DEBUG
+ // If 'this' has a workingset then it better match that of the assigner.
+ NS_ASSERTION(!mDEBUG_WorkingSet ||
+ mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
+ "illegal xptiFile assignment");
+ mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
+#endif
+
+ mName = r.mName;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+};
+
+/***************************************************************************/
+
+class xptiWorkingSet
+{
+public:
+ xptiWorkingSet(); // not implmented
+ xptiWorkingSet(nsISupportsArray* aDirectories);
+ ~xptiWorkingSet();
+
+ PRBool IsValid() const;
+
+ void InvalidateInterfaceInfos();
+ void ClearHashTables();
+ void ClearFiles();
+ void ClearZipItems();
+
+ // utility methods...
+
+ xptiTypelibGuts* GetTypelibGuts(const xptiTypelib& typelib)
+ {
+ return typelib.IsZip() ?
+ GetZipItemAt(typelib.GetZipItemIndex()).GetGuts() :
+ GetFileAt(typelib.GetFileIndex()).GetGuts();
+ }
+
+ enum {NOT_FOUND = 0xffffffff};
+
+ // FileArray stuff...
+
+ PRUint32 GetFileCount() const {return mFileCount;}
+ PRUint32 GetFileFreeSpace()
+ {return mFileArray ? mMaxFileCount - mFileCount : 0;}
+
+ PRUint32 FindFile(PRUint32 dir, const char* name);
+
+ PRUint32 GetTypelibDirectoryIndex(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetDirectory();
+ }
+
+ const char* GetTypelibFileName(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetName();
+ }
+
+ xptiFile& GetFileAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ return mFileArray[i];
+ }
+
+ void SetFileAt(PRUint32 i, const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ mFileArray[i] = r;
+ }
+
+ void AppendFile(const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(mFileCount < mMaxFileCount, "bad param!");
+ mFileArray[mFileCount++] = r;
+ }
+
+ PRBool NewFileArray(PRUint32 count);
+ PRBool ExtendFileArray(PRUint32 count);
+
+ // ZipItemArray stuff...
+
+ PRUint32 GetZipItemCount() const {return mZipItemCount;}
+ PRUint32 GetZipItemFreeSpace()
+ {return mZipItemArray ? mMaxZipItemCount - mZipItemCount : 0;}
+
+ PRUint32 FindZipItemWithName(const char* name);
+
+ xptiZipItem& GetZipItemAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ return mZipItemArray[i];
+ }
+
+ void SetZipItemAt(PRUint32 i, const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ mZipItemArray[i] = r;
+ }
+
+ void AppendZipItem(const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(mZipItemCount < mMaxZipItemCount, "bad param!");
+ mZipItemArray[mZipItemCount++] = r;
+ }
+
+ PRBool NewZipItemArray(PRUint32 count);
+ PRBool ExtendZipItemArray(PRUint32 count);
+
+ // Directory stuff...
+
+ PRUint32 GetDirectoryCount();
+ nsresult GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ nsresult GetDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ PRBool FindDirectory(nsILocalFile* dir, PRUint32* index);
+ PRBool FindDirectoryOfFile(nsILocalFile* file, PRUint32* index);
+ PRBool DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc);
+
+ // Arena stuff...
+
+ XPTArena* GetStringArena() {return mStringArena;}
+ XPTArena* GetStructArena() {return mStructArena;}
+
+
+private:
+ PRUint32 mFileCount;
+ PRUint32 mMaxFileCount;
+ xptiFile* mFileArray; // using new[] and delete[]
+
+ PRUint32 mZipItemCount;
+ PRUint32 mMaxZipItemCount;
+ xptiZipItem* mZipItemArray; // using new[] and delete[]
+
+ XPTArena* mStringArena;
+ XPTArena* mStructArena;
+
+ nsCOMPtr<nsISupportsArray> mDirectories;
+
+public:
+ // XXX make these private with accessors
+ PLDHashTable* mNameTable;
+ PLDHashTable* mIIDTable;
+ PRUint32* mFileMergeOffsetMap; // always in an arena
+ PRUint32* mZipItemMergeOffsetMap; // always in an arena
+};
+
+/***************************************************************************/
+
+class xptiInterfaceGuts
+{
+public:
+ uint16 mMethodBaseIndex;
+ uint16 mConstantBaseIndex;
+ xptiInterfaceEntry* mParent;
+ XPTInterfaceDescriptor* mDescriptor;
+ xptiTypelib mTypelib;
+ xptiWorkingSet* mWorkingSet;
+
+ static xptiInterfaceGuts* NewGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ {
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceGuts));
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceGuts(aDescriptor, aTypelib, aWorkingSet);
+ }
+
+private:
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+ xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ : mMethodBaseIndex(0),
+ mConstantBaseIndex(0),
+ mParent(nsnull),
+ mDescriptor(aDescriptor),
+ mTypelib(aTypelib),
+ mWorkingSet(aWorkingSet) {}
+
+ ~xptiInterfaceGuts() {}
+};
+
+/***************************************************************************/
+
+// 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:
+ xptiInfoFlags(uint8 n) : mData(n) {}
+ xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
+
+ static uint8 GetStateMask()
+ {return uint8(STATE_MASK);}
+
+ void Clear()
+ {mData = 0;}
+
+ uint8 GetData() const
+ {return mData;}
+
+ uint8 GetState() const
+ {return mData & GetStateMask();}
+
+ void SetState(uint8 state)
+ {mData &= ~GetStateMask(); mData |= state;}
+
+ void SetFlagBit(uint8 flag, PRBool on)
+ {if(on)
+ mData |= ~GetStateMask() & flag;
+ else
+ mData &= GetStateMask() | ~flag;}
+
+ PRBool GetFlagBit(uint8 flag) const
+ {return (mData & flag) ? PR_TRUE : PR_FALSE;}
+
+private:
+ uint8 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* NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ enum {
+ NOT_RESOLVED = 0,
+ PARTIALLY_RESOLVED = 1,
+ FULLY_RESOLVED = 2,
+ RESOLVE_FAILED = 3
+ };
+
+ // Additional bit flags...
+ enum {SCRIPTABLE = 4};
+
+ uint8 GetResolveState() const {return mFlags.GetState();}
+
+ PRBool IsFullyResolved() const
+ {return GetResolveState() == (uint8) FULLY_RESOLVED;}
+
+ PRBool HasInterfaceRecord() const
+ {int s = (int) GetResolveState();
+ return (s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface;}
+
+ const xptiTypelib& GetTypelibRecord() const
+ {return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
+
+ xptiInterfaceGuts* GetInterfaceGuts() const
+ {return HasInterfaceRecord() ? mInterface : nsnull;}
+
+#ifdef DEBUG
+ PRBool DEBUG_ScriptableFlagIsValid() const
+ {int s = (int) GetResolveState();
+ if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
+ {
+ if(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags))
+ return GetScriptableFlag();
+ return !GetScriptableFlag();
+ }
+ return PR_TRUE;
+ }
+#endif
+
+ void SetScriptableFlag(PRBool on)
+ {mFlags.SetFlagBit(uint8(SCRIPTABLE),on);}
+ PRBool GetScriptableFlag() const
+ {return mFlags.GetFlagBit(uint8(SCRIPTABLE));}
+
+ const nsID* GetTheIID() const {return &mIID;}
+ const char* GetTheName() const {return mName;}
+
+ PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
+ {return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
+
+ PRBool PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
+ xptiWorkingSet* aWorkingSet);
+
+ nsresult GetInterfaceInfo(xptiInterfaceInfo** info);
+ PRBool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
+ {return info == mInfo;}
+
+ void LockedInvalidateInterfaceInfo();
+ void LockedInterfaceInfoDeathNotification() {mInfo = nsnull;}
+
+ //////////////////////
+ // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+ nsresult GetName(char * *aName);
+ nsresult GetIID(nsIID * *aIID);
+ nsresult IsScriptable(PRBool *_retval);
+ // Except this one.
+ //nsresult GetParent(nsIInterfaceInfo * *aParent);
+ nsresult GetMethodCount(PRUint16 *aMethodCount);
+ nsresult GetConstantCount(PRUint16 *aConstantCount);
+ nsresult GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info);
+ nsresult GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info);
+ nsresult GetConstant(PRUint16 index, const nsXPTConstant * *constant);
+ nsresult GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
+ nsresult GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
+ nsresult GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval);
+ nsresult GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
+ nsresult GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
+ nsresult GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
+ nsresult IsIID(const nsIID * IID, PRBool *_retval);
+ nsresult GetNameShared(const char **name);
+ nsresult GetIIDShared(const nsIID * *iid);
+ nsresult IsFunction(PRBool *_retval);
+ nsresult HasAncestor(const nsIID * iid, PRBool *_retval);
+ nsresult GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid);
+
+ //////////////////////
+
+private:
+ xptiInterfaceEntry(); // not implemented
+
+ xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib);
+
+ xptiInterfaceEntry(const xptiInterfaceEntry& r,
+ size_t nameLength,
+ const xptiTypelib& typelib);
+ ~xptiInterfaceEntry();
+
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+ void SetResolvedState(int state)
+ {mFlags.SetState(uint8(state));}
+
+ PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
+
+ // 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.
+
+ PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
+ {return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
+ PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
+
+ // private helpers
+
+ nsresult GetEntryForParam(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry);
+
+ nsresult GetTypeInArray(const nsXPTParamInfo* param,
+ uint16 dimension,
+ const XPTTypeDescriptor** type);
+
+private:
+ nsID mIID;
+ union {
+ xptiTypelib mTypelib; // Valid only until resolved.
+ xptiInterfaceGuts* mInterface; // Valid only after resolved.
+ };
+ xptiInterfaceInfo* mInfo; // May come and go.
+ xptiInfoFlags mFlags;
+ char mName[1]; // Always last. Sized to fit.
+};
+
+struct xptiHashEntry : public PLDHashEntryHdr
+{
+ xptiInterfaceEntry* value;
+};
+
+/****************************************************/
+
+class xptiInterfaceInfo : public nsIInterfaceInfo
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // Use delegation to implement (most!) of nsIInterfaceInfo.
+ NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
+ NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
+ NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
+ // Except this one.
+ NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent)
+ {
+ if(!EnsureResolved() || !EnsureParent())
+ return NS_ERROR_UNEXPECTED;
+ NS_IF_ADDREF(*aParent = mParent);
+ return NS_OK;
+ }
+ NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
+ NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
+ NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
+ NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); }
+ NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetLengthIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
+ NS_IMETHOD IsIID(const nsIID * IID, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
+ NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
+ NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
+ NS_IMETHOD IsFunction(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
+ NS_IMETHOD HasAncestor(const nsIID * iid, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
+ NS_IMETHOD GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
+
+public:
+ xptiInterfaceInfo(xptiInterfaceEntry* entry);
+
+ void Invalidate()
+ {NS_IF_RELEASE(mParent); mEntry = nsnull;}
+
+#ifdef DEBUG
+ static void DEBUG_ShutdownNotification();
+#endif
+
+private:
+
+ ~xptiInterfaceInfo();
+
+ // Note that mParent might still end up as nsnull if we don't have one.
+ PRBool EnsureParent(xptiWorkingSet* aWorkingSet = nsnull)
+ {
+ NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
+ return mParent || !mEntry->GetInterfaceGuts()->mParent || BuildParent();
+ }
+
+ PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
+ {
+ return mEntry && mEntry->EnsureResolved(aWorkingSet);
+ }
+
+ PRBool BuildParent()
+ {
+ NS_ASSERTION(mEntry &&
+ mEntry->IsFullyResolved() &&
+ !mParent &&
+ mEntry->GetInterfaceGuts()->mParent,
+ "bad BuildParent call");
+ return NS_SUCCEEDED(mEntry->GetInterfaceGuts()->mParent->
+ GetInterfaceInfo(&mParent));
+ }
+
+ xptiInterfaceInfo(); // not implemented
+
+private:
+ xptiInterfaceEntry* mEntry;
+ xptiInterfaceInfo* mParent;
+};
+
+/***************************************************************************/
+
+class xptiManifest
+{
+public:
+ static PRBool Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Delete(xptiInterfaceInfoManager* aMgr);
+
+private:
+ xptiManifest(); // no implementation
+};
+
+/***************************************************************************/
+
+class xptiZipLoaderSink : public nsIXPTLoaderSink
+{
+public:
+ xptiZipLoaderSink(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet) :
+ mManager(aMgr),
+ mWorkingSet(aWorkingSet) {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIXPTLOADERSINK
+
+private:
+ ~xptiZipLoaderSink() {}
+
+ xptiInterfaceInfoManager* mManager;
+ xptiWorkingSet* mWorkingSet;
+
+};
+
+class xptiZipLoader
+{
+public:
+ xptiZipLoader(); // not implemented
+
+ static XPTHeader*
+ ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet);
+
+};
+
+
+/***************************************************************************/
+
+class xptiFileType
+{
+public:
+ enum Type {UNKNOWN = -1, XPT = 0, ZIP = 1 };
+
+ static Type GetType(const char* name);
+
+ static PRBool IsUnknown(const char* name)
+ {return GetType(name) == UNKNOWN;}
+
+ static PRBool IsXPT(const char* name)
+ {return GetType(name) == XPT;}
+
+ static PRBool IsZip(const char* name)
+ {return GetType(name) == ZIP;}
+private:
+ xptiFileType(); // no implementation
+};
+
+/***************************************************************************/
+
+// We use this is as a fancy way to open a logfile to be used within the scope
+// of some given function where it is instantiated.
+
+class xptiAutoLog
+{
+public:
+ xptiAutoLog(); // not implemented
+ xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append);
+ ~xptiAutoLog();
+private:
+ void WriteTimestamp(PRFileDesc* fd, const char* msg);
+
+ xptiInterfaceInfoManager* mMgr;
+ PRFileDesc* mOldFileDesc;
+#ifdef DEBUG
+ PRFileDesc* m_DEBUG_FileDesc;
+#endif
+};
+
+/***************************************************************************/
+
+class xptiInterfaceInfoManager
+ : public nsIInterfaceInfoSuperManager
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEINFOMANAGER
+ NS_DECL_NSIINTERFACEINFOSUPERMANAGER
+
+ // helper
+ PRBool
+ FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet);
+
+public:
+ static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
+ static void FreeInterfaceInfoManager();
+
+ xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;}
+ PRFileDesc* GetOpenLogFile() {return mOpenLogFile;}
+ PRFileDesc* SetOpenLogFile(PRFileDesc* fd)
+ {PRFileDesc* temp = mOpenLogFile; mOpenLogFile = fd; return temp;}
+
+ PRBool LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet = nsnull);
+
+ PRBool GetApplicationDir(nsILocalFile** aDir);
+ PRBool GetCloneOfManifestLocation(nsILocalFile** aDir);
+
+ void GetSearchPath(nsISupportsArray** aSearchPath)
+ {NS_ADDREF(*aSearchPath = mSearchPath);}
+
+ static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mResolveLock;}
+
+ static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mAutoRegLock;}
+
+ static PRMonitor* GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mInfoMonitor;}
+
+ static void WriteToLog(const char *fmt, ...);
+
+private:
+ ~xptiInterfaceInfoManager();
+ xptiInterfaceInfoManager(); // not implmented
+ xptiInterfaceInfoManager(nsISupportsArray* aSearchPath);
+
+ enum AutoRegMode {
+ NO_FILES_CHANGED = 0,
+ FILES_ADDED_ONLY,
+ FULL_VALIDATION_REQUIRED
+ };
+
+ PRBool IsValid();
+
+ PRBool BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList);
+
+ nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet* aWorkingSet);
+
+ AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded);
+
+ PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet);
+
+ void LogStats();
+
+ PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
+ PRBool DEBUG_DumpFileArray(nsILocalFile** aFileArray, PRUint32 count);
+ PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet);
+
+ static PRBool BuildFileSearchPath(nsISupportsArray** aPath);
+
+private:
+ xptiWorkingSet mWorkingSet;
+ nsCOMPtr<nsILocalFile> mStatsLogFile;
+ nsCOMPtr<nsILocalFile> mAutoRegLogFile;
+ PRFileDesc* mOpenLogFile;
+ PRLock* mResolveLock;
+ PRLock* mAutoRegLock;
+ PRMonitor* mInfoMonitor;
+ PRLock* mAdditionalManagersLock;
+ nsSupportsArray mAdditionalManagers;
+ nsCOMPtr<nsISupportsArray> mSearchPath;
+};
+
+/***************************************************************************/
+// utilities...
+
+nsresult xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile);
+
+nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile);
+
+#endif /* xptiprivate_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore
new file mode 100644
index 00000000..f29041e6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+TestInterfaceInfo
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in
new file mode 100644
index 00000000..9b7f1ed4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in
@@ -0,0 +1,58 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+SIMPLE_PROGRAMS = TestInterfaceInfo$(BIN_SUFFIX)
+
+CPPSRCS = TestInterfaceInfo.cpp
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTI_API
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp
new file mode 100644
index 00000000..75005c50
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Some simple smoke tests of the typelib loader. */
+
+#include "nscore.h"
+
+#include "nsISupports.h"
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+
+#include <stdio.h>
+
+// This file expects the nsInterfaceInfoManager to be able to discover
+// .xpt files corresponding to those in xpcom/idl. Currently this
+// means setting XPTDIR in the environment to some directory
+// containing these files.
+
+int main (int argc, char **argv) {
+ int i;
+ nsIID *iid1, *iid2, *iid3;
+ char *name1, *name2, *name3;
+ nsIInterfaceInfo *info2, *info3, *info4, *info5;
+
+ nsIInterfaceInfoManager *iim = XPTI_GetInterfaceInfoManager();
+
+ fprintf(stderr, "\ngetting iid for 'nsISupports'\n");
+ iim->GetIIDForName("nsISupports", &iid1);
+ iim->GetNameForIID(iid1, &name1);
+ fprintf(stderr, "%s iid %s\n", name1, iid1->ToString());
+
+ fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
+ iim->GetIIDForName("nsIInputStream", &iid2);
+ iim->GetNameForIID(iid2, &name2);
+ fprintf(stderr, "%s iid %s\n", name2, iid2->ToString());
+
+ fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1);
+ fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2);
+
+ fprintf(stderr, "\ngetting info for iid2 from above\n");
+ iim->GetInfoForIID(iid2, &info2);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info2)->print(stderr);
+#endif
+
+ fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
+ iim->GetIIDForName("nsIInputStream", &iid3);
+ iim->GetNameForIID(iid3, &name3);
+ fprintf(stderr, "%s iid %s\n", name3, iid2->ToString());
+ iim->GetInfoForIID(iid3, &info3);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info3)->print(stderr);
+#endif
+
+ fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n");
+ iim->GetInfoForName("nsIBidirectionalEnumerator", &info4);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info4)->print(stderr);
+#endif
+
+ fprintf(stderr, "\nparams work?\n");
+ fprintf(stderr, "\ngetting info for name 'nsIServiceManager'\n");
+ iim->GetInfoForName("nsIServiceManager", &info5);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info5)->print(stderr);
+#endif
+
+ // XXX: nsIServiceManager is no more; what do we test with?
+ if (info5 == NULL) {
+ fprintf(stderr, "\nNo nsIServiceManager; cannot continue.\n");
+ return 1;
+ }
+
+ uint16 methodcount;
+ info5->GetMethodCount(&methodcount);
+ const nsXPTMethodInfo *mi;
+ for (i = 0; i < methodcount; i++) {
+ info5->GetMethodInfo(i, &mi);
+ fprintf(stderr, "method %d, name %s\n", i, mi->GetName());
+ }
+
+ // 7 is GetServiceWithListener, which has juicy params.
+ info5->GetMethodInfo(7, &mi);
+// uint8 paramcount = mi->GetParamCount();
+
+ nsXPTParamInfo param2 = mi->GetParam(2);
+ // should be IID for nsIShutdownListener
+ nsIID *nsISL;
+ info5->GetIIDForParam(7, &param2, &nsISL);
+// const nsIID *nsISL = param2.GetInterfaceIID(info5);
+ fprintf(stderr, "iid assoc'd with param 2 of method 7 of GetServiceWithListener - %s\n", nsISL->ToString());
+ // if we look up the name?
+ char *nsISLname;
+ iim->GetNameForIID(nsISL, &nsISLname);
+ fprintf(stderr, "which is called %s\n", nsISLname);
+
+ fprintf(stderr, "\nhow about one defined in a different typelib\n");
+ nsXPTParamInfo param3 = mi->GetParam(3);
+ // should be IID for nsIShutdownListener
+ nsIID *nsISS;
+ info5->GetIIDForParam(7, &param3, &nsISS);
+// const nsIID *nsISS = param3.GetInterfaceIID(info5);
+ fprintf(stderr, "iid assoc'd with param 3 of method 7 of GetServiceWithListener - %s\n", nsISS->ToString());
+ // if we look up the name?
+ char *nsISSname;
+ iim->GetNameForIID(nsISS, &nsISSname);
+ fprintf(stderr, "which is called %s\n", nsISSname);
+
+ return 0;
+}
+