Bug 1456035: Part 5 - Convert manual QueryInterface to ChromeUtils.generateQI. r=mccr8
authorKris Maglione <maglione.k@gmail.com>
Mon, 23 Apr 2018 12:58:34 -0700
changeset 416160 8db81ce4d3a29fa0f9f69b904d2868e3b954bf39
parent 416159 c58f0b4dd8494f4a81c69b0315af223576660200
child 416161 23d3d208fcaaeb67b79380d4b514f9785cc57a72
push id33917
push userapavel@mozilla.com
push dateSat, 28 Apr 2018 17:30:55 +0000
treeherdermozilla-central@08f68e2c892c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1456035
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456035: Part 5 - Convert manual QueryInterface to ChromeUtils.generateQI. r=mccr8 Manually-implemented QueryInterface functions don't benefit from the MozQueryInterface optimizaions, and a lot of them are in hot code, and implement a large number of interfaces. MozReview-Commit-ID: 8OzglraowZt
browser/base/content/aboutDialog-appUpdater.js
browser/base/content/browser.js
browser/base/content/tabbrowser.js
browser/base/content/web-panels.js
browser/components/feeds/FeedConverter.js
browser/components/feeds/WebContentConverter.js
browser/components/nsBrowserContentHandler.js
browser/components/places/content/bookmarkProperties.js
browser/components/places/content/browserPlacesViews.js
browser/components/places/content/places.js
browser/components/preferences/in-content/main.js
devtools/client/responsive.html/browser/content.js
devtools/shared/gcli/commands/screenshot.js
dom/push/PushServiceHttp2.jsm
mobile/android/modules/Notifications.jsm
mobile/android/modules/SSLExceptions.jsm
toolkit/components/contentprefs/ContentPrefService2.js
toolkit/components/printing/content/printPreviewProgress.js
toolkit/components/printing/content/printProgress.js
toolkit/components/printing/content/printUtils.js
toolkit/components/viewsource/content/viewSourceUtils.js
toolkit/content/browser-child.js
toolkit/content/contentAreaUtils.js
toolkit/modules/CertUtils.jsm
toolkit/modules/FinderHighlighter.jsm
toolkit/modules/addons/WebRequest.jsm
toolkit/mozapps/downloads/DownloadLastDir.jsm
toolkit/mozapps/downloads/nsHelperAppDlg.js
toolkit/mozapps/extensions/amWebAPI.js
toolkit/mozapps/update/content/updates.js
--- a/browser/base/content/aboutDialog-appUpdater.js
+++ b/browser/base/content/aboutDialog-appUpdater.js
@@ -296,22 +296,17 @@ appUpdater.prototype =
       // notified with the normal app update user interface so this is safe.
       gAppUpdater.isChecking = false;
       gAppUpdater.selectPanel("noUpdatesFound");
     },
 
     /**
      * See nsISupports.idl
      */
-    QueryInterface(aIID) {
-      if (!aIID.equals(Ci.nsIUpdateCheckListener) &&
-          !aIID.equals(Ci.nsISupports))
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      return this;
-    }
+    QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckListener"]),
   },
 
   /**
    * Starts the download of an update mar.
    */
   startDownload() {
     if (!this.update)
       this.update = this.um.activeUpdate;
@@ -422,16 +417,10 @@ appUpdater.prototype =
   onProgress(aRequest, aContext, aProgress, aProgressMax) {
     this.downloadStatus.textContent =
       DownloadUtils.getTransferTotal(aProgress, aProgressMax);
   },
 
   /**
    * See nsISupports.idl
    */
-  QueryInterface(aIID) {
-    if (!aIID.equals(Ci.nsIProgressEventSink) &&
-        !aIID.equals(Ci.nsIRequestObserver) &&
-        !aIID.equals(Ci.nsISupports))
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    return this;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIProgressEventSink", "nsIRequestObserver"]),
 };
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4595,25 +4595,20 @@ var XULBrowserWindow = {
   // Stored Status, Link and Loading values
   status: "",
   defaultStatus: "",
   overLink: "",
   startTime: 0,
   isBusy: false,
   busyUI: false,
 
-  QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIWebProgressListener) ||
-        aIID.equals(Ci.nsIWebProgressListener2) ||
-        aIID.equals(Ci.nsISupportsWeakReference) ||
-        aIID.equals(Ci.nsIXULBrowserWindow) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_NOINTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+                                          "nsIWebProgressListener2",
+                                          "nsISupportsWeakReference",
+                                          "nsIXULBrowserWindow"]),
 
   get stopCommand() {
     delete this.stopCommand;
     return this.stopCommand = document.getElementById("Browser:Stop");
   },
   get reloadCommand() {
     delete this.reloadCommand;
     return this.reloadCommand = document.getElementById("Browser:Reload");
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -4569,26 +4569,21 @@ class TabProgressListener {
     this._callProgressListeners("onSecurityChange",
                                 [aWebProgress, aRequest, aState]);
   }
 
   onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
     return this._callProgressListeners("onRefreshAttempted",
                                        [aWebProgress, aURI, aDelay, aSameURI]);
   }
-
-  QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIWebProgressListener) ||
-        aIID.equals(Ci.nsIWebProgressListener2) ||
-        aIID.equals(Ci.nsISupportsWeakReference) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_NOINTERFACE;
-  }
 }
+TabProgressListener.prototype.QueryInterface = ChromeUtils.generateQI(
+  ["nsIWebProgressListener",
+   "nsIWebProgressListener2",
+   "nsISupportsWeakReference"]);
 
 var StatusPanel = {
   get panel() {
     window.addEventListener("resize", this);
 
     delete this.panel;
     return this.panel = document.getElementById("statuspanel");
   },
--- a/browser/base/content/web-panels.js
+++ b/browser/base/content/web-panels.js
@@ -42,23 +42,17 @@ var panelProgressListener = {
     },
 
     onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
     },
 
     onSecurityChange(aWebProgress, aRequest, aState) {
     },
 
-    QueryInterface(aIID) {
-        if (aIID.equals(Ci.nsIWebProgressListener) ||
-            aIID.equals(Ci.nsISupportsWeakReference) ||
-            aIID.equals(Ci.nsISupports))
-            return this;
-        throw Cr.NS_NOINTERFACE;
-    }
+    QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]),
 };
 
 var gLoadFired = false;
 function loadWebPanel(aURI) {
     var panelBrowser = getPanelBrowser();
     if (gLoadFired) {
         panelBrowser.webNavigation
                     .loadURI(aURI, Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
--- a/browser/components/feeds/FeedConverter.js
+++ b/browser/components/feeds/FeedConverter.js
@@ -321,25 +321,20 @@ FeedConverter.prototype = {
   onStopRequest(request, context, status) {
     if (this._processor)
       this._processor.onStopRequest(request, context, status);
   },
 
   /**
    * See nsISupports.idl
    */
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIFeedResultListener) ||
-        iid.equals(Ci.nsIStreamConverter) ||
-        iid.equals(Ci.nsIStreamListener) ||
-        iid.equals(Ci.nsIRequestObserver) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIFeedResultListener",
+                                          "nsIStreamConverter",
+                                          "nsIStreamListener",
+                                          "nsIRequestObserver"]),
 };
 
 /**
  * Keeps parsed FeedResults around for use elsewhere in the UI after the stream
  * converter completes.
  */
 function FeedResultService() {
 }
@@ -451,23 +446,18 @@ FeedResultService.prototype = {
   },
 
   createInstance(outer, iid) {
     if (outer != null)
       throw Cr.NS_ERROR_NO_AGGREGATION;
     return this.QueryInterface(iid);
   },
 
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIFeedResultService) ||
-        iid.equals(Ci.nsIFactory) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIFeedResultService",
+                                          "nsIFactory"]),
 };
 
 
 var components = [FeedConverter,
                   FeedResultService];
 
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/browser/components/feeds/WebContentConverter.js
+++ b/browser/components/feeds/WebContentConverter.js
@@ -43,38 +43,28 @@ WebContentConverter.prototype = {
 
   onStartRequest(request, context) {
     let wccr =
         Cc[WCCR_CONTRACTID].
         getService(Ci.nsIWebContentConverterService);
     wccr.loadPreferredHandler(request);
   },
 
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIStreamConverter) ||
-        iid.equals(Ci.nsIStreamListener) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIStreamConverter",
+                                          "nsIStreamListener"]),
 };
 
 let WebContentConverterFactory = {
   createInstance(outer, iid) {
     if (outer != null)
       throw Cr.NS_ERROR_NO_AGGREGATION;
     return new WebContentConverter().QueryInterface(iid);
   },
 
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIFactory) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIFactory"]),
 };
 
 function ServiceInfo(contentType, uri, name) {
   this._contentType = contentType;
   this._uri = uri;
   this._name = name;
 }
 ServiceInfo.prototype = {
@@ -116,22 +106,17 @@ ServiceInfo.prototype = {
 
   /**
    * See nsIWebContentHandlerInfo
    */
   getHandlerURI(uri) {
     return this._uri.replace(/%s/gi, encodeURIComponent(uri));
   },
 
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIWebContentHandlerInfo) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIWebContentHandlerInfo"]),
 };
 
 const Utils = {
   makeURI(aURL, aOriginCharset, aBaseURI) {
     return Services.io.newURI(aURL, aOriginCharset, aBaseURI);
   },
 
   checkAndGetURI(aURIString, aContentWindow) {
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -692,23 +692,17 @@ function handURIToExistingBrowser(uri, l
 
 function nsDefaultCommandLineHandler() {
 }
 
 nsDefaultCommandLineHandler.prototype = {
   classID: Components.ID("{47cd0651-b1be-4a0f-b5c4-10e5a573ef71}"),
 
   /* nsISupports */
-  QueryInterface: function dch_QI(iid) {
-    if (!iid.equals(Ci.nsISupports) &&
-        !iid.equals(Ci.nsICommandLineHandler))
-      throw Cr.NS_ERROR_NO_INTERFACE;
-
-    return this;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsICommandLineHandler"]),
 
   _haveProfile: false,
 
   /* nsICommandLineHandler */
   handle: function dch_handle(cmdLine) {
     var urilist = [];
 
     if (AppConstants.platform == "win") {
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -367,22 +367,17 @@ var BookmarkPropertiesPanel = {
           this._height += -oldHeight + newHeight;
           elementsHeight.set(id, newHeight);
         }
         break;
     }
   },
 
   // nsISupports
-  QueryInterface: function BPP_QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_NOINTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI([]),
 
   _element: function BPP__element(aID) {
     return document.getElementById("editBMPanel_" + aID);
   },
 
   onDialogUnload() {
     // gEditItemOverlay does not exist anymore here, so don't rely on it.
     this._mutationObserver.disconnect();
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -14,16 +14,19 @@ function PlacesViewBase(aPlace, aOptions
   if ("viewElt" in aOptions)
     this._viewElt = aOptions.viewElt;
   this.options = aOptions;
   this._controller = new PlacesController(this);
   this.place = aPlace;
   this._viewElt.controllers.appendController(this._controller);
 }
 
+PlacesViewBase.interfaces = [Ci.nsINavHistoryResultObserver,
+                             Ci.nsISupportsWeakReference];
+
 PlacesViewBase.prototype = {
   // The xul element that holds the entire view.
   _viewElt: null,
   get viewElt() {
     return this._viewElt;
   },
 
   get associatedElement() {
@@ -37,18 +40,17 @@ PlacesViewBase.prototype = {
   // The xul element that represents the root container.
   _rootElt: null,
 
   // Set to true for views that are represented by native widgets (i.e.
   // the native mac menu).
   _nativeView: false,
 
   QueryInterface: ChromeUtils.generateQI(
-    [Ci.nsINavHistoryResultObserver,
-     Ci.nsISupportsWeakReference]),
+    PlacesViewBase.interfaces),
 
   _place: "",
   get place() {
     return this._place;
   },
   set place(val) {
     this._place = val;
 
@@ -1003,22 +1005,18 @@ function PlacesToolbar(aPlace) {
 }
 
 PlacesToolbar.prototype = {
   __proto__: PlacesViewBase.prototype,
 
   _cbEvents: ["dragstart", "dragover", "dragexit", "dragend", "drop",
               "mousemove", "mouseover", "mouseout"],
 
-  QueryInterface: function PT_QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsITimerCallback))
-      return this;
-
-    return PlacesViewBase.prototype.QueryInterface.apply(this, arguments);
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsITimerCallback",
+                                          ...PlacesViewBase.interfaces]),
 
   uninit: function PT_uninit() {
     this._removeEventListeners(this._viewElt, this._cbEvents, false);
     this._removeEventListeners(this._rootElt, ["popupshowing", "popuphidden"],
                                true);
     this._removeEventListeners(this._rootElt, ["overflow", "underflow"], true);
     this._removeEventListeners(window, ["resize", "unload"], false);
     this._removeEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
@@ -1970,20 +1968,16 @@ function PlacesPanelMenuView(aPlace, aVi
   this.options = aOptions;
 
   PlacesViewBase.call(this, aPlace, aOptions);
 }
 
 PlacesPanelMenuView.prototype = {
   __proto__: PlacesViewBase.prototype,
 
-  QueryInterface: function PAMV_QueryInterface(aIID) {
-    return PlacesViewBase.prototype.QueryInterface.apply(this, arguments);
-  },
-
   uninit: function PAMV_uninit() {
     PlacesViewBase.prototype.uninit.apply(this, arguments);
   },
 
   _insertNewItem:
   function PAMV__insertNewItem(aChild, aInsertionNode, aBefore = null) {
     this._domNodes.delete(aChild);
 
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -191,22 +191,17 @@ var PlacesOrganizer = {
 
     if (!Services.policies.isAllowed("profileImport")) {
       document.getElementById("OrganizerCommand_browserImport").setAttribute("disabled", true);
     }
 
     ContentArea.focus();
   },
 
-  QueryInterface: function PO_QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_NOINTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI([]),
 
   handleEvent: function PO_handleEvent(aEvent) {
     if (aEvent.type != "AppCommand")
       return;
 
     aEvent.stopPropagation();
     switch (aEvent.command) {
       case "Back":
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -3017,24 +3017,17 @@ FeedHandlerInfo.prototype = {
       return this._possibleApplicationHandlers;
 
     // A minimal implementation of nsIMutableArray.  It only supports the two
     // methods its callers invoke, namely appendElement and nsIArray::enumerate.
     this._possibleApplicationHandlers = {
       _inner: [],
       _removed: [],
 
-      QueryInterface(aIID) {
-        if (aIID.equals(Ci.nsIMutableArray) ||
-          aIID.equals(Ci.nsIArray) ||
-          aIID.equals(Ci.nsISupports))
-          return this;
-
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      },
+      QueryInterface: ChromeUtils.generateQI(["nsIMutableArray", "nsIArray"]),
 
       get length() {
         return this._inner.length;
       },
 
       enumerate() {
         return new ArrayEnumerator(this._inner);
       },
--- a/devtools/client/responsive.html/browser/content.js
+++ b/devtools/client/responsive.html/browser/content.js
@@ -178,21 +178,15 @@ var global = this;
 
   let WebProgressListener = {
     onLocationChange(webProgress, request, URI, flags) {
       if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
         return;
       }
       makeScrollbarsFloating();
     },
-    QueryInterface: function QueryInterface(iid) {
-      if (iid.equals(Ci.nsIWebProgressListener) ||
-          iid.equals(Ci.nsISupportsWeakReference) ||
-          iid.equals(Ci.nsISupports)) {
-        return this;
-      }
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
+    QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+                                            "nsISupportsWeakReference"]),
   };
 })();
 
 global.responsiveFrameScriptLoaded = true;
 sendAsyncMessage("ResponsiveMode:ChildScriptReady");
--- a/devtools/shared/gcli/commands/screenshot.js
+++ b/devtools/shared/gcli/commands/screenshot.js
@@ -486,25 +486,19 @@ function DownloadListener(win, transfer)
   }
 
   // Allow saveToFile to await completion for error handling
   this._completedDeferred = defer();
   this.completed = this._completedDeferred.promise;
 }
 
 DownloadListener.prototype = {
-  QueryInterface: function(iid) {
-    if (iid.equals(Ci.nsIInterfaceRequestor) ||
-        iid.equals(Ci.nsIWebProgressListener) ||
-        iid.equals(Ci.nsIWebProgressListener2) ||
-        iid.equals(Ci.nsISupports)) {
-      return this;
-    }
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor",
+                                          "nsIWebProgressListener",
+                                          "nsIWebProgressListener2"]),
 
   getInterface: function(iid) {
     if (iid.equals(Ci.nsIAuthPrompt) ||
         iid.equals(Ci.nsIAuthPrompt2)) {
       let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
                  .getService(Ci.nsIPromptFactory);
       return ww.getPrompt(this.window, iid);
     }
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -45,23 +45,18 @@ const kPUSHHTTP2DB_STORE_NAME = "pushHtt
 var PushSubscriptionListener = function(pushService, uri) {
   console.debug("PushSubscriptionListener()");
   this._pushService = pushService;
   this.uri = uri;
 };
 
 PushSubscriptionListener.prototype = {
 
-  QueryInterface: function (aIID) {
-    if (aIID.equals(Ci.nsIHttpPushListener) ||
-        aIID.equals(Ci.nsIStreamListener)) {
-      return this;
-    }
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIHttpPushListener",
+                                         "nsIStreamListener"]),
 
   getInterface: function(aIID) {
     return this.QueryInterface(aIID);
   },
 
   onStartRequest: function(aRequest, aContext) {
     console.debug("PushSubscriptionListener: onStartRequest()");
     // We do not do anything here.
--- a/mobile/android/modules/Notifications.jsm
+++ b/mobile/android/modules/Notifications.jsm
@@ -231,18 +231,13 @@ var Notifications = {
 
         if (notification && notification._onCancel)
           notification._onCancel(id, notification._cookie);
         delete _notificationsMap[id]; // since the notification was dismissed, we no longer need to hold a reference.
         break;
     }
   },
 
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) &&
-        !aIID.equals(Ci.nsIObserver) &&
-        !aIID.equals(Ci.nsISupportsWeakReference))
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    return this;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIObserver",
+                                          "nsISupportsWeakReference"]),
 };
 
 EventDispatcher.instance.registerListener(Notifications, "Notification:Event");
--- a/mobile/android/modules/SSLExceptions.jsm
+++ b/mobile/android/modules/SSLExceptions.jsm
@@ -21,23 +21,17 @@ function SSLExceptions() {
 
 SSLExceptions.prototype = {
   _overrideService: null,
   _sslStatus: null,
 
   getInterface: function SSLE_getInterface(aIID) {
     return this.QueryInterface(aIID);
   },
-  QueryInterface: function SSLE_QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIBadCertListener2) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIBadCertListener2"]),
 
   /**
     To collect the SSL status we intercept the certificate error here
     and store the status for later use.
   */
   notifyCertProblem: function SSLE_notifyCertProblem(socketInfo, sslStatus, targetHost) {
     this._sslStatus = sslStatus.QueryInterface(Ci.nsISSLStatus);
     return true; // suppress error UI
--- a/toolkit/components/contentprefs/ContentPrefService2.js
+++ b/toolkit/components/contentprefs/ContentPrefService2.js
@@ -969,26 +969,18 @@ ContentPrefService2.prototype = {
 
     let tables = ["prefs", "groups", "settings"];
     let stmts = tables.map(t => this._stmt(`DELETE FROM ${t}`));
     this._execStmts(stmts, { onDone: () => {
       callback();
     } });
   },
 
-  QueryInterface: function CPS2_QueryInterface(iid) {
-    let supportedIIDs = [
-      Ci.nsIContentPrefService2,
-      Ci.nsIObserver,
-      Ci.nsISupports,
-    ];
-    if (supportedIIDs.some(i => iid.equals(i)))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIContentPrefService2",
+                                          "nsIObserver"]),
 
 
   // Database Creation & Access
 
   _dbVersion: 4,
 
   _dbSchema: {
     tables: {
--- a/toolkit/components/printing/content/printPreviewProgress.js
+++ b/toolkit/components/printing/content/printPreviewProgress.js
@@ -61,21 +61,18 @@ var progressListener = {
   onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {},
   onSecurityChange(aWebProgress, aRequest, state) {},
 
   onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
     if (aMessage)
       dialog.title.setAttribute("value", aMessage);
   },
 
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIWebProgressListener) || iid.equals(Ci.nsISupportsWeakReference))
-      return this;
-    throw Cr.NS_NOINTERFACE;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+                                          "nsISupportsWeakReference"]),
 };
 
 function onLoad() {
   // Set global variables.
   printProgress = window.arguments[0];
   if (window.arguments[1]) {
     progressParams = window.arguments[1].QueryInterface(Ci.nsIPrintProgressParams);
     if (progressParams) {
--- a/toolkit/components/printing/content/printProgress.js
+++ b/toolkit/components/printing/content/printProgress.js
@@ -143,22 +143,18 @@ var progressListener = {
       if (aMessage != "")
         dialog.title.setAttribute("value", aMessage);
     },
 
     onSecurityChange(aWebProgress, aRequest, state) {
       // we can ignore this notification
     },
 
-    QueryInterface(iid) {
-     if (iid.equals(Ci.nsIWebProgressListener) || iid.equals(Ci.nsISupportsWeakReference))
-      return this;
-
-     throw Cr.NS_NOINTERFACE;
-    }
+    QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+                                            "nsISupportsWeakReference"]),
 };
 
 function getString( stringId ) {
    // Check if we've fetched this string already.
    if (!(stringId in dialog.strings)) {
       // Try to get it.
       var elem = document.getElementById( "dialog.strings." + stringId );
       try {
--- a/toolkit/components/printing/content/printUtils.js
+++ b/toolkit/components/printing/content/printUtils.js
@@ -394,23 +394,18 @@ var PrintUtils = {
       if (aTopic) {
         return;
       }
 
       // delay the print preview to show the content of the progress dialog
       setTimeout(function() { PrintUtils.enterPrintPreview(); }, 0);
     },
 
-    QueryInterface(iid) {
-      if (iid.equals(Ci.nsIObserver) ||
-          iid.equals(Ci.nsISupportsWeakReference) ||
-          iid.equals(Ci.nsISupports))
-        return this;
-      throw Cr.NS_NOINTERFACE;
-    }
+    QueryInterface: ChromeUtils.generateQI(["nsIObserver",
+                                            "nsISupportsWeakReference"]),
   },
 
   setSimplifiedMode(shouldSimplify) {
     this._shouldSimplify = shouldSimplify;
   },
 
   /**
   * Currently, we create a new print preview browser to host the simplified
--- a/toolkit/components/viewsource/content/viewSourceUtils.js
+++ b/toolkit/components/viewsource/content/viewSourceUtils.js
@@ -265,23 +265,18 @@ var gViewSourceUtils = {
 
     return null;
   },
 
   viewSourceProgressListener: {
 
     mnsIWebProgressListener: Ci.nsIWebProgressListener,
 
-    QueryInterface(aIID) {
-     if (aIID.equals(this.mnsIWebProgressListener) ||
-         aIID.equals(Ci.nsISupportsWeakReference) ||
-         aIID.equals(Ci.nsISupports))
-       return this;
-     throw Cr.NS_NOINTERFACE;
-    },
+    QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+                                            "nsISupportsWeakReference"]),
 
     destroy() {
       if (this.webShell) {
         this.webShell.QueryInterface(Ci.nsIBaseWindow).destroy();
       }
       this.webShell = null;
       this.editor = null;
       this.resolve = null;
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -227,26 +227,19 @@ var WebProgressListener = {
   onRefreshAttempted: function onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
     return true;
   },
 
   sendLoadCallResult() {
     sendAsyncMessage("Content:LoadURIResult");
   },
 
-  QueryInterface: function QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIWebProgressListener) ||
-        aIID.equals(Ci.nsIWebProgressListener2) ||
-        aIID.equals(Ci.nsISupportsWeakReference) ||
-        aIID.equals(Ci.nsISupports)) {
-        return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+                                          "nsIWebProgressListener2",
+                                          "nsISupportsWeakReference"]),
 };
 
 WebProgressListener.init();
 addEventListener("unload", () => {
   WebProgressListener.uninit();
 });
 
 var WebNavigation =  {
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -243,25 +243,19 @@ function DownloadListener(win, transfer)
   // Now... we need to forward all calls to our transfer
   for (var i in transfer) {
     if (i != "QueryInterface")
       this[i] = makeClosure(i);
   }
 }
 
 DownloadListener.prototype = {
-  QueryInterface: function dl_qi(aIID) {
-    if (aIID.equals(Ci.nsIInterfaceRequestor) ||
-        aIID.equals(Ci.nsIWebProgressListener) ||
-        aIID.equals(Ci.nsIWebProgressListener2) ||
-        aIID.equals(Ci.nsISupports)) {
-      return this;
-    }
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor",
+                                          "nsIWebProgressListener",
+                                          "nsIWebProgressListener2"]),
 
   getInterface: function dl_gi(aIID) {
     if (aIID.equals(Ci.nsIAuthPrompt) ||
         aIID.equals(Ci.nsIAuthPrompt2)) {
       var ww =
         Cc["@mozilla.org/embedcomp/window-watcher;1"]
           .getService(Ci.nsIPromptFactory);
       return ww.getPrompt(this.window, aIID);
@@ -1179,23 +1173,18 @@ function openURL(aURL) {
 
     var loadListener = {
       onStartRequest: function ll_start(aRequest, aContext) {
         appstartup.enterLastWindowClosingSurvivalArea();
       },
       onStopRequest: function ll_stop(aRequest, aContext, aStatusCode) {
         appstartup.exitLastWindowClosingSurvivalArea();
       },
-      QueryInterface: function ll_QI(iid) {
-        if (iid.equals(Ci.nsISupports) ||
-            iid.equals(Ci.nsIRequestObserver) ||
-            iid.equals(Ci.nsISupportsWeakReference))
-          return this;
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      }
+      QueryInterface: ChromeUtils.generateQI(["nsIRequestObserver",
+                                              "nsISupportsWeakReference"]),
     };
     loadgroup.groupObserver = loadListener;
 
     var uriListener = {
       onStartURIOpen(uri) { return false; },
       doContent(ctype, preferred, request, handler) { return false; },
       isPreferred(ctype, desired) { return false; },
       canHandleContent(ctype, preferred, desired) { return false; },
--- a/toolkit/modules/CertUtils.jsm
+++ b/toolkit/modules/CertUtils.jsm
@@ -199,23 +199,18 @@ BadCertHandler.prototype = {
   },
 
   // nsIInterfaceRequestor
   getInterface(iid) {
     return this.QueryInterface(iid);
   },
 
   // nsISupports
-  QueryInterface(iid) {
-    if (!iid.equals(Ci.nsIChannelEventSink) &&
-        !iid.equals(Ci.nsIInterfaceRequestor) &&
-        !iid.equals(Ci.nsISupports))
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    return this;
-  }
+  QueryInterface: ChromeUtils.generateQI(["nsIChannelEventSink",
+                                          "nsIInterfaceRequestor"]),
 };
 
 var CertUtils = {
   BadCertHandler,
   checkCert,
   readCertPrefs,
   validateCert,
 };
--- a/toolkit/modules/FinderHighlighter.jsm
+++ b/toolkit/modules/FinderHighlighter.jsm
@@ -1694,23 +1694,17 @@ FinderHighlighter.prototype = {
    * to work out which editor was being destroyed. Therefore, we create new
    * listeners on the fly, and cache them in sync with the editors they
    * listen to.
    */
   _createStateListener() {
     return {
       findbar: this,
 
-      QueryInterface(iid) {
-        if (iid.equals(Ci.nsIDocumentStateListener) ||
-            iid.equals(Ci.nsISupports))
-          return this;
-
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      },
+      QueryInterface: ChromeUtils.generateQI(["nsIDocumentStateListener"]),
 
       NotifyDocumentWillBeDestroyed() {
         this.findbar._onEditorDestruction(this);
       },
 
       // Unimplemented
       notifyDocumentCreated() {},
       notifyDocumentStateChanged(aDirty) {}
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -363,29 +363,16 @@ ChannelEventSink.init();
 // nsIAuthPrompt2 implementation for onAuthRequired
 class AuthRequestor {
   constructor(channel, httpObserver) {
     this.notificationCallbacks = channel.notificationCallbacks;
     this.loadGroupCallbacks = channel.loadGroup && channel.loadGroup.notificationCallbacks;
     this.httpObserver = httpObserver;
   }
 
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsISupports) ||
-        iid.equals(Ci.nsIInterfaceRequestor) ||
-        iid.equals(Ci.nsIAuthPromptProvider) ||
-        iid.equals(Ci.nsIAuthPrompt2)) {
-      return this;
-    }
-    try {
-      return this.notificationCallbacks.QueryInterface(iid);
-    } catch (e) {}
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-
   getInterface(iid) {
     if (iid.equals(Ci.nsIAuthPromptProvider) || iid.equals(Ci.nsIAuthPrompt2)) {
       return this;
     }
     try {
       return this.notificationCallbacks.getInterface(iid);
     } catch (e) {}
     throw Cr.NS_ERROR_NO_INTERFACE;
@@ -492,16 +479,22 @@ class AuthRequestor {
         }
         wrapper.authPromptForward = null;
         wrapper.authPromptCallback = null;
       },
     };
   }
 }
 
+AuthRequestor.prototype.QueryInterface = ChromeUtils.generateQI(
+  ["nsIInterfaceRequestor",
+   "nsIAuthPromptProvider",
+   "nsIAuthPrompt2"]);
+
+
 HttpObserverManager = {
   openingInitialized: false,
   modifyInitialized: false,
   examineInitialized: false,
   redirectInitialized: false,
   activityInitialized: false,
   needTracing: false,
   hasRedirects: false,
--- a/toolkit/mozapps/downloads/DownloadLastDir.jsm
+++ b/toolkit/mozapps/downloads/DownloadLastDir.jsm
@@ -35,23 +35,19 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 let nonPrivateLoadContext = Cc["@mozilla.org/loadcontext;1"].
                               createInstance(Ci.nsILoadContext);
 let privateLoadContext = Cc["@mozilla.org/privateloadcontext;1"].
                               createInstance(Ci.nsILoadContext);
 
 var observer = {
-  QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIObserver) ||
-        aIID.equals(Ci.nsISupports) ||
-        aIID.equals(Ci.nsISupportsWeakReference))
-      return this;
-    throw Cr.NS_NOINTERFACE;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIObserver",
+                                          "nsISupportsWeakReference"]),
+
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "last-pb-context-exited":
         gDownloadLastDirFile = null;
         break;
       case "browser:purge-session-history":
         gDownloadLastDirFile = null;
         if (Services.prefs.prefHasUserValue(LAST_DIR_PREF))
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -116,24 +116,18 @@ function nsUnknownContentTypeDialog() {
   this.mTitle    = "";
 }
 
 nsUnknownContentTypeDialog.prototype = {
   classID: Components.ID("{F68578EB-6EC2-4169-AE19-8C6243F0ABE1}"),
 
   nsIMIMEInfo: Ci.nsIMIMEInfo,
 
-  QueryInterface(iid) {
-    if (!iid.equals(Ci.nsIHelperAppLauncherDialog) &&
-        !iid.equals(Ci.nsITimerCallback) &&
-        !iid.equals(Ci.nsISupports)) {
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
-    return this;
-  },
+  QueryInterface: ChromeUtils.generateQI(["nsIHelperAppLauncherDialog",
+                                          "nsITimerCallback"]),
 
   // ---------- nsIHelperAppLauncherDialog methods ----------
 
   // show: Open XUL dialog using window watcher.  Since the dialog is not
   //       modal, it needs to be a top level window and the way to open
   //       one of those is via that route).
   show(aLauncher, aContext, aReason) {
     this.mLauncher = aLauncher;
--- a/toolkit/mozapps/extensions/amWebAPI.js
+++ b/toolkit/mozapps/extensions/amWebAPI.js
@@ -254,20 +254,12 @@ class WebAPI extends APIObject {
   }
 
   eventListenerRemoved(type) {
     this.listenerCount--;
     if (this.listenerCount == 0) {
       this.broker.setAddonListener(null);
     }
   }
-
-  QueryInterface(iid) {
-    if (iid.equals(WebAPI.classID) || iid.equals(Ci.nsISupports)
-        || iid.equals(Ci.nsIDOMGlobalPropertyInitializer)) {
-      return this;
-    }
-    return Cr.NS_ERROR_NO_INTERFACE;
-  }
 }
-
+WebAPI.prototype.QueryInterface = ChromeUtils.generateQI(["nsIDOMGlobalPropertyInitializer"]);
 WebAPI.prototype.classID = Components.ID("{8866d8e3-4ea5-48b7-a891-13ba0ac15235}");
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebAPI]);
--- a/toolkit/mozapps/update/content/updates.js
+++ b/toolkit/mozapps/update/content/updates.js
@@ -542,22 +542,17 @@ var gCheckingPage = {
       LOG("gCheckingPage", "onError - proceeding to error page");
       gUpdates.setUpdate(update);
       gUpdates.wiz.goTo("errors");
     },
 
     /**
      * See nsISupports.idl
      */
-    QueryInterface(aIID) {
-      if (!aIID.equals(Ci.nsIUpdateCheckListener) &&
-          !aIID.equals(Ci.nsISupports))
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      return this;
-    }
+    QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckListener"]),
   }
 };
 
 /**
  * The "No Updates Are Available" page
  */
 var gNoUpdatesPage = {
   /**