Bug 1562313 - Convert JavaScript components to use static registration in mailnews/. r=mkmelin
authorKhushil Mistry <khushil324@gmail.com>
Tue, 12 Nov 2019 13:03:00 +0100
changeset 37521 0f435d1559190627ecdfa9f8162a9b32275b88b3
parent 37520 430487e62ffd051ea2047205d10f3993587390c7
child 37522 e667b9f62b83583094e564bb3640fcaee26fcc8c
push id396
push userclokep@gmail.com
push dateMon, 06 Jan 2020 23:11:57 +0000
reviewersmkmelin
bugs1562313
Bug 1562313 - Convert JavaScript components to use static registration in mailnews/. r=mkmelin
mail/installer/package-manifest.in
mailnews/addrbook/src/AbAutoCompleteMyDomain.jsm
mailnews/addrbook/src/AbAutoCompleteSearch.jsm
mailnews/addrbook/src/AbLDAPAttributeMap.jsm
mailnews/addrbook/src/AbLDAPAutoCompleteSearch.jsm
mailnews/addrbook/src/components.conf
mailnews/addrbook/src/moz.build
mailnews/addrbook/src/nsAbAutoCompleteMyDomain.js
mailnews/addrbook/src/nsAbAutoCompleteSearch.js
mailnews/addrbook/src/nsAbLDAPAttributeMap.js
mailnews/addrbook/src/nsAbLDAPAutoCompleteSearch.js
mailnews/addrbook/src/nsAddrbook.manifest
mailnews/base/search/src/MsgTraitService.jsm
mailnews/base/search/src/components.conf
mailnews/base/search/src/moz.build
mailnews/base/search/src/nsMsgTraitService.js
mailnews/base/search/src/nsMsgTraitService.manifest
mailnews/base/src/FolderLookupService.jsm
mailnews/base/src/MailNewsCommandLineHandler.jsm
mailnews/base/src/MailNotificationService.jsm
mailnews/base/src/MsgAsyncPrompter.jsm
mailnews/base/src/OAuth2Module.jsm
mailnews/base/src/components.conf
mailnews/base/src/folderLookupService.js
mailnews/base/src/moz.build
mailnews/base/src/msgAsyncPrompter.js
mailnews/base/src/msgBase.manifest
mailnews/base/src/msgOAuth2Module.js
mailnews/base/src/newMailNotificationService.js
mailnews/base/src/nsMailNewsCommandLineHandler.js
mailnews/compose/src/SMTPProtocolHandler.jsm
mailnews/compose/src/components.conf
mailnews/compose/src/moz.build
mailnews/compose/src/nsSMTPProtocolHandler.js
mailnews/compose/src/nsSMTPProtocolHandler.manifest
mailnews/db/gloda/components/GlodaAutoComplete.jsm
mailnews/db/gloda/components/MimeMessageEmitter.jsm
mailnews/db/gloda/components/components.conf
mailnews/db/gloda/components/glautocomp.js
mailnews/db/gloda/components/gloda.manifest
mailnews/db/gloda/components/jsmimeemitter.js
mailnews/db/gloda/components/moz.build
mailnews/extensions/dsn/moz.build
mailnews/extensions/dsn/src/DSNService.jsm
mailnews/extensions/dsn/src/components.conf
mailnews/extensions/dsn/src/dsn-service.js
mailnews/extensions/dsn/src/dsn-service.manifest
mailnews/extensions/mdn/src/MDNService.jsm
mailnews/extensions/mdn/src/components.conf
mailnews/extensions/mdn/src/mdn-service.js
mailnews/extensions/mdn/src/mdn-service.manifest
mailnews/extensions/mdn/src/moz.build
mailnews/extensions/newsblog/components.conf
mailnews/extensions/newsblog/content/NewsBlog.jsm
mailnews/extensions/newsblog/js/newsblog.js
mailnews/extensions/newsblog/js/newsblog.manifest
mailnews/extensions/newsblog/moz.build
mailnews/extensions/offline-startup/OfflineStartup.jsm
mailnews/extensions/offline-startup/components.conf
mailnews/extensions/offline-startup/js/offlineStartup.js
mailnews/extensions/offline-startup/js/offlineStartup.manifest
mailnews/extensions/offline-startup/moz.build
mailnews/extensions/smime/src/SMIMEService.jsm
mailnews/extensions/smime/src/components.conf
mailnews/extensions/smime/src/moz.build
mailnews/extensions/smime/src/smime-service.js
mailnews/extensions/smime/src/smime-service.manifest
mailnews/import/test/components.conf
mailnews/import/test/moz.build
mailnews/import/test/unit/resources/TestMailImporter.js
mailnews/import/test/unit/resources/TestMailImporter.jsm
mailnews/import/test/unit/resources/TestMailImporter.manifest
mailnews/import/test/unit/resources/import_helper.js
mailnews/jsaccount/moz.build
mailnews/jsaccount/test/components.conf
mailnews/jsaccount/test/moz.build
mailnews/jsaccount/test/unit/resources/TestJaMsgProtocolInfoComponent.jsm
mailnews/jsaccount/test/unit/resources/testComponents.manifest
mailnews/jsaccount/test/unit/resources/testJaMsgProtocolInfoComponent.js
mailnews/mime/src/MimeJSComponents.jsm
mailnews/mime/src/components.conf
mailnews/mime/src/mimeJSComponents.js
mailnews/mime/src/moz.build
mailnews/mime/src/msgMime.manifest
mailnews/news/src/NewsAutoCompleteSearch.jsm
mailnews/news/src/components.conf
mailnews/news/src/moz.build
mailnews/news/src/nsNewsAutoCompleteSearch.js
mailnews/news/src/nsNewsAutoCompleteSearch.manifest
--- a/mail/installer/package-manifest.in
+++ b/mail/installer/package-manifest.in
@@ -123,18 +123,16 @@
 @BINPATH@/libEGL.dll
 @BINPATH@/libGLESv2.dll
 #endif
 
 ; Optional RSS extension
 [newsblog]
 @RESPATH@/chrome/newsblog@JAREXT@
 @RESPATH@/chrome/newsblog.manifest
-@RESPATH@/components/newsblog.js
-@RESPATH@/components/newsblog.manifest
 
 [mail]
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 @BINPATH@/thunderbird.VisualElementsManifest.xml
 @BINPATH@/VisualElements/VisualElements_150.png
 @BINPATH@/VisualElements/VisualElements_70.png
 #else
@@ -172,28 +170,20 @@
 @RESPATH@/defaults/messenger/mailViews.dat
 @RESPATH@/defaults/profile/prefs.js
 
 @RESPATH@/isp/*
 
 @RESPATH@/components/EnterprisePolicies.js
 @RESPATH@/components/EnterprisePolicies.manifest
 @RESPATH@/components/EnterprisePoliciesContent.js
-@RESPATH@/components/folderLookupService.js
 ; interfaces.manifest doesn't get packaged because it is dynamically
 ; re-created at packaging time when linking the xpts that will actually
 ; go into the package, so the test related interfaces aren't included.
-@RESPATH@/components/mimeJSComponents.js
 @RESPATH@/components/msgMime.manifest
-@RESPATH@/components/msgAsyncPrompter.js
-@RESPATH@/components/msgBase.manifest
-@RESPATH@/components/nsAddrbook.manifest
-@RESPATH@/components/nsMailNewsCommandLineHandler.js
-@RESPATH@/components/nsNewsAutoCompleteSearch.js
-@RESPATH@/components/nsNewsAutoCompleteSearch.manifest
 @RESPATH@/chrome/toolkit@JAREXT@
 @RESPATH@/chrome/toolkit.manifest
 @RESPATH@/chrome/comm@JAREXT@
 @RESPATH@/chrome/comm.manifest
 ; Browser: Hack to get built_in_addons.json packaged
 @RESPATH@/chrome/browser@JAREXT@
 @RESPATH@/chrome/browser.manifest
 @RESPATH@/chrome/messenger@JAREXT@
@@ -210,41 +200,24 @@
 @RESPATH@/chrome/icons/default/calendar-task-summary-dialog.ico
 #elifdef UNIX_BUT_NOT_MAC
 @RESPATH@/chrome/icons/default/*.png
 #endif
 
 ; Gloda
 @RESPATH@/chrome/gloda@JAREXT@
 @RESPATH@/chrome/gloda.manifest
-@RESPATH@/components/glautocomp.js
-@RESPATH@/components/gloda.manifest
-@RESPATH@/components/jsmimeemitter.js
-
-; OAuth2 for mail
-@RESPATH@/components/msgOAuth2Module.js
-
-; New message notification
-@RESPATH@/components/newMailNotificationService.js
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Mail Extensions (smime, etc.)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 #ifdef MOZ_MAPI_SUPPORT
 @BINPATH@/MapiProxy.dll
 @BINPATH@/mozMapi32.dll
 #endif
-@RESPATH@/components/offlineStartup.js
-@RESPATH@/components/offlineStartup.manifest
-
-
-@RESPATH@/components/mdn-service.js
-@RESPATH@/components/mdn-service.manifest
-@RESPATH@/components/smime-service.js
-@RESPATH@/components/smime-service.manifest
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; instant messaging
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 @RESPATH@/@PREF_DIR@/chat-prefs.js
 @RESPATH@/chrome/chat@JAREXT@
 @RESPATH@/chrome/chat.manifest
 @RESPATH@/components/imAccounts.js
@@ -317,49 +290,35 @@
 @RESPATH@/defaults/settings/main
 @RESPATH@/greprefs.js
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; App extensions to Mail
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 ; LDAP components
-@RESPATH@/components/nsAbLDAPAttributeMap.js
 #ifdef MOZ_LDAP_XPCOM
-@RESPATH@/components/nsAbLDAPAutoCompleteSearch.js
 @RESPATH@/components/nsLDAPProtocolHandler.js
 @RESPATH@/components/ldapComponents.manifest
 @BINPATH@/@DLL_PREFIX@ldap60@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@ldif60@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@prldap60@DLL_SUFFIX@
 #endif
 
-; Protocol/Content handling
-@RESPATH@/components/nsSMTPProtocolHandler.js
-@RESPATH@/components/nsSMTPProtocolHandler.manifest
-
 ; misson control, autoconfig
 #ifdef MOZ_PREF_EXTENSIONS
 @RESPATH@/defaults/autoconfig/prefcalls.js
 #endif
 
-; Address Book autocomplete
-@RESPATH@/components/nsAbAutoCompleteMyDomain.js
-@RESPATH@/components/nsAbAutoCompleteSearch.js
-
 ; Windows Search integration
 ; the module is included as part of the "Modules" rule
 #ifdef XP_WIN
 @BINPATH@/WSEnable.exe
 #endif
 
-; Bayesian trait analysis
-@RESPATH@/components/nsMsgTraitService.js
-@RESPATH@/components/nsMsgTraitService.manifest
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Base Package Files
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 ; accessibility (out of process API support)
 #ifdef ACCESSIBILITY
 #ifdef XP_WIN
 @BINPATH@/Accessible.tlb
rename from mailnews/addrbook/src/nsAbAutoCompleteMyDomain.js
rename to mailnews/addrbook/src/AbAutoCompleteMyDomain.jsm
--- a/mailnews/addrbook/src/nsAbAutoCompleteMyDomain.js
+++ b/mailnews/addrbook/src/AbAutoCompleteMyDomain.jsm
@@ -1,23 +1,21 @@
 /* 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/. */
 
+var EXPORTED_SYMBOLS = ["AbAutoCompleteMyDomain"];
+
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
-function nsAbAutoCompleteMyDomain() {}
+function AbAutoCompleteMyDomain() {}
 
-nsAbAutoCompleteMyDomain.prototype = {
-  classID: Components.ID("{5b259db2-e451-4de9-8a6f-cfba91402973}"),
+AbAutoCompleteMyDomain.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAutoCompleteSearch]),
 
   cachedIdKey: "",
   cachedIdentity: null,
 
   applicableHeaders: new Set(["addr_to", "addr_cc", "addr_bcc", "addr_reply"]),
 
   startSearch(aString, aSearchParam, aResult, aListener) {
@@ -64,11 +62,8 @@ nsAbAutoCompleteMyDomain.prototype = {
       },
       removeValueAt() {},
     };
     aListener.onSearchResult(this, result);
   },
 
   stopSearch() {},
 };
-
-var components = [nsAbAutoCompleteMyDomain];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
rename from mailnews/addrbook/src/nsAbAutoCompleteSearch.js
rename to mailnews/addrbook/src/AbAutoCompleteSearch.jsm
--- a/mailnews/addrbook/src/nsAbAutoCompleteSearch.js
+++ b/mailnews/addrbook/src/AbAutoCompleteSearch.jsm
@@ -1,25 +1,24 @@
 /* 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/. */
 
+var EXPORTED_SYMBOLS = ["AbAutoCompleteSearch"];
+
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var {
   getSearchTokens,
   getModelQuery,
   modelQueryHasUserValue,
   generateQueryURI,
 } = ChromeUtils.import("resource:///modules/ABQueryUtils.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 var ACR = Ci.nsIAutoCompleteResult;
 var nsIAbAutoCompleteResult = Ci.nsIAbAutoCompleteResult;
 
 function nsAbAutoCompleteResult(aSearchString) {
   // Can't create this in the prototype as we'd get the same array for
   // all instances
   this._searchResults = []; // final results
@@ -85,22 +84,19 @@ nsAbAutoCompleteResult.prototype = {
     return this._searchResults[aIndex].emailToUse;
   },
 
   // nsISupports
 
   QueryInterface: ChromeUtils.generateQI([ACR, nsIAbAutoCompleteResult]),
 };
 
-function nsAbAutoCompleteSearch() {}
+function AbAutoCompleteSearch() {}
 
-nsAbAutoCompleteSearch.prototype = {
-  // For component registration
-  classID: Components.ID("2f946df9-114c-41fe-8899-81f10daf4f0c"),
-
+AbAutoCompleteSearch.prototype = {
   // This is set from a preference,
   // 0 = no comment column, 1 = name of address book this card came from
   // Other numbers currently unused (hence default to zero)
   _commentColumn: 0,
   _parser: MailServices.headerParser,
   _abManager: MailServices.ab,
   applicableHeaders: new Set(["addr_to", "addr_cc", "addr_bcc", "addr_reply"]),
 
@@ -511,13 +507,8 @@ nsAbAutoCompleteSearch.prototype = {
   },
 
   stopSearch() {},
 
   // nsISupports
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAutoCompleteSearch]),
 };
-
-// Module
-
-var components = [nsAbAutoCompleteSearch];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
rename from mailnews/addrbook/src/nsAbLDAPAttributeMap.js
rename to mailnews/addrbook/src/AbLDAPAttributeMap.jsm
--- a/mailnews/addrbook/src/nsAbLDAPAttributeMap.js
+++ b/mailnews/addrbook/src/AbLDAPAttributeMap.jsm
@@ -1,32 +1,22 @@
 /* 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/. */
 
-var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["AbLDAPAttributeMap", "AbLDAPAttributeMapService"];
 
-var NS_ABLDAPATTRIBUTEMAP_CID = Components.ID(
-  "{127b341a-bdda-4270-85e1-edff569a9b85}"
-);
-var NS_ABLDAPATTRIBUTEMAPSERVICE_CID = Components.ID(
-  "{4ed7d5e1-8800-40da-9e78-c4f509d7ac5e}"
-);
+var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-function nsAbLDAPAttributeMap() {
+function AbLDAPAttributeMap() {
   this.mPropertyMap = {};
   this.mAttrMap = {};
 }
 
-nsAbLDAPAttributeMap.prototype = {
-  classID: NS_ABLDAPATTRIBUTEMAP_CID,
-
+AbLDAPAttributeMap.prototype = {
   getAttributeList(aProperty) {
     if (!(aProperty in this.mPropertyMap)) {
       return null;
     }
 
     // return the joined list
     return this.mPropertyMap[aProperty].join(",");
   },
@@ -187,40 +177,33 @@ nsAbLDAPAttributeMap.prototype = {
         attrsSeen.push(attr);
       }
     }
   },
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAbLDAPAttributeMap]),
 };
 
-function nsAbLDAPAttributeMapService() {}
+function AbLDAPAttributeMapService() {}
 
-nsAbLDAPAttributeMapService.prototype = {
-  classID: NS_ABLDAPATTRIBUTEMAPSERVICE_CID,
-
+AbLDAPAttributeMapService.prototype = {
   mAttrMaps: {},
 
   getMapForPrefBranch(aPrefBranchName) {
     // if we've already got this map, return it
     if (aPrefBranchName in this.mAttrMaps) {
       return this.mAttrMaps[aPrefBranchName];
     }
 
     // otherwise, try and create it
-    var attrMap = new nsAbLDAPAttributeMap();
+    var attrMap = new AbLDAPAttributeMap();
     attrMap.setFromPrefs("ldap_2.servers.default.attrmap");
     attrMap.setFromPrefs(aPrefBranchName + ".attrmap");
 
     // cache
     this.mAttrMaps[aPrefBranchName] = attrMap;
 
     // and return
     return attrMap;
   },
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAbLDAPAttributeMapService]),
 };
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([
-  nsAbLDAPAttributeMap,
-  nsAbLDAPAttributeMapService,
-]);
rename from mailnews/addrbook/src/nsAbLDAPAutoCompleteSearch.js
rename to mailnews/addrbook/src/AbLDAPAutoCompleteSearch.jsm
--- a/mailnews/addrbook/src/nsAbLDAPAutoCompleteSearch.js
+++ b/mailnews/addrbook/src/AbLDAPAutoCompleteSearch.jsm
@@ -1,20 +1,19 @@
 /* -*- Mode: Java; 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/. */
 
+var EXPORTED_SYMBOLS = ["AbLDAPAutoCompleteSearch"];
+
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 var ACR = Ci.nsIAutoCompleteResult;
 var nsIAbAutoCompleteResult = Ci.nsIAbAutoCompleteResult;
 var nsIAbDirectoryQueryResultListener = Ci.nsIAbDirectoryQueryResultListener;
 
 // nsAbLDAPAutoCompleteResult
 // Derived from nsIAbAutoCompleteResult, provides a LDAP specific result
 // implementation.
@@ -75,25 +74,22 @@ nsAbLDAPAutoCompleteResult.prototype = {
     return this._searchResults[aIndex].card;
   },
 
   // nsISupports
 
   QueryInterface: ChromeUtils.generateQI([ACR, nsIAbAutoCompleteResult]),
 };
 
-function nsAbLDAPAutoCompleteSearch() {
+function AbLDAPAutoCompleteSearch() {
   Services.obs.addObserver(this, "quit-application");
   this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 }
 
-nsAbLDAPAutoCompleteSearch.prototype = {
-  // For component registration
-  classID: Components.ID("227e6482-fe9f-441f-9b7d-7b60375e7449"),
-
+AbLDAPAutoCompleteSearch.prototype = {
   // A short-lived LDAP directory cache.
   // To avoid recreating components as the user completes, we maintain the most
   // recently used address book, nsAbLDAPDirectoryQuery and search context.
   // However the cache is discarded if it has not been used for a minute.
   // This is done to avoid problems with LDAP sessions timing out and hanging.
   _query: null,
   _book: null,
   _attributes: null,
@@ -354,14 +350,8 @@ nsAbLDAPAutoCompleteSearch.prototype = {
   // nsISupports
 
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsIObserver,
     Ci.nsIAutoCompleteSearch,
     Ci.nsIAbDirSearchListener,
   ]),
 };
-
-// Module
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([
-  nsAbLDAPAutoCompleteSearch,
-]);
new file mode 100644
--- /dev/null
+++ b/mailnews/addrbook/src/components.conf
@@ -0,0 +1,38 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{5b259db2-e451-4de9-8a6f-cfba91402973}',
+    'contract_ids': ['@mozilla.org/autocomplete/search;1?name=mydomain'],
+    'jsm': 'resource:///modules/AbAutoCompleteMyDomain.jsm',
+    'constructor': 'AbAutoCompleteMyDomain',
+  },
+  {
+    'cid': '{2f946df9-114c-41fe-8899-81f10daf4f0c}',
+    'contract_ids': ['@mozilla.org/autocomplete/search;1?name=addrbook'],
+    'jsm': 'resource:///modules/AbAutoCompleteSearch.jsm',
+    'constructor': 'AbAutoCompleteSearch',
+  },
+  {
+    'cid': '{127b341a-bdda-4270-85e1-edff569a9b85}',
+    'contract_ids': ['@mozilla.org/addressbook/ldap-attribute-map;1'],
+    'jsm': 'resource:///modules/AbLDAPAttributeMap.jsm',
+    'constructor': 'AbLDAPAttributeMap',
+  },
+  {
+    'cid': '{4ed7d5e1-8800-40da-9e78-c4f509d7ac5e}',
+    'contract_ids': ['@mozilla.org/addressbook/ldap-attribute-map-service;1'],
+    'jsm': 'resource:///modules/AbLDAPAttributeMap.jsm',
+    'constructor': 'AbLDAPAttributeMapService',
+  },
+  {
+    'cid': '{227e6482-fe9f-441f-9b7d-7b60375e7449}',
+    'contract_ids': ['@mozilla.org/autocomplete/search;1?name=ldap'],
+    'jsm': 'resource:///modules/AbLDAPAutoCompleteSearch.jsm',
+    'constructor': 'AbLDAPAutoCompleteSearch',
+  },
+]
--- a/mailnews/addrbook/src/moz.build
+++ b/mailnews/addrbook/src/moz.build
@@ -69,25 +69,25 @@ if CONFIG['MOZ_LDAP_XPCOM']:
         'nsAbLDAPReplicationQuery.cpp',
         'nsAbLDAPReplicationService.cpp',
     ]
     # XXX These files are not being built as they don't work. Bug 311632 should
     # fix them.
     # nsAbLDAPChangeLogQuery.cpp
     # nsAbLDAPChangeLogData.cpp
 
-    EXTRA_COMPONENTS += [
-        'nsAbLDAPAutoCompleteSearch.js',
+    EXTRA_JS_MODULES += [
+        'AbLDAPAutoCompleteSearch.jsm',
     ]
 
     DEFINES['MOZ_LDAP_XPCOM'] = True
 
-EXTRA_COMPONENTS += [
-    'nsAbAutoCompleteMyDomain.js',
-    'nsAbAutoCompleteSearch.js',
-    'nsAbLDAPAttributeMap.js',
-]
-
-EXTRA_PP_COMPONENTS += [
-    'nsAddrbook.manifest',
+EXTRA_JS_MODULES += [
+    'AbAutoCompleteMyDomain.jsm',
+    'AbAutoCompleteSearch.jsm',
+    'AbLDAPAttributeMap.jsm',
 ]
 
 FINAL_LIBRARY = 'mail'
+
+XPCOM_MANIFESTS += [
+    'components.conf',
+]
deleted file mode 100644
--- a/mailnews/addrbook/src/nsAddrbook.manifest
+++ /dev/null
@@ -1,12 +0,0 @@
-component {5b259db2-e451-4de9-8a6f-cfba91402973} nsAbAutoCompleteMyDomain.js
-contract @mozilla.org/autocomplete/search;1?name=mydomain {5b259db2-e451-4de9-8a6f-cfba91402973}
-component {2f946df9-114c-41fe-8899-81f10daf4f0c} nsAbAutoCompleteSearch.js
-contract @mozilla.org/autocomplete/search;1?name=addrbook {2f946df9-114c-41fe-8899-81f10daf4f0c}
-component {127b341a-bdda-4270-85e1-edff569a9b85} nsAbLDAPAttributeMap.js
-contract @mozilla.org/addressbook/ldap-attribute-map;1 {127b341a-bdda-4270-85e1-edff569a9b85}
-component {4ed7d5e1-8800-40da-9e78-c4f509d7ac5e} nsAbLDAPAttributeMap.js
-contract @mozilla.org/addressbook/ldap-attribute-map-service;1 {4ed7d5e1-8800-40da-9e78-c4f509d7ac5e}
-#ifdef MOZ_LDAP_XPCOM
-component {227e6482-fe9f-441f-9b7d-7b60375e7449} nsAbLDAPAutoCompleteSearch.js
-contract @mozilla.org/autocomplete/search;1?name=ldap {227e6482-fe9f-441f-9b7d-7b60375e7449}
-#endif
\ No newline at end of file
rename from mailnews/base/search/src/nsMsgTraitService.js
rename to mailnews/base/search/src/MsgTraitService.jsm
--- a/mailnews/base/search/src/nsMsgTraitService.js
+++ b/mailnews/base/search/src/MsgTraitService.jsm
@@ -1,16 +1,15 @@
 /* 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/. */
 
+var EXPORTED_SYMBOLS = ["MsgTraitService"];
+
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 // local static variables
 
 var _lastIndex = 0; // the first index will be one
 var _traits = {};
 
 var traitsBranch = Services.prefs.getBranch("mailnews.traits.");
 
@@ -18,22 +17,20 @@ function _registerTrait(aId, aIndex) {
   var trait = {};
   trait.enabled = false;
   trait.name = "";
   trait.antiId = "";
   trait.index = aIndex;
   _traits[aId] = trait;
 }
 
-function nsMsgTraitService() {}
+function MsgTraitService() {}
 
-nsMsgTraitService.prototype = {
+MsgTraitService.prototype = {
   // Component setup
-  classID: Components.ID("{A2E95F4F-DA72-4a41-9493-661AD353C00A}"),
-
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgTraitService]),
 
   // nsIMsgTraitService implementation
 
   get lastIndex() {
     return _lastIndex;
   },
 
@@ -198,11 +195,8 @@ function _init() {
       _lastIndex = index;
     }
   }
 
   // for (traitId in _traits)
   //  dump("\nindex of " + traitId + " is " + _traits[traitId].index);
   // dump("\n");
 }
-
-var components = [nsMsgTraitService];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/base/search/src/components.conf
@@ -0,0 +1,14 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{A2E95F4F-DA72-4a41-9493-661AD353C00A}',
+    'contract_ids': ['@mozilla.org/msg-trait-service;1'],
+    'jsm': 'resource:///modules/MsgTraitService.jsm',
+    'constructor': 'MsgTraitService',
+  },
+]
--- a/mailnews/base/search/src/moz.build
+++ b/mailnews/base/search/src/moz.build
@@ -12,23 +12,23 @@ SOURCES += [
     'nsMsgLocalSearch.cpp',
     'nsMsgSearchAdapter.cpp',
     'nsMsgSearchNews.cpp',
     'nsMsgSearchSession.cpp',
     'nsMsgSearchTerm.cpp',
     'nsMsgSearchValue.cpp',
 ]
 
-EXTRA_COMPONENTS += [
-    'nsMsgTraitService.js',
-    'nsMsgTraitService.manifest',
+EXTRA_JS_MODULES += [
+    'MsgTraitService.jsm',
+    'PeriodicFilterManager.jsm',
 ]
 
-EXTRA_JS_MODULES += [
-    'PeriodicFilterManager.jsm',
+XPCOM_MANIFESTS += [
+    'components.conf',
 ]
 
 FINAL_LIBRARY = 'mail'
 
 FINAL_TARGET_FILES.isp += [
     'Bogofilter.sfd',
     'DSPAM.sfd',
     'POPFile.sfd',
deleted file mode 100644
--- a/mailnews/base/search/src/nsMsgTraitService.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {A2E95F4F-DA72-4a41-9493-661AD353C00A} nsMsgTraitService.js
-contract @mozilla.org/msg-trait-service;1 {A2E95F4F-DA72-4a41-9493-661AD353C00A}
rename from mailnews/base/src/folderLookupService.js
rename to mailnews/base/src/FolderLookupService.jsm
--- a/mailnews/base/src/folderLookupService.js
+++ b/mailnews/base/src/FolderLookupService.jsm
@@ -3,39 +3,36 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * This module implements the folder lookup service (nsIFolderLookupService).
  */
 
 "use strict";
 
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["FolderLookupService"];
 
 // This ensures that the service is only created once.
 var gCreated = false;
 
 /**
- * folderLookupService maintains an index of folders and provides
+ * FolderLookupService maintains an index of folders and provides
  * lookup by folder URI.
  * @class
  */
-function folderLookupService() {
+function FolderLookupService() {
   if (gCreated) {
     throw Cr.NS_ERROR_ALREADY_INITIALIZED;
   }
   this._map = new Map();
   gCreated = true;
 }
 
-folderLookupService.prototype = {
+FolderLookupService.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIFolderLookupService]),
-  classID: Components.ID("{a30be08c-afc8-4fed-9af7-79778a23db23}"),
 
   /**
    * Fetch the folder corresponding to the given URI.
    * Will only return folders which already exist and have a parent. If this
    * not the case then null is returned.
    *
    * @param {String} uri - URI of folder to get.
    * @returns {nsIMsgFolder|null}
@@ -141,10 +138,8 @@ folderLookupService.prototype = {
   _isValidFolder(folder) {
     try {
       return folder.parent != null || folder.rootFolder == folder;
     } catch (e) {
       return false;
     }
   },
 };
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([folderLookupService]);
rename from mailnews/base/src/nsMailNewsCommandLineHandler.js
rename to mailnews/base/src/MailNewsCommandLineHandler.jsm
--- a/mailnews/base/src/nsMailNewsCommandLineHandler.js
+++ b/mailnews/base/src/MailNewsCommandLineHandler.jsm
@@ -1,30 +1,24 @@
 /* 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/. */
 
+var EXPORTED_SYMBOLS = ["MailNewsCommandLineHandler"];
+
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 var { AppConstants } = ChromeUtils.import(
   "resource://gre/modules/AppConstants.jsm"
 );
 
 var MAPI_STARTUP_ARG = "MapiStartup";
 var MESSAGE_ID_PARAM = "?messageid=";
 
-var CMDLINEHANDLER_CID = Components.ID(
-  "{2f86d554-f9d9-4e76-8eb7-243f047333ee}"
-);
-var CMDLINEHANDLER_CONTRACTID =
-  "@mozilla.org/commandlinehandler/general-startup;1?type=mail";
-
-var nsMailNewsCommandLineHandler = {
+function MailNewsCommandLineHandler() {}
+MailNewsCommandLineHandler.prototype = {
   get _messenger() {
     delete this._messenger;
     return (this._messenger = Cc["@mozilla.org/messenger;1"].createInstance(
       Ci.nsIMessenger
     ));
   },
 
   /* nsICommandLineHandler */
@@ -158,23 +152,11 @@ var nsMailNewsCommandLineHandler = {
     }
 
     return this.QueryInterface(iid);
   },
 
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsICommandLineHandler,
     Ci.nsIFactory,
+    Ci.nsIModule,
   ]),
 };
-
-function mailNewsCommandLineHandlerModule() {}
-mailNewsCommandLineHandlerModule.prototype = {
-  // XPCOM registration
-  classID: CMDLINEHANDLER_CID,
-
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIModule]),
-
-  _xpcom_factory: nsMailNewsCommandLineHandler,
-};
-
-var components = [mailNewsCommandLineHandlerModule];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
rename from mailnews/base/src/newMailNotificationService.js
rename to mailnews/base/src/MailNotificationService.jsm
--- a/mailnews/base/src/newMailNotificationService.js
+++ b/mailnews/base/src/MailNotificationService.jsm
@@ -7,27 +7,26 @@
  * platform-specific notification modules
  *
  * Logging for this module uses the TB version of log4moz. Default logging is at the Warn
  * level. Other possibly interesting messages are at Error, Info and Debug. To configure, set the
  * preferences "mail.notification.logging.console" (for the error console) or
  * "mail.notification.logging.dump" (for stderr) to the string indicating the level you want.
  */
 
+var EXPORTED_SYMBOLS = ["NewMailNotificationService"];
+
 var { Log4Moz } = ChromeUtils.import("resource:///modules/gloda/log4moz.js");
 var { fixIterator } = ChromeUtils.import(
   "resource:///modules/iteratorUtils.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 var NMNS = Ci.mozINewMailNotificationService;
 
 var countInboxesPref = "mail.notification.count.inbox_only";
 // Old name for pref
 var countNewMessagesPref = "mail.biff.use_new_count_in_mac_dock";
 // When we go cross-platform we should migrate to
 // const countNewMessagesPref = "mail.notification.count.new";
@@ -55,27 +54,21 @@ function NewMailNotificationService() {
     Log4Moz.Level.Warn
   );
 
   // Listen for mail-startup-done to do the rest of our setup after folders are initialized
   Services.obs.addObserver(this, "mail-startup-done");
 }
 
 NewMailNotificationService.prototype = {
-  classDescription: "Maintain counts of new and unread messages",
-  classID: Components.ID("{740880E6-E299-4165-B82F-DF1DCAB3AE22}"),
-  contractID: "@mozilla.org/newMailNotificationService;1",
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsIObserver,
     Ci.nsIFolderListener,
     Ci.mozINewMailNotificationService,
   ]),
-  _xpcom_factory: XPCOMUtils.generateSingletonFactory(
-    NewMailNotificationService
-  ),
 
   _mUnreadCount: 0,
   _mNewCount: 0,
   _listeners: null,
   _log: null,
 
   get countNew() {
     return getBoolPref(countNewMessagesPref, false);
@@ -495,12 +488,8 @@ NewMailNotificationService.prototype = {
     for (let i = 0; i < list.length; i++) {
       this._log.debug(
         "NMNS_notifyListeners " + flag + " " + func + " " + value
       );
       list[i][func](value);
     }
   },
 };
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([
-  NewMailNotificationService,
-]);
rename from mailnews/base/src/msgAsyncPrompter.js
rename to mailnews/base/src/MsgAsyncPrompter.jsm
--- a/mailnews/base/src/msgAsyncPrompter.js
+++ b/mailnews/base/src/MsgAsyncPrompter.jsm
@@ -1,19 +1,18 @@
 /* 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/. */
 
+var EXPORTED_SYMBOLS = ["MsgAsyncPrompter"];
+
 var { Deprecated } = ChromeUtils.import(
   "resource://gre/modules/Deprecated.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 var { Log4Moz } = ChromeUtils.import("resource:///modules/gloda/log4moz.js");
 
 function runnablePrompter(asyncPrompter, hashKey) {
   this._asyncPrompter = asyncPrompter;
   this._hashKey = hashKey;
 }
 
 runnablePrompter.prototype = {
@@ -74,33 +73,32 @@ runnablePrompter.prototype = {
 
     this._asyncPrompter._log.debug(
       "Finished running prompter for " + this._hashKey
     );
     this._asyncPrompter._doAsyncAuthPrompt();
   },
 };
 
-function msgAsyncPrompter() {
+function MsgAsyncPrompter() {
   this._pendingPrompts = {};
   // By default, only log warnings to the error console and errors to dump().
   // You can use the preferences:
   //   msgAsyncPrompter.logging.console
   //   msgAsyncPrompter.logging.dump
   // To change this up.  Values should be one of:
   //   Fatal/Error/Warn/Info/Config/Debug/Trace/All
   this._log = Log4Moz.getConfiguredLogger(
     "msgAsyncPrompter",
     Log4Moz.Level.Warn,
     Log4Moz.Level.Warn
   );
 }
 
-msgAsyncPrompter.prototype = {
-  classID: Components.ID("{49b04761-23dd-45d7-903d-619418a4d319}"),
+MsgAsyncPrompter.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgAsyncPrompter]),
 
   _pendingPrompts: null,
   _asyncPromptInProgress: 0,
   _log: null,
 
   queueAsyncAuthPrompt(aKey, aJumpQueue, aCaller) {
     if (aKey in this._pendingPrompts) {
@@ -151,11 +149,8 @@ msgAsyncPrompter.prototype = {
     this._asyncPromptInProgress++;
 
     this._log.debug("Dispatching runnablePrompter for " + hashKey);
 
     let runnable = new runnablePrompter(this, hashKey);
     Services.tm.mainThread.dispatch(runnable, Ci.nsIThread.DISPATCH_NORMAL);
   },
 };
-
-var components = [msgAsyncPrompter];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
rename from mailnews/base/src/msgOAuth2Module.js
rename to mailnews/base/src/OAuth2Module.jsm
--- a/mailnews/base/src/msgOAuth2Module.js
+++ b/mailnews/base/src/OAuth2Module.jsm
@@ -1,30 +1,28 @@
 /* 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/. */
 
 "use strict";
 
+var EXPORTED_SYMBOLS = ["OAuth2Module"];
+
 var { OAuth2 } = ChromeUtils.import("resource:///modules/OAuth2.jsm");
 var { OAuth2Providers } = ChromeUtils.import(
   "resource:///modules/OAuth2Providers.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 function OAuth2Module() {
   this._refreshToken = "";
 }
 OAuth2Module.prototype = {
   // XPCOM registration stuff
   QueryInterface: ChromeUtils.generateQI([Ci.msgIOAuth2Module]),
-  classID: Components.ID("{b63d8e4c-bf60-439b-be0e-7c9f67291042}"),
 
   _loadOAuthClientDetails(aIssuer) {
     let details = OAuth2Providers.getIssuerDetails(aIssuer);
     if (details) {
       [this._appKey, this._appSecret, this._authURI, this._tokenURI] = details;
     } else {
       throw Cr.NS_ERROR_INVALID_ARGUMENT;
     }
@@ -187,10 +185,8 @@ OAuth2Module.prototype = {
 
     let asyncprompter = Cc[
       "@mozilla.org/messenger/msgAsyncPrompter;1"
     ].getService(Ci.nsIMsgAsyncPrompter);
     let promptkey = this._loginUrl + "/" + this._username;
     asyncprompter.queueAsyncAuthPrompt(promptkey, false, promptlistener);
   },
 };
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([OAuth2Module]);
new file mode 100644
--- /dev/null
+++ b/mailnews/base/src/components.conf
@@ -0,0 +1,40 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{a30be08c-afc8-4fed-9af7-79778a23db23}',
+    'contract_ids': ['@mozilla.org/mail/folder-lookup;1'],
+    'jsm': 'resource:///modules/FolderLookupService.jsm',
+    'constructor': 'FolderLookupService',
+  },
+  {
+    'cid': '{49b04761-23dd-45d7-903d-619418a4d319}',
+    'contract_ids': ['@mozilla.org/messenger/msgAsyncPrompter;1'],
+    'jsm': 'resource:///modules/MsgAsyncPrompter.jsm',
+    'constructor': 'MsgAsyncPrompter',
+  },
+  {
+    'cid': '{b63d8e4c-bf60-439b-be0e-7c9f67291042}',
+    'contract_ids': ['@mozilla.org/mail/oauth2-module;1'],
+    'jsm': 'resource:///modules/OAuth2Module.jsm',
+    'constructor': 'OAuth2Module',
+  },
+  {
+    'cid': '{740880E6-E299-4165-B82F-DF1DCAB3AE22}',
+    'contract_ids': ['@mozilla.org/newMailNotificationService;1'],
+    'jsm': 'resource:///modules/MailNotificationService.jsm',
+    'constructor': 'NewMailNotificationService',
+    'categories': {'profile-after-change': 'NewMailNotificationService'},
+  },
+  {
+    'cid': '{2f86d554-f9d9-4e76-8eb7-243f047333ee}',
+    'contract_ids': ['@mozilla.org/commandlinehandler/general-startup;1?type=mail'],
+    'jsm': 'resource:///modules/MailNewsCommandLineHandler.jsm',
+    'constructor': 'MailNewsCommandLineHandler',
+    'categories': {'command-line-handler': 'm-mail'},
+  },
+]
--- a/mailnews/base/src/moz.build
+++ b/mailnews/base/src/moz.build
@@ -52,28 +52,27 @@ if CONFIG['NS_PRINTING']:
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += ['nsMessengerWinIntegration.cpp']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
     SOURCES += ['nsMessengerUnixIntegration.cpp']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     SOURCES += ['nsMessengerOSXIntegration.mm']
 
-EXTRA_COMPONENTS += [
-    'folderLookupService.js',
-    'msgAsyncPrompter.js',
-    'msgBase.manifest',
-    'msgOAuth2Module.js',
-    'newMailNotificationService.js',
-    'nsMailNewsCommandLineHandler.js',
-]
-
 EXTRA_JS_MODULES += [
+    'FolderLookupService.jsm',
+    'MailNewsCommandLineHandler.jsm',
+    'MailNotificationService.jsm',
+    'MsgAsyncPrompter.jsm',
+    'OAuth2Module.jsm',
     'virtualFolderWrapper.js',
 ]
 LOCAL_INCLUDES += [
   '/%s/dom/base' % CONFIG['mozreltopsrcdir'],
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'mail'
 
+XPCOM_MANIFESTS += [
+    'components.conf',
+]
deleted file mode 100644
--- a/mailnews/base/src/msgBase.manifest
+++ /dev/null
@@ -1,12 +0,0 @@
-component {49b04761-23dd-45d7-903d-619418a4d319} msgAsyncPrompter.js
-contract @mozilla.org/messenger/msgAsyncPrompter;1 {49b04761-23dd-45d7-903d-619418a4d319}
-component {2f86d554-f9d9-4e76-8eb7-243f047333ee} nsMailNewsCommandLineHandler.js
-contract @mozilla.org/commandlinehandler/general-startup;1?type=mail {2f86d554-f9d9-4e76-8eb7-243f047333ee}
-category command-line-handler m-mail @mozilla.org/commandlinehandler/general-startup;1?type=mail
-component {740880E6-E299-4165-B82F-DF1DCAB3AE22} newMailNotificationService.js
-contract @mozilla.org/newMailNotificationService;1 {740880E6-E299-4165-B82F-DF1DCAB3AE22}
-category profile-after-change NewMailNotificationService @mozilla.org/newMailNotificationService;1 
-component {a30be08c-afc8-4fed-9af7-79778a23db23} folderLookupService.js
-contract @mozilla.org/mail/folder-lookup;1 {a30be08c-afc8-4fed-9af7-79778a23db23}
-component {b63d8e4c-bf60-439b-be0e-7c9f67291042} msgOAuth2Module.js
-contract @mozilla.org/mail/oauth2-module;1 {b63d8e4c-bf60-439b-be0e-7c9f67291042}
rename from mailnews/compose/src/nsSMTPProtocolHandler.js
rename to mailnews/compose/src/SMTPProtocolHandler.jsm
--- a/mailnews/compose/src/nsSMTPProtocolHandler.js
+++ b/mailnews/compose/src/SMTPProtocolHandler.jsm
@@ -1,22 +1,18 @@
 /* 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/. */
 
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["SMTPProtocolHandler", "SMTPSProtocolHandler"];
 
-var kNetworkProtocolCIDPrefix = "@mozilla.org/network/protocol;1?name=";
 var nsIProtocolHandler = Ci.nsIProtocolHandler;
 
 function makeProtocolHandler(aProtocol, aDefaultPort, aClassID) {
   return {
-    classID: Components.ID(aClassID),
     QueryInterface: ChromeUtils.generateQI([nsIProtocolHandler]),
 
     scheme: aProtocol,
     defaultPort: aDefaultPort,
     protocolFlags:
       nsIProtocolHandler.URI_NORELATIVE |
       nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
       nsIProtocolHandler.URI_NON_PERSISTABLE |
@@ -28,26 +24,23 @@ function makeProtocolHandler(aProtocol, 
     },
 
     allowPort(port, scheme) {
       return port == aDefaultPort;
     },
   };
 }
 
-function nsSMTPProtocolHandler() {}
+function SMTPProtocolHandler() {}
 
-nsSMTPProtocolHandler.prototype = makeProtocolHandler(
+SMTPProtocolHandler.prototype = makeProtocolHandler(
   "smtp",
   Ci.nsISmtpUrl.DEFAULT_SMTP_PORT,
   "b14c2b67-8680-4c11-8d63-9403c7d4f757"
 );
 
-function nsSMTPSProtocolHandler() {}
+function SMTPSProtocolHandler() {}
 
-nsSMTPSProtocolHandler.prototype = makeProtocolHandler(
+SMTPSProtocolHandler.prototype = makeProtocolHandler(
   "smtps",
   Ci.nsISmtpUrl.DEFAULT_SMTPS_PORT,
   "057d0997-9e3a-411e-b4ee-2602f53fe05f"
 );
-
-var components = [nsSMTPProtocolHandler, nsSMTPSProtocolHandler];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/compose/src/components.conf
@@ -0,0 +1,20 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{b14c2b67-8680-4c11-8d63-9403c7d4f757}',
+    'contract_ids': ['@mozilla.org/network/protocol;1?name=smtp'],
+    'jsm': 'resource:///modules/SMTPProtocolHandler.jsm',
+    'constructor': 'SMTPProtocolHandler',
+  },
+  {
+    'cid': '{057d0997-9e3a-411e-b4ee-2602f53fe05f}',
+    'contract_ids': ['@mozilla.org/network/protocol;1?name=smtps'],
+    'jsm': 'resource:///modules/SMTPProtocolHandler.jsm',
+    'constructor': 'SMTPSProtocolHandler',
+  },
+]
--- a/mailnews/compose/src/moz.build
+++ b/mailnews/compose/src/moz.build
@@ -41,22 +41,25 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'nsMsgAppleDoubleEncode.cpp',
         'nsMsgAppleEncode.cpp',
     ]
     EXPORTS += [
         'nsMsgAppleCodes.h',
         'nsMsgAppleDouble.h',
     ]
 
-EXTRA_COMPONENTS += [
-    'nsSMTPProtocolHandler.js',
-    'nsSMTPProtocolHandler.manifest',
-]
-
 LOCAL_INCLUDES += [
   '/%s/dom/base' % CONFIG['mozreltopsrcdir'],
 ]
 
 FINAL_LIBRARY = 'mail'
 
 # clang-cl rightly complains about switch on nsresult.
 if CONFIG['CC_TYPE'] == 'clang-cl':
     CXXFLAGS += ['-Wno-switch']
+
+EXTRA_JS_MODULES += [
+    'SMTPProtocolHandler.jsm',
+]
+
+XPCOM_MANIFESTS += [
+    'components.conf',
+]
deleted file mode 100644
--- a/mailnews/compose/src/nsSMTPProtocolHandler.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-component {b14c2b67-8680-4c11-8d63-9403c7d4f757} nsSMTPProtocolHandler.js
-contract @mozilla.org/network/protocol;1?name=smtp {b14c2b67-8680-4c11-8d63-9403c7d4f757}
-component {057d0997-9e3a-411e-b4ee-2602f53fe05f} nsSMTPProtocolHandler.js
-contract @mozilla.org/network/protocol;1?name=smtps {057d0997-9e3a-411e-b4ee-2602f53fe05f}
rename from mailnews/db/gloda/components/glautocomp.js
rename to mailnews/db/gloda/components/GlodaAutoComplete.jsm
--- a/mailnews/db/gloda/components/glautocomp.js
+++ b/mailnews/db/gloda/components/GlodaAutoComplete.jsm
@@ -4,23 +4,23 @@
 
 /**
  * glautocomp.js decides which autocomplete item type to
  * use when one enters text in global search box. There are
  * following types of autocomplete item: gloda-contact-chunk-richlistitem,
  * gloda-fulltext-all-richlistitem, gloda-fulltext-single-richlistitem, gloda-multi-richlistitem,
  * gloda-single-identity-richlistitem, gloda-single-tag-richlistitem.
  */
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+
+var EXPORTED_SYMBOLS = ["GlodaAutoComplete"];
+
 var { logException } = ChromeUtils.import("resource:///modules/errUtils.js");
 
 var Gloda = null;
-var GlodaUtils = null;
+var GlodaUtils = null; // eslint-disable-line no-unused-vars
 var MultiSuffixTree = null;
 var TagNoun = null;
 var FreeTagNoun = null;
 
 function ResultRowFullText(aItem, words, typeForStyle) {
   this.item = aItem;
   this.words = words;
   this.typeForStyle = "gloda-fulltext-" + typeForStyle + "-richlistitem";
@@ -501,19 +501,19 @@ FullTextCompleter.prototype = {
     } else {
       aResult.addRows([new ResultRowFullText(aSearchString, terms, "all")]);
     }
 
     return false; // no async mechanism that will add new rows
   },
 };
 
-var LOG;
+var LOG; // eslint-disable-line no-unused-vars
 
-function nsAutoCompleteGloda() {
+function GlodaAutoComplete() {
   this.wrappedJSObject = this;
   try {
     // set up our awesome globals!
     if (Gloda === null) {
       let loadNS = ChromeUtils.import("resource:///modules/gloda/public.js");
       Gloda = loadNS.Gloda;
 
       loadNS = ChromeUtils.import("resource:///modules/gloda/utils.js");
@@ -536,18 +536,17 @@ function nsAutoCompleteGloda() {
     this.completers.push(new ContactIdentityCompleter()); // potentially async.
     this.completers.push(new ContactTagCompleter()); // not async.
     this.completers.push(new MessageTagCompleter()); // not async.
   } catch (e) {
     logException(e);
   }
 }
 
-nsAutoCompleteGloda.prototype = {
-  classID: Components.ID("{3bbe4d77-3f70-4252-9500-bc00c26f476d}"),
+GlodaAutoComplete.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAutoCompleteSearch]),
 
   startSearch(aString, aParam, aResult, aListener) {
     try {
       let result = new nsAutoCompleteGlodaResult(aListener, this, aString);
       // save this for hacky access to the search.  I somewhat suspect we simply
       //  should not be using the formal autocomplete mechanism at all.
       // Used in glodacomplete.xml.
@@ -574,11 +573,8 @@ nsAutoCompleteGloda.prototype = {
       logException(e);
     }
   },
 
   stopSearch() {
     this.curResult.active = false;
   },
 };
-
-var components = [nsAutoCompleteGloda];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
rename from mailnews/db/gloda/components/jsmimeemitter.js
rename to mailnews/db/gloda/components/MimeMessageEmitter.jsm
--- a/mailnews/db/gloda/components/jsmimeemitter.js
+++ b/mailnews/db/gloda/components/MimeMessageEmitter.jsm
@@ -1,15 +1,13 @@
 /* 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/. */
 
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["MimeMessageEmitter"];
 
 var kStateUnknown = 0;
 var kStateInHeaders = 1;
 var kStateInBody = 2;
 var kStateInAttachment = 3;
 
 /**
  * When the saneBodySize flag is active, limit body parts to at most this many
@@ -63,18 +61,16 @@ function MimeMessageEmitter() {
   this._state = kStateUnknown;
 
   this._writeBody = false;
 }
 
 var deathToNewlines = /\n/g;
 
 MimeMessageEmitter.prototype = {
-  classID: Components.ID("{8cddbbbc-7ced-46b0-a936-8cddd1928c24}"),
-
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMimeEmitter]),
 
   initialize(aUrl, aChannel, aFormat) {
     this._url = aUrl;
     this._curPart = new this._mimeMsg.MimeMessage();
     // the partName is intentionally ""!  not a place-holder!
     this._curPart.partName = "";
     this._curAttachment = "";
@@ -498,11 +494,8 @@ MimeMessageEmitter.prototype = {
     aOutAmountWritten.value = aSize;
   },
 
   // (string writing)
   utilityWrite(aBuf) {
     this.write(aBuf, aBuf.length, {});
   },
 };
-
-var components = [MimeMessageEmitter];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/db/gloda/components/components.conf
@@ -0,0 +1,21 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{3bbe4d77-3f70-4252-9500-bc00c26f476d}',
+    'contract_ids': ['@mozilla.org/autocomplete/search;1?name=gloda'],
+    'jsm': 'resource:///modules/GlodaAutoComplete.jsm',
+    'constructor': 'GlodaAutoComplete',
+  },
+  {
+    'cid': '{8cddbbbc-7ced-46b0-a936-8cddd1928c24}',
+    'contract_ids': ['@mozilla.org/gloda/jsmimeemitter;1',],
+    'jsm': 'resource:///modules/MimeMessageEmitter.jsm',
+    'constructor': 'MimeMessageEmitter',
+    'categories': {'mime-emitter': '@mozilla.org/messenger/mimeemitter;1?type=application/x-js-mime-message'},
+  },
+]
deleted file mode 100644
--- a/mailnews/db/gloda/components/gloda.manifest
+++ /dev/null
@@ -1,5 +0,0 @@
-component {3bbe4d77-3f70-4252-9500-bc00c26f476d} glautocomp.js
-contract @mozilla.org/autocomplete/search;1?name=gloda {3bbe4d77-3f70-4252-9500-bc00c26f476d}
-component {8cddbbbc-7ced-46b0-a936-8cddd1928c24} jsmimeemitter.js
-contract @mozilla.org/gloda/jsmimeemitter;1 {8cddbbbc-7ced-46b0-a936-8cddd1928c24}
-category mime-emitter @mozilla.org/messenger/mimeemitter;1?type=application/x-js-mime-message @mozilla.org/gloda/jsmimeemitter;1
--- a/mailnews/db/gloda/components/moz.build
+++ b/mailnews/db/gloda/components/moz.build
@@ -1,11 +1,13 @@
 # vim: set filetype=python:
 # 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/.
 
-EXTRA_COMPONENTS += [
-    'glautocomp.js',
-    'gloda.manifest',
-    'jsmimeemitter.js',
+EXTRA_JS_MODULES += [
+    'GlodaAutoComplete.jsm',
+    'MimeMessageEmitter.jsm',
 ]
 
+XPCOM_MANIFESTS += [
+    'components.conf',
+]
--- a/mailnews/extensions/dsn/moz.build
+++ b/mailnews/extensions/dsn/moz.build
@@ -1,15 +1,18 @@
 # vim: set filetype=python:
 # 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/.
 
-EXTRA_COMPONENTS += [
-    'src/dsn-service.js',
-    'src/dsn-service.manifest',
+EXTRA_JS_MODULES += [
+    'src/DSNService.jsm',
+]
+
+XPCOM_MANIFESTS += [
+    'src/components.conf',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
 JS_PREFERENCE_FILES += [
     'content/dsn.js',
 ]
\ No newline at end of file
rename from mailnews/extensions/dsn/src/dsn-service.js
rename to mailnews/extensions/dsn/src/DSNService.jsm
--- a/mailnews/extensions/dsn/src/dsn-service.js
+++ b/mailnews/extensions/dsn/src/DSNService.jsm
@@ -1,27 +1,21 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["DSNService"];
 
 function DSNService() {}
 
 DSNService.prototype = {
   name: "dsn",
   chromePackageName: "messenger",
   showPanel(server) {
     // don't show the panel for news, rss, or local accounts
     return (
       server.type != "nntp" && server.type != "rss" && server.type != "none"
     );
   },
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgAccountManagerExtension]),
-  classID: Components.ID("{849dab91-9bc9-4508-a0ee-c2453e7c092d}"),
 };
-
-var components = [DSNService];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/extensions/dsn/src/components.conf
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{849dab91-9bc9-4508-a0ee-c2453e7c092d}',
+    'contract_ids': ['@mozilla.org/accountmanager/extension;1?name=dsn'],
+    'jsm': 'resource:///modules/DSNService.jsm',
+    'constructor': 'DSNService',
+    'categories': {'mailnews-accountmanager-extensions': 'dsn-account-manager-extension'},
+  },
+]
deleted file mode 100644
--- a/mailnews/extensions/dsn/src/dsn-service.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {849dab91-9bc9-4508-a0ee-c2453e7c092d} dsn-service.js
-contract @mozilla.org/accountmanager/extension;1?name=dsn {849dab91-9bc9-4508-a0ee-c2453e7c092d}
-category mailnews-accountmanager-extensions dsn-account-manager-extension @mozilla.org/accountmanager/extension;1?name=dsn
rename from mailnews/extensions/mdn/src/mdn-service.js
rename to mailnews/extensions/mdn/src/MDNService.jsm
--- a/mailnews/extensions/mdn/src/mdn-service.js
+++ b/mailnews/extensions/mdn/src/MDNService.jsm
@@ -1,16 +1,14 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["MDNService"];
 
 function MDNService() {}
 
 MDNService.prototype = {
   name: "mdn",
   chromePackageName: "messenger",
   showPanel(server) {
     // don't show the panel for news, rss, im or local accounts
@@ -18,13 +16,9 @@ MDNService.prototype = {
       server.type != "nntp" &&
       server.type != "rss" &&
       server.type != "im" &&
       server.type != "none"
     );
   },
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgAccountManagerExtension]),
-  classID: Components.ID("{e007d92e-1dd1-11b2-a61e-dc962c9b8571}"),
 };
-
-var components = [MDNService];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/extensions/mdn/src/components.conf
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{e007d92e-1dd1-11b2-a61e-dc962c9b8571}',
+    'contract_ids': ['@mozilla.org/accountmanager/extension;1?name=mdn'],
+    'jsm': 'resource:///modules/MDNService.jsm',
+    'constructor': 'MDNService',
+    'categories': {'mailnews-accountmanager-extensions': 'mdn-account-manager-extension'},
+  },
+]
deleted file mode 100644
--- a/mailnews/extensions/mdn/src/mdn-service.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {e007d92e-1dd1-11b2-a61e-dc962c9b8571} mdn-service.js
-contract @mozilla.org/accountmanager/extension;1?name=mdn {e007d92e-1dd1-11b2-a61e-dc962c9b8571}
-category mailnews-accountmanager-extensions mdn-account-manager-extension @mozilla.org/accountmanager/extension;1?name=mdn
--- a/mailnews/extensions/mdn/src/moz.build
+++ b/mailnews/extensions/mdn/src/moz.build
@@ -2,15 +2,18 @@
 # 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/.
 
 SOURCES += [
     'nsMsgMdnGenerator.cpp',
 ]
 
-EXTRA_COMPONENTS += [
-    'mdn-service.js',
-    'mdn-service.manifest',
+EXTRA_JS_MODULES += [
+    'MDNService.jsm',
+]
+
+XPCOM_MANIFESTS += [
+    'components.conf',
 ]
 
 FINAL_LIBRARY = 'mail'
 
new file mode 100644
--- /dev/null
+++ b/mailnews/extensions/newsblog/components.conf
@@ -0,0 +1,21 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{5c124537-adca-4456-b2b5-641ab687d1f6}',
+    'contract_ids': ['@mozilla.org/newsblog-feed-downloader;1'],
+    'jsm': 'resource:///modules/NewsBlog.jsm',
+    'constructor': 'FeedDownloader',
+  },
+  {
+    'cid': '{E109C05F-D304-4ca5-8C44-6DE1BFAF1F74}',
+    'contract_ids': ['@mozilla.org/accountmanager/extension;1?name=newsblog'],
+    'jsm': 'resource:///modules/NewsBlog.jsm',
+    'constructor': 'FeedAcctMgrExtension',
+    'categories': {'mailnews-accountmanager-extensions': 'newsblog'},
+  },
+]
rename from mailnews/extensions/newsblog/js/newsblog.js
rename to mailnews/extensions/newsblog/content/NewsBlog.jsm
--- a/mailnews/extensions/newsblog/js/newsblog.js
+++ b/mailnews/extensions/newsblog/content/NewsBlog.jsm
@@ -1,38 +1,32 @@
 /* -*- Mode: Java; 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/. */
 
+var EXPORTED_SYMBOLS = ["FeedDownloader", "FeedAcctMgrExtension"];
+
 var { FeedUtils } = ChromeUtils.import("resource:///modules/FeedUtils.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 function FeedDownloader() {}
 FeedDownloader.prototype = {
   downloadFeed(aFolder, aUrlListener, aIsBiff, aMsgWindow) {
     FeedUtils.downloadFeed(aFolder, aUrlListener, aIsBiff, aMsgWindow);
   },
   subscribeToFeed(aUrl, aFolder, aMsgWindow) {
     FeedUtils.subscribeToFeed(aUrl, aFolder, aMsgWindow);
   },
   updateSubscriptionsDS(aFolder, aOrigFolder, aAction) {
     FeedUtils.updateSubscriptionsDS(aFolder, aOrigFolder, aAction);
   },
 
-  classID: Components.ID("{5c124537-adca-4456-b2b5-641ab687d1f6}"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsINewsBlogFeedDownloader]),
 };
 
 function FeedAcctMgrExtension() {}
 FeedAcctMgrExtension.prototype = {
   name: "newsblog",
   chromePackageName: "messenger-newsblog",
   showPanel: server => false,
 
-  classID: Components.ID("{E109C05F-D304-4ca5-8C44-6DE1BFAF1F74}"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgAccountManagerExtension]),
 };
-
-var components = [FeedDownloader, FeedAcctMgrExtension];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
deleted file mode 100644
--- a/mailnews/extensions/newsblog/js/newsblog.manifest
+++ /dev/null
@@ -1,5 +0,0 @@
-component {5c124537-adca-4456-b2b5-641ab687d1f6} newsblog.js
-contract @mozilla.org/newsblog-feed-downloader;1 {5c124537-adca-4456-b2b5-641ab687d1f6}
-component {E109C05F-D304-4ca5-8C44-6DE1BFAF1F74} newsblog.js
-contract @mozilla.org/accountmanager/extension;1?name=newsblog {E109C05F-D304-4ca5-8C44-6DE1BFAF1F74}
-category mailnews-accountmanager-extensions newsblog @mozilla.org/accountmanager/extension;1?name=newsblog
--- a/mailnews/extensions/newsblog/moz.build
+++ b/mailnews/extensions/newsblog/moz.build
@@ -1,17 +1,17 @@
 # vim: set filetype=python:
 # 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/.
 
-EXTRA_COMPONENTS += [
-    'js/newsblog.js',
-    'js/newsblog.manifest',
+EXTRA_JS_MODULES += [
+    'content/FeedUtils.jsm',
+    'content/NewsBlog.jsm',
 ]
 
-EXTRA_JS_MODULES += [
-    'content/FeedUtils.jsm',
+XPCOM_MANIFESTS += [
+    'components.conf',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 TEST_DIRS += ['test']
 
rename from mailnews/extensions/offline-startup/js/offlineStartup.js
rename to mailnews/extensions/offline-startup/OfflineStartup.jsm
--- a/mailnews/extensions/offline-startup/js/offlineStartup.js
+++ b/mailnews/extensions/offline-startup/OfflineStartup.jsm
@@ -1,17 +1,16 @@
 /* -*- Mode: Java; 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/. */
 
+var EXPORTED_SYMBOLS = ["OfflineStartup"];
+
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 var kDebug = false;
 var kOfflineStartupPref = "offline.startup_state";
 var kRememberLastState = 0;
 var kAskForOnlineState = 1;
 var kAlwaysOnline = 2;
 var kAlwaysOffline = 3;
 var kAutomatic = 4;
@@ -33,17 +32,18 @@ if (!kDebug) {
 //
 // Check if the user has set the pref to be prompted for
 // online/offline startup mode. If so, prompt the user. Also,
 // check if the user wants to remember their offline state
 // the next time they start up.
 // If the user shutdown offline, and is now starting up in online
 // mode, we will set the boolean pref "mailnews.playback_offline" to true.
 
-var nsOfflineStartup = {
+function OfflineStartup() {}
+OfflineStartup.prototype = {
   onProfileStartup() {
     gDebugLog("onProfileStartup");
 
     if (gStartingUp) {
       gStartingUp = false;
       // if checked, the "work offline" checkbox overrides
       if (Services.io.offline && !Services.io.manageOfflineStatus) {
         gDebugLog("already offline!");
@@ -120,31 +120,8 @@ var nsOfflineStartup = {
       Services.obs.addObserver(this, "profile-change-net-teardown");
     } else if (aTopic == "profile-after-change") {
       this.onProfileStartup();
     }
   },
 
   QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
 };
-
-function nsOfflineStartupModule() {}
-
-nsOfflineStartupModule.prototype = {
-  classID: Components.ID("3028a3c8-2165-42a4-b878-398da5d32736"),
-  _xpcom_factory: {
-    createInstance(aOuter, aIID) {
-      if (aOuter != null) {
-        throw Cr.NS_ERROR_NO_AGGREGATION;
-      }
-
-      // return the singleton
-      return nsOfflineStartup.QueryInterface(aIID);
-    },
-
-    lockFactory(aLock) {
-      // quieten warnings
-    },
-  },
-};
-
-var components = [nsOfflineStartupModule];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/extensions/offline-startup/components.conf
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{3028a3c8-2165-42a4-b878-398da5d32736}',
+    'contract_ids': ['@mozilla.org/offline-startup;1'],
+    'jsm': 'resource:///modules/OfflineStartup.jsm',
+    'constructor': 'OfflineStartup',
+    'categories': {'app-startup': 'Offline-startup'},
+  },
+]
deleted file mode 100644
--- a/mailnews/extensions/offline-startup/js/offlineStartup.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {3028a3c8-2165-42a4-b878-398da5d32736} offlineStartup.js
-contract @mozilla.org/offline-startup;1 {3028a3c8-2165-42a4-b878-398da5d32736}
-category app-startup Offline-startup @mozilla.org/offline-startup;1
--- a/mailnews/extensions/offline-startup/moz.build
+++ b/mailnews/extensions/offline-startup/moz.build
@@ -1,10 +1,12 @@
 # vim: set filetype=python:
 # 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/.
 
-EXTRA_COMPONENTS += [
-    'js/offlineStartup.js',
-    'js/offlineStartup.manifest',
+EXTRA_JS_MODULES += [
+    'OfflineStartup.jsm',
 ]
 
+XPCOM_MANIFESTS += [
+    'components.conf',
+]
rename from mailnews/extensions/smime/src/smime-service.js
rename to mailnews/extensions/smime/src/SMIMEService.jsm
--- a/mailnews/extensions/smime/src/smime-service.js
+++ b/mailnews/extensions/smime/src/SMIMEService.jsm
@@ -1,16 +1,14 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["SMIMEService"];
 
 function SMIMEService() {}
 
 SMIMEService.prototype = {
   name: "smime",
   chromePackageName: "messenger",
   showPanel(server) {
     // don't show the panel for news, rss, or local accounts
@@ -18,13 +16,9 @@ SMIMEService.prototype = {
       server.type != "nntp" &&
       server.type != "rss" &&
       server.type != "im" &&
       server.type != "none"
     );
   },
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgAccountManagerExtension]),
-  classID: Components.ID("{f2809796-1dd1-11b2-8c1b-8f15f007c699}"),
 };
-
-var components = [SMIMEService];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/extensions/smime/src/components.conf
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{f2809796-1dd1-11b2-8c1b-8f15f007c699}',
+    'contract_ids': ['@mozilla.org/accountmanager/extension;1?name=smime'],
+    'jsm': 'resource:///modules/SMIMEService.jsm',
+    'constructor': 'SMIMEService',
+    'categories': {'mailnews-accountmanager-extensions': 'smime-account-manager-extension'},
+  },
+]
--- a/mailnews/extensions/smime/src/moz.build
+++ b/mailnews/extensions/smime/src/moz.build
@@ -5,19 +5,22 @@
 
 SOURCES += [
     'nsCertPicker.cpp',
     'nsEncryptedSMIMEURIsService.cpp',
     'nsMsgComposeSecure.cpp',
     'nsSMimeJSHelper.cpp',
 ]
 
-EXTRA_COMPONENTS += [
-    'smime-service.js',
-    'smime-service.manifest',
+EXTRA_JS_MODULES += [
+    'SMIMEService.jsm',
+]
+
+XPCOM_MANIFESTS += [
+    'components.conf',
 ]
 
 FINAL_LIBRARY = 'mail'
 
 LOCAL_INCLUDES += [
     '/%s/security/manager/pki' % CONFIG['mozreltopsrcdir'],
     '/%s/security/manager/ssl' % CONFIG['mozreltopsrcdir']
 ]
deleted file mode 100644
--- a/mailnews/extensions/smime/src/smime-service.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {f2809796-1dd1-11b2-8c1b-8f15f007c699} smime-service.js
-contract @mozilla.org/accountmanager/extension;1?name=smime {f2809796-1dd1-11b2-8c1b-8f15f007c699}
-category mailnews-accountmanager-extensions smime-account-manager-extension @mozilla.org/accountmanager/extension;1?name=smime
new file mode 100644
--- /dev/null
+++ b/mailnews/import/test/components.conf
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{a81438ef-aca1-41a5-9b3a-3ccfbbe4f5e1}',
+    'contract_ids': ['@mozilla.org/import/test;1'],
+    'jsm': 'resource:///modules/TestMailImpoter.jsm',
+    'constructor': 'TestMailImpoter',
+    'categories': {'mailnewsimport': 'mail'},
+  },
+]
--- a/mailnews/import/test/moz.build
+++ b/mailnews/import/test/moz.build
@@ -1,7 +1,15 @@
 # vim: set filetype=python:
 # 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 
+EXTRA_JS_MODULES += [
+  'unit/resources/TestMailImporter.jsm',
+]
+
+XPCOM_MANIFESTS += [
+  'components.conf',
+]
+
rename from mailnews/import/test/unit/resources/TestMailImporter.js
rename to mailnews/import/test/unit/resources/TestMailImporter.jsm
--- a/mailnews/import/test/unit/resources/TestMailImporter.js
+++ b/mailnews/import/test/unit/resources/TestMailImporter.jsm
@@ -1,11 +1,9 @@
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
+var EXPORTED_SYMBOLS = ["TestMailImpoter"];
 
 function TestMailImpoter() {}
 
 TestMailImpoter.prototype = {
   classID: Components.ID("{a81438ef-aca1-41a5-9b3a-3ccfbbe4f5e1}"),
 
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsIImportModule,
@@ -129,10 +127,8 @@ TestMailImpoter.prototype = {
   GetImportProgress() {
     return this.progress;
   },
 
   translateFolderName(folderName) {
     return folderName;
   },
 };
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestMailImpoter]);
deleted file mode 100644
--- a/mailnews/import/test/unit/resources/TestMailImporter.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-component {a81438ef-aca1-41a5-9b3a-3ccfbbe4f5e1} TestMailImporter.js
-contract @mozilla.org/import/test;1 {a81438ef-aca1-41a5-9b3a-3ccfbbe4f5e1}
-category mailnewsimport {a81438ef-aca1-41a5-9b3a-3ccfbbe4f5e1} mail
-
--- a/mailnews/import/test/unit/resources/import_helper.js
+++ b/mailnews/import/test/unit/resources/import_helper.js
@@ -662,10 +662,8 @@ FiltersImportHelper.prototype = {
           filterList,
           f => f.filterType & Ci.nsMsgFilterType.PostOutgoing
         ),
         expected.outgoing
       );
     }
   },
 };
-
-do_load_manifest("resources/TestMailImporter.manifest");
--- a/mailnews/jsaccount/moz.build
+++ b/mailnews/jsaccount/moz.build
@@ -5,13 +5,19 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
   'public',
   'src'
 ]
 
 EXTRA_JS_MODULES.jsaccount += [
-    'modules/JaBaseUrl.jsm',
-    'modules/JSAccountUtils.jsm',
+  'modules/JaBaseUrl.jsm',
+  'modules/JSAccountUtils.jsm',
+  'test/unit/resources/TestJaMsgProtocolInfoComponent.jsm',
 ]
 
+XPCOM_MANIFESTS += [
+  'test/components.conf',
+]
+
+
 TEST_DIRS += ['test']
new file mode 100644
--- /dev/null
+++ b/mailnews/jsaccount/test/components.conf
@@ -0,0 +1,14 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{74b9b9c3-9594-41c4-b9f0-326e5daac2e0}',
+    'contract_ids': ['@mozilla.org/messenger/protocol/info;1?type=testja'],
+    'jsm': 'resource:///modules/jsaccount/TestJaMsgProtocolInfoComponent.jsm',
+    'constructor': 'TestJaMsgProtocolInfo',
+  },
+]
--- a/mailnews/jsaccount/test/moz.build
+++ b/mailnews/jsaccount/test/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 TEST_DIRS += [
-    'idl',
+  'idl',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 
 TESTING_JS_MODULES.mailnews += [
   'unit/resources/testJaBaseIncomingServer.jsm',
   'unit/resources/testJaBaseMsgFolder.jsm',
 ]
rename from mailnews/jsaccount/test/unit/resources/testJaMsgProtocolInfoComponent.js
rename to mailnews/jsaccount/test/unit/resources/TestJaMsgProtocolInfoComponent.jsm
--- a/mailnews/jsaccount/test/unit/resources/testJaMsgProtocolInfoComponent.js
+++ b/mailnews/jsaccount/test/unit/resources/TestJaMsgProtocolInfoComponent.jsm
@@ -1,28 +1,27 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // This file is the component definition for a demo base implementation of a
 // javascript nsIMsgProtocolInfo implementation.
 
+var EXPORTED_SYMBOLS = ["TestJaMsgProtocolInfo"];
+
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
-function testJaMsgProtocolInfo() {
+function TestJaMsgProtocolInfo() {
   dump("testJaMsgProtocolInfo");
   // nsIFile object to be used for the default local path.
   this._defaultLocalPath = null;
 }
 
-testJaMsgProtocolInfo.prototype = {
+TestJaMsgProtocolInfo.prototype = {
   // Flag this item as CPP needs to delegate to JS.
   _JsPrototypeToDelegate: true,
 
   get defaultLocalPath() {
     if (this._defaultLocalPath) {
       return this._defaultLocalPath;
     }
     // Setup a default location, "TestFoo" directory in profile.
@@ -69,15 +68,10 @@ testJaMsgProtocolInfo.prototype = {
   },
   get showComposeMsgLink() {
     return false;
   },
   get foldersCreatedAsync() {
     return false;
   },
 
-  classDescription: "testja Msg Protocol Info implementation",
-  classID: Components.ID("{74b9b9c3-9594-41c4-b9f0-326e5daac2e0}"),
-  contractID: "@mozilla.org/messenger/protocol/info;1?type=testja",
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgProtocolInfo]),
 };
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([testJaMsgProtocolInfo]);
--- a/mailnews/jsaccount/test/unit/resources/testComponents.manifest
+++ b/mailnews/jsaccount/test/unit/resources/testComponents.manifest
@@ -9,12 +9,8 @@ contract @mozilla.org/jsaccount/testjafo
 
 # nsIMsgFolder implementation
 component {8508ddeb-3eab-4877-a420-297518f62371} testJaBaseMsgFolderComponent.js
 contract @mozilla.org/mail/folder-factory;1?name=testja {8508ddeb-3eab-4877-a420-297518f62371}
 
 # nsIMsgIncomingServer implementation
 component {0eec03cd-da67-4949-ab2d-5fa4bdc68135} testJaBaseIncomingServerComponent.js
 contract @mozilla.org/messenger/server;1?type=testja {0eec03cd-da67-4949-ab2d-5fa4bdc68135}
-
-# nsIMsgProtocolInfo implementation
-component {74b9b9c3-9594-41c4-b9f0-326e5daac2e0} testJaMsgProtocolInfoComponent.js
-contract @mozilla.org/messenger/protocol/info;1?type=testja {74b9b9c3-9594-41c4-b9f0-326e5daac2e0}
rename from mailnews/mime/src/mimeJSComponents.js
rename to mailnews/mime/src/MimeJSComponents.jsm
--- a/mailnews/mime/src/mimeJSComponents.js
+++ b/mailnews/mime/src/MimeJSComponents.jsm
@@ -1,17 +1,21 @@
 /* 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/. */
 
+var EXPORTED_SYMBOLS = [
+  "MimeHeaders",
+  "MimeWritableStructuredHeaders",
+  "MimeAddressParser",
+  "MimeConverter",
+];
+
 var { jsmime } = ChromeUtils.import("resource:///modules/jsmime.jsm");
 var { MimeParser } = ChromeUtils.import("resource:///modules/mimeParser.jsm");
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 function HeaderHandler() {
   this.value = "";
   this.deliverData = function(str) {
     this.value += str;
   };
   this.deliverEOF = function() {};
 }
@@ -138,18 +142,16 @@ MimeStructuredHeaders.prototype = {
     return handler.value;
   },
 };
 
 function MimeHeaders() {}
 MimeHeaders.prototype = {
   __proto__: MimeStructuredHeaders.prototype,
   classDescription: "Mime headers implementation",
-  classID: Components.ID("d1258011-f391-44fd-992e-c6f4b461a42f"),
-  contractID: "@mozilla.org/messenger/mimeheaders;1",
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsIMimeHeaders,
     Ci.msgIStructuredHeaders,
   ]),
 
   initialize(allHeaders) {
     this._headers = MimeParser.extractHeaders(allHeaders);
   },
@@ -175,17 +177,16 @@ MimeHeaders.prototype = {
   },
 };
 
 function MimeWritableStructuredHeaders() {
   this._headers = new Map();
 }
 MimeWritableStructuredHeaders.prototype = {
   __proto__: MimeStructuredHeaders.prototype,
-  classID: Components.ID("c560806a-425f-4f0f-bf69-397c58c599a7"),
   QueryInterface: ChromeUtils.generateQI([
     Ci.msgIStructuredHeaders,
     Ci.msgIWritableStructuredHeaders,
   ]),
 
   setHeader(aHeaderName, aValue) {
     this._headers.set(aHeaderName.toLowerCase(), aValue);
   },
@@ -274,17 +275,16 @@ function fixArray(addresses, preserveGro
   if (count) {
     count.value = outputArray.length;
   }
   return outputArray;
 }
 
 function MimeAddressParser() {}
 MimeAddressParser.prototype = {
-  classID: Components.ID("96bd8769-2d0e-4440-963d-22b97fb3ba77"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgHeaderParser]),
 
   parseEncodedHeader(aHeader, aCharset, aPreserveGroups) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(
       aHeader,
       MimeParser.HEADER_ADDRESS | MimeParser.HEADER_OPTION_ALL_I18N,
       aCharset
@@ -449,17 +449,16 @@ MimeAddressParser.prototype = {
   makeMimeAddress(aName, aEmail) {
     let object = this.makeMailboxObject(aName, aEmail);
     return this.makeMimeHeader([object]);
   },
 };
 
 function MimeConverter() {}
 MimeConverter.prototype = {
-  classID: Components.ID("93f8c049-80ed-4dda-9000-94ad8daba44c"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMimeConverter]),
 
   encodeMimePartIIStr_UTF8(aHeader, aStructured, aFieldNameLen, aLineLength) {
     // Compute the encoding options. The way our API is structured in this
     // method is really horrendous and does not align with the way that JSMime
     // handles it. Instead, we'll need to create a fake header to take into
     // account the aFieldNameLen parameter.
     let fakeHeader = "-".repeat(aFieldNameLen);
@@ -518,16 +517,8 @@ MimeConverter.prototype = {
   },
 
   // This is identical to the above, except for factors that are handled by the
   // xpconnect conversion process
   decodeMimeHeaderToUTF8(...aArgs) {
     return this.decodeMimeHeader(...aArgs);
   },
 };
-
-var components = [
-  MimeHeaders,
-  MimeWritableStructuredHeaders,
-  MimeAddressParser,
-  MimeConverter,
-];
-var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/src/components.conf
@@ -0,0 +1,32 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{d1258011-f391-44fd-992e-c6f4b461a42f}',
+    'contract_ids': ['@mozilla.org/messenger/mimeheaders;1'],
+    'jsm': 'resource:///modules/MimeJSComponents.jsm',
+    'constructor': 'MimeHeaders',
+  },
+  {
+    'cid': '{c560806a-425f-4f0f-bf69-397c58c599a7}',
+    'contract_ids': ['@mozilla.org/messenger/structuredheaders;1'],
+    'jsm': 'resource:///modules/MimeJSComponents.jsm',
+    'constructor': 'MimeWritableStructuredHeaders',
+  },
+  {
+    'cid': '{96bd8769-2d0e-4440-963d-22b97fb3ba77}',
+    'contract_ids': ['@mozilla.org/messenger/headerparser;1'],
+    'jsm': 'resource:///modules/MimeJSComponents.jsm',
+    'constructor': 'MimeAddressParser',
+  },
+  {
+    'cid': '{93f8c049-80ed-4dda-9000-94ad8daba44c}',
+    'contract_ids': ['@mozilla.org/messenger/mimeconverter;1'],
+    'jsm': 'resource:///modules/MimeJSComponents.jsm',
+    'constructor': 'MimeConverter',
+  },
+]
--- a/mailnews/mime/src/moz.build
+++ b/mailnews/mime/src/moz.build
@@ -72,21 +72,25 @@ SOURCES += [
 
 LOCAL_INCLUDES += [
     '/%s/intl/chardet' % CONFIG['mozreltopsrcdir'],
     '/%s/security/certverifier' % CONFIG['mozreltopsrcdir'],
     '/%s/security/manager/ssl' % CONFIG['mozreltopsrcdir']
 ]
 
 EXTRA_COMPONENTS += [
-    'mimeJSComponents.js',
     'msgMime.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'extraMimeParsers.jsm',
     'jsmime.jsm',
-    'mimeParser.jsm'
+    'MimeJSComponents.jsm',
+    'mimeParser.jsm',
+]
+
+XPCOM_MANIFESTS += [
+    'components.conf',
 ]
 
 FINAL_LIBRARY = 'mail'
 
 DEFINES['ENABLE_SMIME'] = True
--- a/mailnews/mime/src/msgMime.manifest
+++ b/mailnews/mime/src/msgMime.manifest
@@ -1,9 +1,1 @@
-component {d1258011-f391-44fd-992e-c6f4b461a42f} mimeJSComponents.js
-component {96bd8769-2d0e-4440-963d-22b97fb3ba77} mimeJSComponents.js
-component {93f8c049-80ed-4dda-9000-94ad8daba44c} mimeJSComponents.js
-component {c560806a-425f-4f0f-bf69-397c58c599a7} mimeJSComponents.js
-contract @mozilla.org/messenger/mimeheaders;1 {d1258011-f391-44fd-992e-c6f4b461a42f}
-contract @mozilla.org/messenger/mimeconverter;1 {93f8c049-80ed-4dda-9000-94ad8daba44c}
-contract @mozilla.org/messenger/headerparser;1 {96bd8769-2d0e-4440-963d-22b97fb3ba77}
-contract @mozilla.org/messenger/structuredheaders;1 {c560806a-425f-4f0f-bf69-397c58c599a7}
 category custom-mime-encoder A-extra resource:///modules/extraMimeParsers.jsm
rename from mailnews/news/src/nsNewsAutoCompleteSearch.js
rename to mailnews/news/src/NewsAutoCompleteSearch.jsm
--- a/mailnews/news/src/nsNewsAutoCompleteSearch.js
+++ b/mailnews/news/src/NewsAutoCompleteSearch.jsm
@@ -1,31 +1,30 @@
 /* -*- Mode: Javascript; 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/. */
 
+var EXPORTED_SYMBOLS = ["NewsAutoCompleteSearch"];
+
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
-var { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
 
 var kACR = Ci.nsIAutoCompleteResult;
 var kSupportedTypes = new Set(["addr_newsgroups", "addr_followup"]);
 
-function nsNewsAutoCompleteResult(aSearchString) {
+function NewsAutoCompleteResult(aSearchString) {
   // Can't create this in the prototype as we'd get the same array for
   // all instances
   this._searchResults = [];
   this.searchString = aSearchString;
 }
 
-nsNewsAutoCompleteResult.prototype = {
+NewsAutoCompleteResult.prototype = {
   _searchResults: null,
 
   // nsIAutoCompleteResult
 
   searchString: null,
   searchResult: kACR.RESULT_NOMATCH,
   defaultIndex: -1,
   errorDescription: null,
@@ -60,22 +59,21 @@ nsNewsAutoCompleteResult.prototype = {
 
   removeValueAt(aRowIndex, aRemoveFromDB) {},
 
   // nsISupports
 
   QueryInterface: ChromeUtils.generateQI([kACR]),
 };
 
-function nsNewsAutoCompleteSearch() {}
+function NewsAutoCompleteSearch() {}
 
-nsNewsAutoCompleteSearch.prototype = {
+NewsAutoCompleteSearch.prototype = {
   // For component registration
   classDescription: "Newsgroup Autocomplete",
-  classID: Components.ID("e9bb3330-ac7e-11de-8a39-0800200c9a66"),
 
   cachedAccountKey: "",
   cachedServer: null,
 
   /**
    * Find the newsgroup server associated with the given accountKey.
    *
    * @param accountKey  The key of the account.
@@ -88,17 +86,17 @@ nsNewsAutoCompleteSearch.prototype = {
       return account.incomingServer;
     }
     return null;
   },
 
   // nsIAutoCompleteSearch
   startSearch(aSearchString, aSearchParam, aPreviousResult, aListener) {
     let params = aSearchParam ? JSON.parse(aSearchParam) : {};
-    let result = new nsNewsAutoCompleteResult(aSearchString);
+    let result = new NewsAutoCompleteResult(aSearchString);
     if (
       !("type" in params) ||
       !("accountKey" in params) ||
       !kSupportedTypes.has(params.type)
     ) {
       result.searchResult = kACR.RESULT_IGNORED;
       aListener.onSearchResult(this, result);
       return;
@@ -131,11 +129,8 @@ nsNewsAutoCompleteSearch.prototype = {
   },
 
   stopSearch() {},
 
   // nsISupports
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAutoCompleteSearch]),
 };
-
-// Module
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsNewsAutoCompleteSearch]);
new file mode 100644
--- /dev/null
+++ b/mailnews/news/src/components.conf
@@ -0,0 +1,14 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+  {
+    'cid': '{e9bb3330-ac7e-11de-8a39-0800200c9a66}',
+    'contract_ids': ['@mozilla.org/autocomplete/search;1?name=news'],
+    'jsm': 'resource:///modules/NewsAutoCompleteSearch.jsm',
+    'constructor': 'NewsAutoCompleteSearch',
+  },
+]
--- a/mailnews/news/src/moz.build
+++ b/mailnews/news/src/moz.build
@@ -13,15 +13,18 @@ SOURCES += [
     'nsNntpMockChannel.cpp',
     'nsNNTPNewsgroupList.cpp',
     'nsNNTPNewsgroupPost.cpp',
     'nsNNTPProtocol.cpp',
     'nsNntpService.cpp',
     'nsNntpUrl.cpp',
 ]
 
-EXTRA_COMPONENTS += [
-    'nsNewsAutoCompleteSearch.js',
-    'nsNewsAutoCompleteSearch.manifest',
+EXTRA_JS_MODULES += [
+    'NewsAutoCompleteSearch.jsm',
+]
+
+XPCOM_MANIFESTS += [
+    'components.conf',
 ]
 
 FINAL_LIBRARY = 'mail'
 
deleted file mode 100644
--- a/mailnews/news/src/nsNewsAutoCompleteSearch.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {e9bb3330-ac7e-11de-8a39-0800200c9a66} nsNewsAutoCompleteSearch.js
-contract @mozilla.org/autocomplete/search;1?name=news {e9bb3330-ac7e-11de-8a39-0800200c9a66}