Bug 1606066 - Remove nsIAbCollection; r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net>
Wed, 11 Dec 2019 16:24:03 +1300
changeset 37828 12617633b4ff2aabdace5cea2ba6f7cd1454d05e
parent 37827 a6f54c89daf7a7a3aef24b3569a4970a60bd6fcd
child 37829 81d8400783ab24cb18c3592dfe9d77ee9be7bf70
push id397
push userclokep@gmail.com
push dateMon, 10 Feb 2020 21:16:13 +0000
reviewersmkmelin
bugs1606066
Bug 1606066 - Remove nsIAbCollection; r=mkmelin
mailnews/addrbook/jsaddrbook/AddrBookDirectory.jsm
mailnews/addrbook/public/moz.build
mailnews/addrbook/public/nsIAbCollection.idl
mailnews/addrbook/public/nsIAbDirectory.idl
mailnews/addrbook/src/nsAbDirProperty.cpp
mailnews/addrbook/src/nsAbDirProperty.h
mailnews/addrbook/test/unit/test_jsaddrbook.js
mailnews/jsaccount/src/JaAbDirectory.cpp
mailnews/jsaccount/src/JaAbDirectory.h
mailnews/jsaccount/test/unit/test_componentsExist.js
--- a/mailnews/addrbook/jsaddrbook/AddrBookDirectory.jsm
+++ b/mailnews/addrbook/jsaddrbook/AddrBookDirectory.jsm
@@ -171,17 +171,16 @@ function closeConnectionTo(file) {
 // One AddrBookDirectoryInner exists for each address book, multiple
 // AddrBookDirectory objects (e.g. queries) can use it as their prototype.
 
 var directories = new Map();
 
 /**
  * Prototype for nsIAbDirectory objects that aren't mailing lists.
  *
- * @implements {nsIAbCollection}
  * @implements {nsIAbDirectory}
  */
 function AddrBookDirectoryInner(fileName) {
   for (let child of Services.prefs.getChildList("ldap_2.servers.")) {
     if (
       child.endsWith(".filename") &&
       Services.prefs.getStringPref(child) == fileName
     ) {
@@ -500,64 +499,27 @@ AddrBookDirectoryInner.prototype = {
       }
       this._dbConnection.commitTransaction();
     } catch (ex) {
       this._dbConnection.rollbackTransaction();
       throw ex;
     }
   },
 
-  /* nsIAbCollection */
+  /* nsIAbDirectory */
 
   get readOnly() {
     return false;
   },
   get isRemote() {
     return false;
   },
   get isSecure() {
     return false;
   },
-  cardForEmailAddress(emailAddress) {
-    return (
-      this.getCardFromProperty("PrimaryEmail", emailAddress, false) ||
-      this.getCardFromProperty("SecondEmail", emailAddress, false)
-    );
-  },
-  getCardFromProperty(property, value, caseSensitive) {
-    let sql = caseSensitive
-      ? "SELECT card FROM properties WHERE name = :name AND value = :value LIMIT 1"
-      : "SELECT card FROM properties WHERE name = :name AND LOWER(value) = LOWER(:value) LIMIT 1";
-    let selectStatement = this._dbConnection.createStatement(sql);
-    selectStatement.params.name = property;
-    selectStatement.params.value = value;
-    let result = null;
-    if (selectStatement.executeStep()) {
-      result = this._getCard({ uid: selectStatement.row.card });
-    }
-    selectStatement.finalize();
-    return result;
-  },
-  getCardsFromProperty(property, value, caseSensitive) {
-    let sql = caseSensitive
-      ? "SELECT card FROM properties WHERE name = :name AND value = :value"
-      : "SELECT card FROM properties WHERE name = :name AND LOWER(value) = LOWER(:value)";
-    let selectStatement = this._dbConnection.createStatement(sql);
-    selectStatement.params.name = property;
-    selectStatement.params.value = value;
-    let results = [];
-    while (selectStatement.executeStep()) {
-      results.push(this._getCard({ uid: selectStatement.row.card }));
-    }
-    selectStatement.finalize();
-    return new SimpleEnumerator(results);
-  },
-
-  /* nsIAbDirectory */
-
   get propertiesChromeURI() {
     return "chrome://messenger/content/addressbook/abAddressBookNameDialog.xhtml";
   },
   get dirName() {
     return this.getLocalizedStringValue("description", "");
   },
   set dirName(value) {
     let oldValue = this.dirName;
@@ -742,16 +704,50 @@ AddrBookDirectoryInner.prototype = {
         ).asDirectory
     );
     return toXPCOMArray(lists, Ci.nsIMutableArray);
   },
 
   generateName(generateFormat, bundle) {
     return this.dirName;
   },
+  cardForEmailAddress(emailAddress) {
+    return (
+      this.getCardFromProperty("PrimaryEmail", emailAddress, false) ||
+      this.getCardFromProperty("SecondEmail", emailAddress, false)
+    );
+  },
+  getCardFromProperty(property, value, caseSensitive) {
+    let sql = caseSensitive
+      ? "SELECT card FROM properties WHERE name = :name AND value = :value LIMIT 1"
+      : "SELECT card FROM properties WHERE name = :name AND LOWER(value) = LOWER(:value) LIMIT 1";
+    let selectStatement = this._dbConnection.createStatement(sql);
+    selectStatement.params.name = property;
+    selectStatement.params.value = value;
+    let result = null;
+    if (selectStatement.executeStep()) {
+      result = this._getCard({ uid: selectStatement.row.card });
+    }
+    selectStatement.finalize();
+    return result;
+  },
+  getCardsFromProperty(property, value, caseSensitive) {
+    let sql = caseSensitive
+      ? "SELECT card FROM properties WHERE name = :name AND value = :value"
+      : "SELECT card FROM properties WHERE name = :name AND LOWER(value) = LOWER(:value)";
+    let selectStatement = this._dbConnection.createStatement(sql);
+    selectStatement.params.name = property;
+    selectStatement.params.value = value;
+    let results = [];
+    while (selectStatement.executeStep()) {
+      results.push(this._getCard({ uid: selectStatement.row.card }));
+    }
+    selectStatement.finalize();
+    return new SimpleEnumerator(results);
+  },
   deleteDirectory(directory) {
     let list = this._lists.get(directory.UID);
     list = new AddrBookMailingList(
       list.uid,
       this,
       list.localId,
       list.name,
       list.nickName,
--- a/mailnews/addrbook/public/moz.build
+++ b/mailnews/addrbook/public/moz.build
@@ -3,17 +3,16 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'nsIAbAddressCollector.idl',
     'nsIAbAutoCompleteResult.idl',
     'nsIAbBooleanExpression.idl',
     'nsIAbCard.idl',
-    'nsIAbCollection.idl',
     'nsIAbDirectory.idl',
     'nsIAbDirectoryQuery.idl',
     'nsIAbDirectoryQueryProxy.idl',
     'nsIAbDirFactory.idl',
     'nsIAbDirFactoryService.idl',
     'nsIAbDirSearchListener.idl',
     'nsIAbItem.idl',
     'nsIAbLDAPAttributeMap.idl',
deleted file mode 100644
--- a/mailnews/addrbook/public/nsIAbCollection.idl
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIAbItem.idl"
-
-interface nsIAbCard;
-interface nsISimpleEnumerator;
-
-/**
- * A collection of address book items.
- */
-[scriptable, uuid(70f6123f-e06b-4101-9750-4ce73b38134b)]
-interface nsIAbCollection : nsIAbItem {
-
-  /**
-   * Returns true if this collection is read-only.
-   */
-  readonly attribute boolean readOnly;
-
-  /**
-   * Returns true if this collection is accessed over a network connection.
-   */
-  readonly attribute boolean isRemote;
-
-  /**
-   * Returns true if this collection is accessed over a secure connection.
-   *
-   * If isRemote returns false, then this value MUST be false as well.
-   */
-  readonly attribute boolean isSecure;
-
-  /**
-   * Returns an address book card for the specified email address if found.
-   *
-   * If there are multiple cards with the given email address, this method will
-   * return one of these cards in an implementation-defined manner.
-   *
-   * Matching is performed in a case-insensitive manner.
-   *
-   * This method performs a synchronous operation. If the collection cannot do
-   * the search in such a manner, then it should throw NS_ERROR_NOT_IMPLEMENTED.
-   *
-   * @param  emailAddress The email address to find in any of the email address
-   *                      fields. If emailAddress is empty, the database won't
-   *                      be searched and the function will return as if no card
-   *                      was found.
-   * @return              An nsIAbCard if one was found, else returns NULL.
-   * @exception NS_ERROR_NOT_IMPLEMENTED If the collection cannot do this.
-   */
-  nsIAbCard cardForEmailAddress(in AUTF8String emailAddress);
-
-  /**
-   * Returns an address book card for the specified property if found.
-   *
-   * If there are multiple cards with the given value for the property, this
-   * method will return one of these cards in an implementation-defined manner.
-   *
-   * This method performs a synchronous operation. If the collection cannot do
-   * the search in such a manner, then it should throw NS_ERROR_NOT_IMPLEMENTED.
-   *
-   * If the property is not natively a string, it can still be searched for
-   * using the string-encoded value of the property, e.g. "0". See
-   * nsIAbCard::getPropertyAsAUTF8String for more information. Empty values will
-   * return no match, to prevent spurious results.
-   *
-   * @param  aProperty      The property to look for.
-   * @param  aValue         The value to search for.
-   * @param  aCaseSensitive True if matching should be done case-sensitively.
-   * @result                An nsIAbCard if one was found, else returns NULL.
-   * @exception NS_ERROR_NOT_IMPLEMENTED If the collection cannot do this.
-   */
-  nsIAbCard getCardFromProperty(in string aProperty, in AUTF8String aValue,
-                                in boolean aCaseSensitive);
-
-  /**
-   * Returns all address book cards with a specific property matching value
-   *
-   * This function is almost identical to getCardFromProperty, with the
-   * exception of returning all cards rather than just the first.
-   *
-   * @param  aProperty      The property to look for.
-   * @param  aValue         The value to search for.
-   * @param  aCaseSensitive True if matching should be done case-sensitively.
-   * @result                A nsISimpleEnumerator that holds nsIAbCard
-   *                        instances.
-   */
-  nsISimpleEnumerator getCardsFromProperty(in string aProperty,
-                                           in AUTF8String aValue,
-                                           in boolean aCaseSensitive);
-};
--- a/mailnews/addrbook/public/nsIAbDirectory.idl
+++ b/mailnews/addrbook/public/nsIAbDirectory.idl
@@ -1,14 +1,13 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsIAbCollection.idl"
 #include "nsIAbCard.idl"
 
 interface nsISimpleEnumerator;
 interface nsIArray;
 interface nsIMutableArray;
 
 /* moz-abdirectory:// is the URI to access nsAbBSDirectory,
  * which is the root directory for all types of address books
@@ -45,17 +44,92 @@ interface nsIMutableArray;
  * the Mork-based address book type is:
  *
  * @mozilla.org/addressbook/directory;1?type=moz-abmdbdirectory
  *
  * The UUID of an nsIAbDirectory is its preference ID and its name, concatenated
  * together.
  */
 [scriptable, uuid(72dc868b-db5b-4daa-b6c6-071be4a05d02)]
-interface nsIAbDirectory : nsIAbCollection {
+interface nsIAbDirectory : nsIAbItem {
+  /**
+   * Returns true if this collection is read-only.
+   */
+  readonly attribute boolean readOnly;
+
+  /**
+   * Returns true if this collection is accessed over a network connection.
+   */
+  readonly attribute boolean isRemote;
+
+  /**
+   * Returns true if this collection is accessed over a secure connection.
+   *
+   * If isRemote returns false, then this value MUST be false as well.
+   */
+  readonly attribute boolean isSecure;
+
+  /**
+   * Returns an address book card for the specified email address if found.
+   *
+   * If there are multiple cards with the given email address, this method will
+   * return one of these cards in an implementation-defined manner.
+   *
+   * Matching is performed in a case-insensitive manner.
+   *
+   * This method performs a synchronous operation. If the collection cannot do
+   * the search in such a manner, then it should throw NS_ERROR_NOT_IMPLEMENTED.
+   *
+   * @param  emailAddress The email address to find in any of the email address
+   *                      fields. If emailAddress is empty, the database won't
+   *                      be searched and the function will return as if no card
+   *                      was found.
+   * @return              An nsIAbCard if one was found, else returns NULL.
+   * @exception NS_ERROR_NOT_IMPLEMENTED If the collection cannot do this.
+   */
+  nsIAbCard cardForEmailAddress(in AUTF8String emailAddress);
+
+  /**
+   * Returns an address book card for the specified property if found.
+   *
+   * If there are multiple cards with the given value for the property, this
+   * method will return one of these cards in an implementation-defined manner.
+   *
+   * This method performs a synchronous operation. If the collection cannot do
+   * the search in such a manner, then it should throw NS_ERROR_NOT_IMPLEMENTED.
+   *
+   * If the property is not natively a string, it can still be searched for
+   * using the string-encoded value of the property, e.g. "0". See
+   * nsIAbCard::getPropertyAsAUTF8String for more information. Empty values will
+   * return no match, to prevent spurious results.
+   *
+   * @param  aProperty      The property to look for.
+   * @param  aValue         The value to search for.
+   * @param  aCaseSensitive True if matching should be done case-sensitively.
+   * @result                An nsIAbCard if one was found, else returns NULL.
+   * @exception NS_ERROR_NOT_IMPLEMENTED If the collection cannot do this.
+   */
+  nsIAbCard getCardFromProperty(in string aProperty, in AUTF8String aValue,
+                                in boolean aCaseSensitive);
+
+  /**
+   * Returns all address book cards with a specific property matching value
+   *
+   * This function is almost identical to getCardFromProperty, with the
+   * exception of returning all cards rather than just the first.
+   *
+   * @param  aProperty      The property to look for.
+   * @param  aValue         The value to search for.
+   * @param  aCaseSensitive True if matching should be done case-sensitively.
+   * @result                A nsISimpleEnumerator that holds nsIAbCard
+   *                        instances.
+   */
+  nsISimpleEnumerator getCardsFromProperty(in string aProperty,
+                                           in AUTF8String aValue,
+                                           in boolean aCaseSensitive);
 
   /**
    * The chrome URI to use for bringing up a dialog to edit this directory.
    * When opening the dialog, use a JS argument of
    * {selectedDirectory: thisdir} where thisdir is this directory that you just
    * got the chrome URI from.
    */
   readonly attribute ACString propertiesChromeURI;
--- a/mailnews/addrbook/src/nsAbDirProperty.cpp
+++ b/mailnews/addrbook/src/nsAbDirProperty.cpp
@@ -39,17 +39,17 @@ nsAbDirProperty::~nsAbDirProperty(void) 
     int32_t i;
     for (i = count - 1; i >= 0; i--)
       m_AddressList->RemoveElementAt(i);
   }
 #endif
 }
 
 NS_IMPL_ISUPPORTS(nsAbDirProperty, nsIAbDirectory, nsISupportsWeakReference,
-                  nsIAbCollection, nsIAbItem)
+                  nsIAbItem)
 
 NS_IMETHODIMP nsAbDirProperty::GetUuid(nsACString &uuid) {
   // XXX: not all directories have a dirPrefId...
   nsresult rv = GetDirPrefId(uuid);
   NS_ENSURE_SUCCESS(rv, rv);
   uuid.Append('&');
   nsString dirName;
   GetDirName(dirName);
--- a/mailnews/addrbook/src/nsAbDirProperty.h
+++ b/mailnews/addrbook/src/nsAbDirProperty.h
@@ -25,17 +25,16 @@
  */
 
 class nsAbDirProperty : public nsIAbDirectory, public nsSupportsWeakReference {
  public:
   nsAbDirProperty(void);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIABITEM
-  NS_DECL_NSIABCOLLECTION
   NS_DECL_NSIABDIRECTORY
 
  protected:
   virtual ~nsAbDirProperty(void);
 
   /**
    * Initialise the directory prefs for this branch
    */
--- a/mailnews/addrbook/test/unit/test_jsaddrbook.js
+++ b/mailnews/addrbook/test/unit/test_jsaddrbook.js
@@ -113,22 +113,20 @@ add_task(async function setUp() {
 add_task(async function createAddressBook() {
   let dirPrefId = MailServices.ab.newAddressBook("new book", "", DIR_TYPE);
   book = MailServices.ab.getDirectoryFromId(dirPrefId);
   observer.checkEvents(["onItemAdded", undefined, book]);
 
   // Check nsIAbItem properties.
   equal(book.uuid, "ldap_2.servers.newbook&new book");
 
-  // Check nsIAbCollection properties;
+  // Check nsIAbDirectory properties.
   ok(!book.readOnly);
   ok(!book.isRemote);
   ok(!book.isSecure);
-
-  // Check nsIAbDirectory properties.
   equal(book.dirName, "new book");
   equal(book.dirType, DIR_TYPE);
   equal(book.fileName, FILE_NAME);
   equal(book.UID.length, 36);
   equal(book.URI, `${SCHEME}://${FILE_NAME}`);
   equal(book.isMailList, false);
   equal(book.isQuery, false);
   equal(book.supportsMailingLists, true);
--- a/mailnews/jsaccount/src/JaAbDirectory.cpp
+++ b/mailnews/jsaccount/src/JaAbDirectory.cpp
@@ -21,17 +21,17 @@ NS_IMETHODIMP JaBaseCppAbDirectory::GetI
 }
 
 // Delegator
 NS_IMPL_ISUPPORTS_INHERITED(JaCppAbDirectoryDelegator, JaBaseCppAbDirectory,
                             msgIOverride)
 
 // Delegator object to bypass JS method override.
 NS_IMPL_ISUPPORTS(JaCppAbDirectoryDelegator::Super, nsIAbDirectory,
-                  nsIAbCollection, nsIAbItem, nsIInterfaceRequestor)
+                  nsIAbItem, nsIInterfaceRequestor)
 
 JaCppAbDirectoryDelegator::JaCppAbDirectoryDelegator()
     : mCppBase(new Super(this)), mMethods(nullptr) {}
 
 NS_IMETHODIMP JaCppAbDirectoryDelegator::SetMethodsToDelegate(
     msgIDelegateList* aDelegateList) {
   if (!aDelegateList) {
     NS_WARNING("Null delegate list");
@@ -51,17 +51,16 @@ NS_IMETHODIMP JaCppAbDirectoryDelegator:
 }
 
 NS_IMETHODIMP JaCppAbDirectoryDelegator::SetJsDelegate(
     nsISupports* aJsDelegate) {
   // If these QIs fail, then overrides are not provided for methods in that
   // interface, which is OK.
   mJsISupports = aJsDelegate;
   mJsIAbDirectory = do_QueryInterface(aJsDelegate);
-  mJsIAbCollection = do_QueryInterface(aJsDelegate);
   mJsIAbItem = do_QueryInterface(aJsDelegate);
   mJsIInterfaceRequestor = do_QueryInterface(aJsDelegate);
   return NS_OK;
 }
 NS_IMETHODIMP JaCppAbDirectoryDelegator::GetJsDelegate(
     nsISupports** aJsDelegate) {
   NS_ENSURE_ARG_POINTER(aJsDelegate);
   if (mJsISupports) {
--- a/mailnews/jsaccount/src/JaAbDirectory.h
+++ b/mailnews/jsaccount/src/JaAbDirectory.h
@@ -7,17 +7,16 @@
 #ifndef _JaAbDirectory_H_
 #define _JaAbDirectory_H_
 
 #include "nsISupports.h"
 #include "DelegateList.h"
 #include "msgIOverride.h"
 #include "nsIAbDirectory.h"
 #include "nsAbDirProperty.h"
-#include "nsIAbCollection.h"
 #include "nsIAbItem.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsIInterfaceRequestor.h"
 
 namespace mozilla {
 namespace mailnews {
 
@@ -39,49 +38,45 @@ class JaBaseCppAbDirectory : public nsAb
 class JaCppAbDirectoryDelegator : public JaBaseCppAbDirectory,
                                   public msgIOverride {
  public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_MSGIOVERRIDE
 
   // use mCppBase as a raw pointer where possible
   NS_FORWARD_NSIABDIRECTORY(DELEGATE_JS(mJsIAbDirectory, mMethods, mCppBase)->)
-  NS_FORWARD_NSIABCOLLECTION(
-      DELEGATE_JS(mJsIAbCollection, mMethods, (mCppBase.get()))->)
   NS_FORWARD_NSIABITEM(DELEGATE_JS(mJsIAbItem, mMethods, (mCppBase.get()))->)
   NS_FORWARD_NSIINTERFACEREQUESTOR(
       DELEGATE_JS(
           mJsIInterfaceRequestor, mMethods,
           (nsCOMPtr<nsIInterfaceRequestor>(do_QueryInterface(mCppBase))))
           ->)
 
   JaCppAbDirectoryDelegator();
 
  private:
   virtual ~JaCppAbDirectoryDelegator() {}
 
-  // nsIAbDirectory inherits from nsIAbCollection which inherits from nsIAbItem.
+  // nsIAbDirectory inherits from nsIAbItem.
   class Super : public nsIAbDirectory, public nsIInterfaceRequestor {
    public:
     explicit Super(JaCppAbDirectoryDelegator* aFakeThis) {
       mFakeThis = aFakeThis;
     }
     NS_DECL_ISUPPORTS
     NS_FORWARD_NSIABDIRECTORY(mFakeThis->JaBaseCppAbDirectory::)
-    NS_FORWARD_NSIABCOLLECTION(mFakeThis->JaBaseCppAbDirectory::)
     NS_FORWARD_NSIABITEM(mFakeThis->JaBaseCppAbDirectory::)
     NS_FORWARD_NSIINTERFACEREQUESTOR(mFakeThis->JaBaseCppAbDirectory::)
    private:
     virtual ~Super() {}
     JaCppAbDirectoryDelegator* mFakeThis;
   };
 
   // Interfaces that may be overridden by JS.
   nsCOMPtr<nsIAbDirectory> mJsIAbDirectory;
-  nsCOMPtr<nsIAbCollection> mJsIAbCollection;
   nsCOMPtr<nsIAbItem> mJsIAbItem;
   nsCOMPtr<nsIInterfaceRequestor> mJsIInterfaceRequestor;
 
   nsCOMPtr<nsISupports> mJsISupports;
 
   // Class to bypass JS delegates. nsCOMPtr for when we do cycle collection.
   nsCOMPtr<nsIAbDirectory> mCppBase;
 
--- a/mailnews/jsaccount/test/unit/test_componentsExist.js
+++ b/mailnews/jsaccount/test/unit/test_componentsExist.js
@@ -23,17 +23,16 @@ let tests = [
   ["@mozilla.org/jsaccount/testjafoourl;1", "nsIMsgMessageUrl"],
   ["@mozilla.org/jsaccount/testjafoourl;1", "nsIURL"],
   ["@mozilla.org/jsaccount/testjafoourl;1", "nsIURI"],
   ["@mozilla.org/jsaccount/testjafoourl;1", "msgIOverride"],
   ["@mozilla.org/jsaccount/testjafoourl;1", "nsIInterfaceRequestor"],
   // JaAbDirectory
   ["@mozilla.org/jacppabdirectorydelegator;1", "nsISupports"],
   ["@mozilla.org/jacppabdirectorydelegator;1", "nsIAbDirectory"],
-  ["@mozilla.org/jacppabdirectorydelegator;1", "nsIAbCollection"],
   ["@mozilla.org/jacppabdirectorydelegator;1", "nsIAbItem"],
   ["@mozilla.org/jacppabdirectorydelegator;1", "msgIOverride"],
   ["@mozilla.org/jacppabdirectorydelegator;1", "nsIInterfaceRequestor"],
   ["@mozilla.org/jacppabdirectorydelegator;1", "nsISupportsWeakReference"],
   // JaCompose
   ["@mozilla.org/jacppcomposedelegator;1", "nsISupports"],
   ["@mozilla.org/jacppcomposedelegator;1", "nsIMsgCompose"],
   ["@mozilla.org/jacppcomposedelegator;1", "nsIMsgSendListener"],