Revert many of the interface changes from bug 568691, so that binaries can be made which are compatible with Firefox 3.6 and Firefox 4. Note that this is not an ongoing process: it will not be possible to make single binary components which are compatible with both Firefox 4 and Firefox 4.1, but you will be able to ship two components and select one based on the platform version.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Thu, 24 Jun 2010 14:31:18 -0400
changeset 47042 95a67dbd4d36c6fb259a187ef0c5dd6696c41777
parent 47041 60c84aedde372108cc1ed42a25152e728496f504
child 47043 21ebf7198406df08149e7232ac26e92d96930d32
push idunknown
push userunknown
push dateunknown
bugs568691
milestone1.9.3a6pre
Revert many of the interface changes from bug 568691, so that binaries can be made which are compatible with Firefox 3.6 and Firefox 4. Note that this is not an ongoing process: it will not be possible to make single binary components which are compatible with both Firefox 4 and Firefox 4.1, but you will be able to ship two components and select one based on the platform version.
xpcom/components/Makefile.in
xpcom/components/nsCategoryManager.cpp
xpcom/components/nsCategoryManager.h
xpcom/components/nsComponentManager.cpp
xpcom/components/nsICategoryManager.idl
xpcom/components/nsIComponentRegistrar.idl
xpcom/components/nsIModule.idl
--- a/xpcom/components/Makefile.in
+++ b/xpcom/components/Makefile.in
@@ -68,17 +68,18 @@ CPPSRCS		= \
 		ManifestParser.cpp \
 		nsNativeComponentLoader.cpp \
 		GenericFactory.cpp \
 		$(NULL)
 
 SDK_XPIDLSRCS	= \
 		nsIClassInfo.idl	      \
 		nsIComponentRegistrar.idl     \
-		nsIFactory.idl                \
+		nsIFactory.idl		      \
+		nsIModule.idl		      \
 		nsIServiceManager.idl	      \
 		nsIComponentManager.idl       \
 		nsICategoryManager.idl        \
 		$(NULL)
 
 LOCAL_INCLUDES	= \
 	-I$(srcdir)/../reflect/xptinfo/src \
 	-I$(srcdir)/../base \
@@ -91,13 +92,13 @@ LOCAL_INCLUDES	= \
 
 # 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
 
-DEFINES	+= -D_IMPL_NS_COM -DNAKED_DLL_SUFFIX=\"$(patsubst .%,%,$(DLL_SUFFIX))\"
+DEFINES	+= -D_IMPL_NS_COM
 
 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
 CXXFLAGS += $(MOZ_GTK2_CFLAGS)
 endif
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -321,16 +321,27 @@ CategoryNode::AddLeaf(const char* aEntry
 
       leaf->value = arenaValue;
     }
   }
     
   return rv;
 }
 
+void
+CategoryNode::DeleteLeaf(const char* aEntryName)
+{
+  // we don't throw any errors, because it normally doesn't matter
+  // and it makes JS a lot cleaner
+  MutexAutoLock lock(mLock);
+
+  // we can just remove the entire hash entry without introspection
+  mTable.RemoveEntry(aEntryName);
+}
+
 NS_METHOD 
 CategoryNode::Enumerate(nsISimpleEnumerator **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
 
   MutexAutoLock lock(mLock);
   EntryEnumerator* enumObj = EntryEnumerator::Create(mTable);
 
@@ -549,21 +560,43 @@ nsCategoryManager::GetCategoryEntry( con
 
   if (category) {
     status = category->GetLeaf(aEntryName, _retval);
   }
 
   return status;
 }
 
+NS_IMETHODIMP
+nsCategoryManager::AddCategoryEntry( const char *aCategoryName,
+                                     const char *aEntryName,
+                                     const char *aValue,
+                                     PRBool aPersist,
+                                     PRBool aReplace,
+                                     char **_retval )
+{
+  if (aPersist) {
+    NS_ERROR("Category manager doesn't support persistence.");
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  AddCategoryEntry(aCategoryName, aEntryName, aValue, aReplace, _retval);
+  return NS_OK;
+}
+
 void
 nsCategoryManager::AddCategoryEntry(const char *aCategoryName,
                                     const char *aEntryName,
-                                    const char *aValue)
+                                    const char *aValue,
+                                    bool aReplace,
+                                    char** aOldValue)
 {
+  if (aOldValue)
+    *aOldValue = NULL;
+
   // Before we can insert a new entry, we'll need to
   //  find the |CategoryNode| to put it in...
   CategoryNode* category;
   {
     MutexAutoLock lock(mLock);
     category = get_category(aCategoryName);
 
     if (!category) {
@@ -589,18 +622,80 @@ nsCategoryManager::AddCategoryEntry(cons
   if (NS_SUCCEEDED(rv)) {
     if (oldEntry) {
       NotifyObservers(NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID,
                       aCategoryName, oldEntry);
     }
     NotifyObservers(NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID,
                     aCategoryName, aEntryName);
 
-    NS_Free(oldEntry);
+    if (aOldValue)
+      *aOldValue = oldEntry;
+    else
+      NS_Free(oldEntry);
+  }
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategoryEntry( const char *aCategoryName,
+                                        const char *aEntryName,
+                                        PRBool aDontPersist)
+{
+  if (!aDontPersist) {
+    NS_ERROR("Persistence not supported in the category manager.");
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  NS_ENSURE_ARG_POINTER(aCategoryName);
+  NS_ENSURE_ARG_POINTER(aEntryName);
+
+  /*
+    Note: no errors are reported since failure to delete
+    probably won't hurt you, and returning errors seriously
+    inconveniences JS clients
+  */
+
+  CategoryNode* category;
+  {
+    MutexAutoLock lock(mLock);
+    category = get_category(aCategoryName);
   }
+
+  if (category) {
+    category->DeleteLeaf(aEntryName);
+
+    NotifyObservers(NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID,
+                    aCategoryName, aEntryName);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategory( const char *aCategoryName )
+{
+  NS_ENSURE_ARG_POINTER(aCategoryName);
+
+  // the categories are arena-allocated, so we don't
+  // actually delete them. We just remove all of the
+  // leaf nodes.
+
+  CategoryNode* category;
+  {
+    MutexAutoLock lock(mLock);
+    category = get_category(aCategoryName);
+  }
+
+  if (category) {
+    category->Clear();
+    NotifyObservers(NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID,
+                    aCategoryName, nsnull);
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCategoryManager::EnumerateCategory( const char *aCategoryName,
                                       nsISimpleEnumerator **_retval )
 {
   NS_ENSURE_ARG_POINTER(aCategoryName);
   NS_ENSURE_ARG_POINTER(_retval);
--- a/xpcom/components/nsCategoryManager.h
+++ b/xpcom/components/nsCategoryManager.h
@@ -81,16 +81,23 @@ public:
   NS_METHOD GetLeaf(const char* aEntryName,
                     char** _retval);
 
   NS_METHOD AddLeaf(const char* aEntryName,
                     const char* aValue,
                     char** _retval,
                     PLArenaPool* aArena);
 
+  void DeleteLeaf(const char* aEntryName);
+
+  void Clear() {
+    mozilla::MutexAutoLock lock(mLock);
+    mTable.Clear();
+  }
+
   PRUint32 Count() {
     mozilla::MutexAutoLock lock(mLock);
     PRUint32 tCount = mTable.Count();
     return tCount;
   }
 
   NS_METHOD Enumerate(nsISimpleEnumerator** _retval);
 
@@ -127,17 +134,19 @@ public:
    * Suppress or unsuppress notifications of category changes to the
    * observer service. This is to be used by nsComponentManagerImpl
    * on startup while reading the stored category list.
    */
   NS_METHOD SuppressNotifications(PRBool aSuppress);
 
   void AddCategoryEntry(const char* aCategory,
                         const char* aKey,
-                        const char* aValue);
+                        const char* aValue,
+                        bool aReplace = true,
+                        char** aOldValue = NULL);
 
   static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
   static nsCategoryManager* GetSingleton();
   static void Destroy();
 
 private:
   static nsCategoryManager* gCategoryManager;
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -1540,16 +1540,54 @@ nsComponentManagerImpl::UnregisterFactor
         f->mFactory.swap(dyingFactory);
         f->mServiceObject.swap(dyingServiceObject);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsComponentManagerImpl::AutoRegister(nsIFile* aLocation)
+{
+    nsCOMPtr<nsILocalFile> lf = do_QueryInterface(aLocation);
+    if (!lf)
+        return NS_ERROR_INVALID_ARG;
+
+    XRE_AddComponentLocation(NS_COMPONENT_LOCATION, lf);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation)
+{
+    NS_ERROR("AutoUnregister not implemented.");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactoryLocation(const nsCID& aCID,
+                                                const char* aClassName,
+                                                const char* aContractID,
+                                                nsIFile* aFile,
+                                                const char* aLoaderStr,
+                                                const char* aType)
+{
+    NS_ERROR("RegisterFactoryLocation not implemented.");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID,
+                                                  nsIFile* aFile)
+{
+    NS_ERROR("UnregisterFactoryLocation not implemented.");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
                                         PRBool *_retval)
 {
     *_retval = (nsnull != GetFactoryEntry(aClass));
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1606,25 +1644,23 @@ nsComponentManagerImpl::EnumerateContrac
     nsCOMPtr<nsIUTF8StringEnumerator> e;
     nsresult rv = NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e), array);
     if (NS_FAILED(rv))
         return rv;
 
     return CallQueryInterface(e, aEnumerator);
 }
 
-#if 0
 NS_IMETHODIMP
 nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
                                         char **_retval)
 {
     NS_ERROR("CIDTOContractID not implemented");
     return NS_ERROR_FACTORY_NOT_REGISTERED;
 }
-#endif
 
 NS_IMETHODIMP
 nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
                                         nsCID * *_retval)
 {
     {
         nsAutoMonitor mon(mMon);
         nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
--- a/xpcom/components/nsICategoryManager.idl
+++ b/xpcom/components/nsICategoryManager.idl
@@ -38,28 +38,56 @@
 #include "nsISupports.idl"
 #include "nsISimpleEnumerator.idl"
 
 /*
  * nsICategoryManager
  * @status FROZEN
  */
 
-[scriptable, uuid(70F95BAF-8F93-4D24-B9E0-3428DF27A835)]
+[scriptable, uuid(3275b2cd-af6d-429a-80d7-f0c5120342ac)]
 interface nsICategoryManager : nsISupports
 {
     /**
      * Get the value for the given category's entry.
      * @param aCategory The name of the category ("protocol")
      * @param aEntry The entry you're looking for ("http")
      * @return The value.
      */
     string getCategoryEntry(in string aCategory, in string aEntry);
     
     /**
+     * Add an entry to a category.
+     * @param aCategory The name of the category ("protocol")
+     * @param aEntry The entry to be added ("http")
+     * @param aValue The value for the entry ("moz.httprulez.1")
+     * @param aPersist Should this data persist between invocations?
+     * @param aReplace Should we replace an existing entry?
+     * @return Previous entry, if any
+     */
+    string addCategoryEntry(in string aCategory, in string aEntry,
+			    in string aValue, in boolean aPersist,
+			    in boolean aReplace);
+
+    /**
+     * Delete an entry from the category.
+     * @param aCategory The name of the category ("protocol")
+     * @param aEntry The entry to be added ("http")
+     * @param aPersist Delete persistent data from registry, if present?
+     */
+    void deleteCategoryEntry(in string aCategory, in string aEntry,
+                               in boolean aPersist);
+
+    /**
+     * Delete a category and all entries.
+     * @param aCategory The category to be deleted.
+     */
+    void deleteCategory(in string aCategory);
+
+    /**
      * Enumerate the entries in a category.
      * @param aCategory The category to be enumerated.
      * @return a simple enumerator, each result QIs to
      *         nsISupportsCString.
      */
     nsISimpleEnumerator enumerateCategory(in string aCategory);
 
     /**
--- a/xpcom/components/nsIComponentRegistrar.idl
+++ b/xpcom/components/nsIComponentRegistrar.idl
@@ -39,28 +39,49 @@
  */
 
 #include "nsISupports.idl"
 
 interface nsIFile;
 interface nsIFactory;
 interface nsISimpleEnumerator;
 
-[scriptable, uuid(B0010F0B-C162-48A1-9E5E-E3453B80388C)]
+[scriptable, uuid(2417cbfe-65ad-48a6-b4b6-eb84db174392)]
 interface nsIComponentRegistrar : nsISupports
 {
     /**
+     * autoRegister
+     *
+     * Register a .manifest or .xpt file, or an entire directory containing
+     * these files. Registration lasts for this run only, and is not cached.
+     *
+     * @note Formerly this method would register component files directly. This
+     *       is no longer supported.
+     */
+    void autoRegister(in nsIFile aSpec);
+
+    /**
+     * autoUnregister
+     * @status OBSOLETE: This method is no longer implemented, but preserved
+     *                   in this interface for binary compatibility with
+     *                   Mozilla 1.9.2.
+     */
+    void autoUnregister(in nsIFile aSpec);
+
+
+    /**
      * registerFactory
      *
      * Register a factory with a given ContractID, CID and Class Name.
      *
      * @param aClass      : CID of object
      * @param aClassName  : Class Name of CID (unused)
-     * @param aContractID : ContractID associated with CID aClass (optional)
-     * @param aFactory    : Factory that will be registered for CID aClass
+     * @param aContractID : ContractID associated with CID aClass. May be null
+     *                      if no contract ID is needed.
+     * @param aFactory    : Factory that will be registered for CID aClass.
      *                      If aFactory is null, the contract will be associated
      *                      with a previously registered CID.
      */
     void registerFactory(in nsCIDRef aClass, 
                          in string aClassName,
                          in string aContractID, 
                          in nsIFactory aFactory);
 
@@ -75,16 +96,38 @@ interface nsIComponentRegistrar : nsISup
      *
      * @return NS_OK     Unregistration was successful.
      *         NS_ERROR* Method failure.
      */    
     void unregisterFactory(in nsCIDRef aClass, 
                            in nsIFactory aFactory);
 
     /**
+     * registerFactoryLocation
+     * @status OBSOLETE: This method is no longer implemented, but preserved
+     *                   in this interface for binary compatibility with
+     *                   Mozilla 1.9.2.
+     */
+    void registerFactoryLocation(in nsCIDRef aClass, 
+                                 in string aClassName,
+                                 in string aContractID, 
+                                 in nsIFile aFile,
+                                 in string aLoaderStr, 
+                                 in string aType);
+
+    /**
+     * unregisterFactoryLocation
+     * @status OBSOLETE: This method is no longer implemented, but preserved
+     *                   in this interface for binary compatibility with
+     *                   Mozilla 1.9.2.
+     */    
+    void unregisterFactoryLocation(in nsCIDRef aClass, 
+                                   in nsIFile aFile);
+
+    /**
      * isCIDRegistered
      *
      * Returns true if a factory is registered for the CID.
      *
      * @param aClass : CID queried for registeration
      * @return       : true if a factory is registered for CID 
      *                 false otherwise.
      */
@@ -120,16 +163,24 @@ interface nsIComponentRegistrar : nsISup
      * @return : enumerator for ContractIDs. Elements of the enumeration can be 
      *           QI'ed for the nsISupportsCString interface.  From  the
      *           nsISupportsCString interface, you can obtain the actual 
      *           Contract ID string.
      */
     nsISimpleEnumerator enumerateContractIDs();
 
     /**
+     * CIDToContractID
+     * @status OBSOLETE: This method is no longer implemented, but preserved
+     *                   in this interface for binary compatibility with
+     *                   Mozilla 1.9.2.
+     */
+    string   CIDToContractID(in nsCIDRef aClass);
+
+    /**
      * contractIDToCID
      *
      * Returns the CID for a given Contract ID, if one exists and is registered.
      *
      * @return : Contract ID.
      */
     nsCIDPtr contractIDToCID(in string aContractID);
 };
new file mode 100644
--- /dev/null
+++ b/xpcom/components/nsIModule.idl
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; 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 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 ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+interface nsIComponentManager;
+
+/**
+ * The nsIModule interface.
+ * @status FROZEN
+ */
+
+[scriptable, uuid(7392D032-5371-11d3-994E-00805FD26FEE)]
+interface nsIModule : nsISupports
+{
+    /** 
+     * Object Instance Creation
+     *
+     * Obtains a Class Object from a nsIModule for a given CID and IID pair.  
+     * This class object can either be query to a nsIFactory or a may be 
+     * query to a nsIClassInfo.
+     *
+     * @param aCompMgr  : The global component manager
+     * @param aClass    : ClassID of object instance requested
+     * @param aIID      : IID of interface requested
+     * 
+     */
+    void getClassObject(in nsIComponentManager aCompMgr, 
+                        in nsCIDRef aClass,
+                        in nsIIDRef aIID,
+                        [retval, iid_is(aIID)] out nsQIResult aResult);
+
+
+    /**
+     * One time registration callback
+     *
+     * When the nsIModule is discovered, this method will be
+     * called so that any setup registration can be preformed.
+     *
+     * @param aCompMgr  : The global component manager
+     * @param aLocation : The location of the nsIModule on disk
+     * @param aLoaderStr: Opaque loader specific string
+     * @param aType     : Loader Type being used to load this module 
+     */
+    void registerSelf(in nsIComponentManager aCompMgr, 
+                      in nsIFile aLocation,
+                      in string aLoaderStr, 
+                      in string aType);
+    /**
+     * One time unregistration callback
+     *
+     * When the nsIModule is being unregistered, this method will be
+     * called so that any unregistration can be preformed
+     *
+     * @param aCompMgr   : The global component manager
+     * @param aLocation  : The location of the nsIModule on disk
+     * @param aLoaderStr : Opaque loader specific string
+     * 
+     */
+   void unregisterSelf(in nsIComponentManager aCompMgr, 
+                        in nsIFile aLocation,
+                        in string  aLoaderStr);
+
+   /** 
+    * Module load management
+    * 
+    * @param aCompMgr  : The global component manager
+    *
+    * @return indicates to the caller if the module can be unloaded.
+    * 		Returning PR_TRUE isn't a guarantee that the module will be
+    *		unloaded. It constitues only willingness of the module to be
+    *		unloaded.  It is very important to ensure that no outstanding 
+    *       references to the module's code/data exist before returning 
+    *       PR_TRUE. 
+    *		Returning PR_FALSE guaratees that the module won't be unloaded.
+    */
+    boolean canUnload(in nsIComponentManager aCompMgr);
+};
+
+