Bug 1476145 part 3. Stop using getInterface(nsIDOMWindowUtils) in browser/. r=gijs
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 24 Jul 2018 19:47:41 -0400
changeset 428177 6daa67c0cae427dc8e514d5f1beea9f71ee4d8ef
parent 428176 9e6977be54558ef6f5309ff0cb8577e39122c1e2
child 428178 640fd7808af52f03ecfac63c6eaf7af0634b61fb
push id105638
push userbzbarsky@mozilla.com
push dateTue, 24 Jul 2018 23:48:05 +0000
treeherdermozilla-inbound@2e9e04da5cb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs
bugs1476145
milestone63.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 1476145 part 3. Stop using getInterface(nsIDOMWindowUtils) in browser/. r=gijs
browser/base/content/browser-fullScreenAndPointerLock.js
browser/base/content/browser-pageActions.js
browser/base/content/browser-places.js
browser/base/content/browser-webrender.js
browser/base/content/browser.js
browser/base/content/content-refreshblocker.js
browser/base/content/nsContextMenu.js
browser/base/content/tab-content.js
browser/base/content/tabbrowser.js
browser/base/content/tabbrowser.xml
browser/base/content/test/general/browser_documentnavigation.js
browser/base/content/test/general/browser_gestureSupport.js
browser/base/content/test/general/browser_save_video_frame.js
browser/base/content/test/general/browser_tab_dragdrop.js
browser/base/content/test/performance/browser_window_resize.js
browser/base/content/test/performance/head.js
browser/base/content/test/plugins/browser_CTP_context_menu.js
browser/base/content/test/plugins/browser_CTP_drag_drop.js
browser/base/content/test/plugins/browser_CTP_hide_overlay.js
browser/base/content/test/plugins/browser_CTP_iframe.js
browser/base/content/test/plugins/browser_blocking.js
browser/base/content/test/plugins/browser_bug787619.js
browser/base/content/test/plugins/browser_pluginnotification.js
browser/base/content/test/tabs/head.js
browser/base/content/test/urlbar/browser_page_action_menu.js
browser/base/content/test/urlbar/head.js
browser/base/content/urlbarBindings.xml
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/PanelMultiView.jsm
browser/components/customizableui/ScrollbarSampler.jsm
browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
browser/components/customizableui/test/head.js
browser/components/downloads/content/allDownloadsView.js
browser/components/downloads/test/browser/head.js
browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js
browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
browser/components/extensions/test/browser/browser_ext_sidebarAction.js
browser/components/nsBrowserGlue.js
browser/components/payments/test/PaymentTestUtils.jsm
browser/components/places/content/browserPlacesViews.js
browser/components/places/tests/browser/head.js
browser/components/search/content/search.xml
browser/components/search/test/browser_oneOffHeader.js
browser/components/search/test/browser_searchbar_openpopup.js
browser/components/sessionstore/ContentSessionStore.jsm
browser/components/sessionstore/SessionStorage.jsm
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js
browser/components/translation/TranslationDocument.jsm
browser/extensions/formautofill/FormAutofillHandler.jsm
browser/extensions/pocket/bootstrap.js
browser/extensions/screenshots/test/browser/browser_screenshots_ui_check.js
browser/extensions/webcompat-reporter/test/browser/head.js
browser/modules/ContentWebRTC.jsm
browser/modules/FormSubmitObserver.jsm
browser/modules/PluginContent.jsm
browser/modules/WindowsPreviewPerTab.jsm
browser/modules/test/browser/browser_PageActions.js
browser/tools/mozscreenshots/browser_screenshots_cropping.js
toolkit/modules/tests/modules/MockDocument.jsm
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -390,28 +390,28 @@ var FullScreen = {
         break;
     }
   },
 
   receiveMessage(aMessage) {
     let browser = aMessage.target;
     switch (aMessage.name) {
       case "DOMFullscreen:Request": {
-        this._windowUtils.remoteFrameFullscreenChanged(browser);
+        window.windowUtils.remoteFrameFullscreenChanged(browser);
         break;
       }
       case "DOMFullscreen:NewOrigin": {
         // Don't show the warning if we've already exited fullscreen.
         if (document.fullscreen) {
           PointerlockFsWarning.showFullScreen(aMessage.data.originNoSuffix);
         }
         break;
       }
       case "DOMFullscreen:Exit": {
-        this._windowUtils.remoteFrameFullscreenReverted();
+        window.windowUtils.remoteFrameFullscreenReverted();
         break;
       }
       case "DOMFullscreen:Painted": {
         Services.obs.notifyObservers(window, "fullscreen-painted");
         TelemetryStopwatch.finish("FULLSCREEN_CHANGE_MS");
         break;
       }
     }
@@ -487,21 +487,16 @@ var FullScreen = {
 
     document.documentElement.removeAttribute("inDOMFullscreen");
   },
 
   _isRemoteBrowser(aBrowser) {
     return gMultiProcessBrowser && aBrowser.getAttribute("remote") == "true";
   },
 
-  get _windowUtils() {
-    return window.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIDOMWindowUtils);
-  },
-
   getMouseTargetRect() {
     return this._mouseTargetRect;
   },
 
   // Event callbacks
   _expandCallback() {
     FullScreen.showNavToolbox();
   },
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -381,23 +381,21 @@ var BrowserPageActions = {
 
     // Try each of the following nodes in order, using the first that's visible.
     let potentialAnchorNodeIDs = [
       action && action.anchorIDOverride,
       action && this.urlbarButtonNodeIDForActionID(action.id),
       this.mainButtonNode.id,
       "identity-icon",
     ];
-    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
     for (let id of potentialAnchorNodeIDs) {
       if (id) {
         let node = document.getElementById(id);
         if (node && !node.hidden) {
-          let bounds = dwu.getBoundsWithoutFlushing(node);
+          let bounds = window.windowUtils.getBoundsWithoutFlushing(node);
           if (bounds.height > 0 && bounds.width > 0) {
             return node;
           }
         }
       }
     }
     let id = action ? action.id : "<no action>";
     throw new Error(`PageActions: No anchor node for ${id}`);
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1130,17 +1130,17 @@ var LibraryUI = {
         !window.toolbar.visible ||
         !this.COSMETIC_ANIMATIONS_ENABLED) {
       return;
     }
 
     let animatableBox = document.getElementById("library-animatable-box");
     let navBar = document.getElementById("nav-bar");
     let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
-    let dwu = window.getInterface(Ci.nsIDOMWindowUtils);
+    let dwu = window.windowUtils;
     let iconBounds = dwu.getBoundsWithoutFlushing(libraryIcon);
     let libraryBounds = dwu.getBoundsWithoutFlushing(libraryButton);
     let toolboxBounds = dwu.getBoundsWithoutFlushing(gNavToolbox);
 
     animatableBox.style.setProperty("--toolbox-y", toolboxBounds.y + "px");
     animatableBox.style.setProperty("--library-button-y", libraryBounds.y + "px");
     animatableBox.style.setProperty("--library-button-height", libraryBounds.height + "px");
     animatableBox.style.setProperty("--library-icon-x", iconBounds.x + "px");
@@ -1193,18 +1193,17 @@ var LibraryUI = {
           libraryButton.getAttribute("cui-areatype") == "menu-panel" ||
           libraryButton.getAttribute("overflowedItem") == "true" ||
           !libraryButton.closest("#nav-bar")) {
         return;
       }
 
       let animatableBox = document.getElementById("library-animatable-box");
       let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
-      let dwu = window.getInterface(Ci.nsIDOMWindowUtils);
-      let iconBounds = dwu.getBoundsWithoutFlushing(libraryIcon);
+      let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
 
       // Resizing the window will only have the ability to change the X offset of the
       // library button.
       animatableBox.style.setProperty("--library-icon-x", iconBounds.x + "px");
 
       LibraryUI._windowResizeRunning = false;
     });
   },
--- a/browser/base/content/browser-webrender.js
+++ b/browser/base/content/browser-webrender.js
@@ -8,13 +8,11 @@
 /**
  * Global browser interface with the WebRender backend.
  */
 var gWebRender = {
   /**
    * Trigger a WebRender capture of the current state into a local folder.
    */
   capture() {
-    window.QueryInterface(Ci.nsIInterfaceRequestor)
-          .getInterface(Ci.nsIDOMWindowUtils)
-          .wrCapture();
+    window.windowUtils.wrCapture();
   }
 };
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2557,23 +2557,21 @@ async function BrowserViewSourceOfDocume
   if (aArgsOrDocument instanceof Document) {
     let doc = aArgsOrDocument;
     // Deprecated API - callers should pass args object instead.
     if (Cu.isCrossProcessWrapper(doc)) {
       throw new Error("BrowserViewSourceOfDocument cannot accept a CPOW " +
                       "as a document.");
     }
 
-    let requestor = doc.defaultView
-                       .QueryInterface(Ci.nsIInterfaceRequestor);
-    let browser = requestor.getInterface(Ci.nsIWebNavigation)
-                           .QueryInterface(Ci.nsIDocShell)
-                           .chromeEventHandler;
-    let outerWindowID = requestor.getInterface(Ci.nsIDOMWindowUtils)
-                                 .outerWindowID;
+    let win = doc.defaultView;
+    let browser = win.getInterface(Ci.nsIWebNavigation)
+                     .QueryInterface(Ci.nsIDocShell)
+                     .chromeEventHandler;
+    let outerWindowID = win.windowUtils.outerWindowID;
     let URL = browser.currentURI.spec;
     args = { browser, outerWindowID, URL };
   } else {
     args = aArgsOrDocument;
   }
 
   // Check if external view source is enabled.  If so, try it.  If it fails,
   // fallback to internal view source.
@@ -3244,24 +3242,22 @@ function BrowserReloadWithFlags(reloadFl
   // "newURL" load, since we're using loadURI, but hopefully
   // that's rare enough to not matter.
   maybeRecordAbandonmentTelemetry(gBrowser.selectedTab, "reload");
 
   // Reset temporary permissions on the current tab. This is done here
   // because we only want to reset permissions on user reload.
   SitePermissions.clearTemporaryPermissions(gBrowser.selectedBrowser);
 
-  let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIDOMWindowUtils);
+  let handlingUserInput = window.windowUtils.isHandlingUserInput;
 
   gBrowser.selectedBrowser
           .messageManager
           .sendAsyncMessage("Browser:Reload",
-                            { flags: reloadFlags,
-                              handlingUserInput: windowUtils.isHandlingUserInput });
+                            { flags: reloadFlags, handlingUserInput });
 }
 
 function getSecurityInfo(securityInfoAsString) {
   if (!securityInfoAsString)
     return null;
 
   const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                        .getService(Ci.nsISerializationHelper);
@@ -7710,17 +7706,17 @@ function duplicateTabIn(aTab, where, del
 var MousePosTracker = {
   _listeners: new Set(),
   _x: 0,
   _y: 0,
   _mostRecentEvent: null,
 
   get _windowUtils() {
     delete this._windowUtils;
-    return this._windowUtils = window.getInterface(Ci.nsIDOMWindowUtils);
+    return this._windowUtils = window.windowUtils;
   },
 
   /**
    * Registers a listener, and then waits for the next refresh
    * driver tick before running the listener to see if the
    * mouse is within the listener's target rect.
    *
    * @param listener (object)
--- a/browser/base/content/content-refreshblocker.js
+++ b/browser/base/content/content-refreshblocker.js
@@ -128,19 +128,17 @@ var RefreshBlocker = {
 
   /**
    * Notices when a refresh / reload was attempted. If, when running,
    * onLocationChange has not yet run, will stash the appropriate data
    * into the blockedWindows map to be sent when onLocationChange fires.
    */
   onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
     let win = aWebProgress.DOMWindow;
-    let outerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils)
-                           .outerWindowID;
+    let outerWindowID = win.windowUtils.outerWindowID;
 
     let data = {
       URI: aURI.spec,
       delay: aDelay,
       sameURI: aSameURI,
       outerWindowID,
     };
 
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1466,18 +1466,17 @@ nsContextMenu.prototype = {
 
   switchPageDirection: function CM_switchPageDirection() {
     this.browser.messageManager.sendAsyncMessage("SwitchDocumentDirection");
   },
 
   mediaCommand: function CM_mediaCommand(command, data) {
     let mm = this.browser.messageManager;
     let win = this.browser.ownerGlobal;
-    let windowUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindowUtils);
+    let windowUtils = win.windowUtils;
     mm.sendAsyncMessage("ContextMenu:MediaCommand",
                         {command,
                          data,
                          handlingUserInput: windowUtils.isHandlingUserInput},
                         {element: this.target});
   },
 
   copyMediaLocation() {
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -408,26 +408,18 @@ var DOMFullscreenHandler = {
     addEventListener("MozDOMFullscreen:Request", this);
     addEventListener("MozDOMFullscreen:Entered", this);
     addEventListener("MozDOMFullscreen:NewOrigin", this);
     addEventListener("MozDOMFullscreen:Exit", this);
     addEventListener("MozDOMFullscreen:Exited", this);
     this.init = null;
   },
 
-  get _windowUtils() {
-    if (!content) {
-      return null;
-    }
-    return content.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
-  },
-
   receiveMessage(aMessage) {
-    let windowUtils = this._windowUtils;
+    let windowUtils = content && content.windowUtils;
     switch (aMessage.name) {
       case "DOMFullscreen:Entered": {
         this._lastTransactionId = windowUtils.lastTransactionId;
         if (!windowUtils.handleFullscreenRequests() &&
             !content.document.fullscreenElement) {
           // If we don't actually have any pending fullscreen request
           // to handle, neither we have been in fullscreen, tell the
           // parent to just exit.
@@ -519,19 +511,17 @@ var UserContextIdNotifier = {
   }
 };
 
 UserContextIdNotifier.init();
 
 Services.obs.notifyObservers(this, "tab-content-frameloader-created");
 
 addMessageListener("AllowScriptsToClose", () => {
-  content.QueryInterface(Ci.nsIInterfaceRequestor)
-         .getInterface(Ci.nsIDOMWindowUtils)
-         .allowScriptsToClose();
+  content.windowUtils.allowScriptsToClose();
 });
 
 addEventListener("MozAfterPaint", function onFirstPaint() {
   removeEventListener("MozAfterPaint", onFirstPaint);
   sendAsyncMessage("Browser:FirstPaint");
 });
 
 // Remove this once bug 1397365 is fixed.
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1294,18 +1294,17 @@ window._gBrowser = {
     }
 
     aTab._labelIsContentTitle = aOptions.isContentTitle;
 
     if (aTab.getAttribute("label") == aLabel) {
       return false;
     }
 
-    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+    let dwu = window.windowUtils;
     let isRTL = dwu.getDirectionFromText(aLabel) == Ci.nsIDOMWindowUtils.DIRECTION_RTL;
 
     aTab.setAttribute("label", aLabel);
     aTab.setAttribute("labeldirection", isRTL ? "rtl" : "ltr");
 
     // Dispatch TabAttrModified event unless we're setting the label
     // before the TabOpen event was dispatched.
     if (!aOptions.beforeTabOpen) {
@@ -2619,18 +2618,17 @@ window._gBrowser = {
     // asynchronously closing tab.
     if (!animate &&
         aTab.closing) {
       this._endRemoveTab(aTab);
       return;
     }
 
     var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
-    let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindowUtils);
+    let windowUtils = window.windowUtils;
     // We have to sample the tab width now, since _beginRemoveTab might
     // end up modifying the DOM in such a way that aTab gets a new
     // frame created for it (for example, by updating the visually selected
     // state).
     let tabWidth = windowUtils.getBoundsWithoutFlushing(aTab).width;
 
     if (!this._beginRemoveTab(aTab, null, null, true, skipPermitUnload)) {
       TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_ANIM_MS", aTab);
@@ -2802,19 +2800,17 @@ window._gBrowser = {
       // sibling is going away.
       window.messageManager
             .broadcastAsyncMessage("Browser:HasSiblings", false);
     }
 
     if (aTab.linkedPanel) {
       if (!aAdoptedByTab && !gMultiProcessBrowser) {
         // Prevent this tab from showing further dialogs, since we're closing it
-        var windowUtils = browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                               .getInterface(Ci.nsIDOMWindowUtils);
-        windowUtils.disableDialogs();
+        browser.contentWindow.windowUtils.disableDialogs();
       }
 
       // Remove the tab's filter and progress listener.
       const filter = this._tabFilters.get(aTab);
 
       browser.webProgress.removeProgressListener(filter);
 
       const listener = this._tabListeners.get(aTab);
@@ -3048,19 +3044,17 @@ window._gBrowser = {
       return;
 
     // If this is the last tab of the window, hide the window
     // immediately without animation before the docshell swap, to avoid
     // about:blank being painted.
     let [closeWindow] = aOtherTab._endRemoveArgs;
     if (closeWindow) {
       let win = aOtherTab.ownerGlobal;
-      let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                   .getInterface(Ci.nsIDOMWindowUtils);
-      dwu.suppressAnimation(true);
+      win.windowUtils.suppressAnimation(true);
       // Only suppressing window animations isn't enough to avoid
       // an empty content area being painted.
       let baseWin = win.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell)
                        .QueryInterface(Ci.nsIDocShellTreeItem)
                        .treeOwner
                        .QueryInterface(Ci.nsIBaseWindow);
       baseWin.visibility = false;
@@ -4120,19 +4114,17 @@ window._gBrowser = {
     }
   },
 
   _generateUniquePanelID() {
     if (!this._uniquePanelIDCounter) {
       this._uniquePanelIDCounter = 0;
     }
 
-    let outerID = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDOMWindowUtils)
-                        .outerWindowID;
+    let outerID = window.windowUtils.outerWindowID;
 
     // We want panel IDs to be globally unique, that's why we include the
     // window ID. We switched to a monotonic counter as Date.now() lead
     // to random failures because of colliding IDs.
     return "panel-" + outerID + "-" + (++this._uniquePanelIDCounter);
   },
 
   destroy() {
@@ -4895,18 +4887,17 @@ var StatusPanel = {
     if (this.panel.getAttribute("type") == "status" &&
         this.panel.getAttribute("previoustype") == "status") {
       // Before updating the label, set the panel's current width as its
       // min-width to let the panel grow but not shrink and prevent
       // unnecessary flicker while loading pages. We only care about the
       // panel's width once it has been painted, so we can do this
       // without flushing layout.
       this.panel.style.minWidth =
-        window.QueryInterface(Ci.nsIInterfaceRequestor)
-              .getInterface(Ci.nsIDOMWindowUtils)
+        window.windowUtils
               .getBoundsWithoutFlushing(this.panel).width + "px";
     } else {
       this.panel.style.minWidth = "";
     }
 
     if (val) {
       this._mouseTargetRect = null;
       this._labelElement.value = val;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -349,19 +349,17 @@
                 this.setAttribute("closebuttons", "activetab");
                 return;
               }
 
               // Check if tab widths are below the threshold where we want to
               // remove close buttons from background tabs so that people don't
               // accidentally close tabs by selecting them.
               let rect = ele => {
-                return window.QueryInterface(Ci.nsIInterfaceRequestor)
-                             .getInterface(Ci.nsIDOMWindowUtils)
-                             .getBoundsWithoutFlushing(ele);
+                return window.windowUtils.getBoundsWithoutFlushing(ele);
               };
               let tab = this._getVisibleTabs()[gBrowser._numPinnedTabs];
               if (tab && rect(tab).width <= this._tabClipWidth) {
                 this.setAttribute("closebuttons", "activetab");
               } else {
                 this.removeAttribute("closebuttons");
               }
             });
@@ -1166,17 +1164,17 @@
         // Set the tab as the source of the drag, which ensures we have a stable
         // node to deliver the `dragend` event.  See bug 1345473.
         dt.addElement(tab);
 
         // Create a canvas to which we capture the current tab.
         // Until canvas is HiDPI-aware (bug 780362), we need to scale the desired
         // canvas size (in CSS pixels) to the window's backing resolution in order
         // to get a full-resolution drag image for use on HiDPI displays.
-        let windowUtils = window.getInterface(Ci.nsIDOMWindowUtils);
+        let windowUtils = window.windowUtils;
         let scale = windowUtils.screenPixelsPerCSSPixel / windowUtils.fullZoom;
         let canvas = this._dndCanvas;
         if (!canvas) {
           this._dndCanvas = canvas =
             document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
           canvas.style.width = "100%";
           canvas.style.height = "100%";
           canvas.mozOpaque = true;
--- a/browser/base/content/test/general/browser_documentnavigation.js
+++ b/browser/base/content/test/general/browser_documentnavigation.js
@@ -249,15 +249,15 @@ add_task(async function() {
                                false, "back focus on frameset frame urlbar");
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 // XXXndeakin add tests for browsers inside of panels
 
 function promiseButtonShown(id) {
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     let target = document.getElementById(id);
     let bounds = dwu.getBoundsWithoutFlushing(target);
     return bounds.width > 0 && bounds.height > 0;
   }, `Waiting for button ${id} to have non-0 size`);
 }
--- a/browser/base/content/test/general/browser_gestureSupport.js
+++ b/browser/base/content/test/general/browser_gestureSupport.js
@@ -13,18 +13,17 @@ var test_commandset;
 var test_prefBranch = "browser.gesture.";
 
 function test() {
   waitForExplicitFinish();
 
   // Disable the default gestures support during the test
   gGestureSupport.init(false);
 
-  test_utils = window.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIDOMWindowUtils);
+  test_utils = window.windowUtils;
 
   // Run the tests of "simple gesture" events generally
   test_EnsureConstantsAreDisjoint();
   test_TestEventListeners();
   test_TestEventCreation();
 
   // Reenable the default gestures support. The remaining tests target
   // the Firefox gesture functionality.
--- a/browser/base/content/test/general/browser_save_video_frame.js
+++ b/browser/base/content/test/general/browser_save_video_frame.js
@@ -39,18 +39,17 @@ function waitForTransferComplete() {
 }
 
 /**
  * Given some browser, loads a framescript that right-clicks
  * on the video1 element to spawn a contextmenu.
  */
 function rightClickVideo(browser) {
   let frame_script = () => {
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
 
     let document = content.document;
     let video = document.getElementById("video1");
     let rect = video.getBoundingClientRect();
 
     /* Synthesize a click in the center of the video. */
     let left = rect.left + (rect.width / 2);
     let top = rect.top + (rect.height / 2);
--- a/browser/base/content/test/general/browser_tab_dragdrop.js
+++ b/browser/base/content/test/general/browser_tab_dragdrop.js
@@ -12,18 +12,17 @@ var clickTest = async function(tab) {
   let clicks = await getClicks(tab);
 
   await ContentTask.spawn(tab.linkedBrowser, {}, function() {
     let target = content.document.body;
     let rect = target.getBoundingClientRect();
     let left = (rect.left + rect.right) / 2;
     let top = (rect.top + rect.bottom) / 2;
 
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   let newClicks = await getClicks(tab);
   is(newClicks, clicks + 1, "adding 1 more click on BODY");
 };
 
--- a/browser/base/content/test/performance/browser_window_resize.js
+++ b/browser/base/content/test/performance/browser_window_resize.js
@@ -49,18 +49,17 @@ async function toggleBookmarksToolbar(vi
  *        The height to resize the window to.
  * @returns Promise
  */
 async function resizeWindow(win, width, height) {
   let toolbarEvent =
     BrowserTestUtils.waitForEvent(win, "BookmarksToolbarVisibilityUpdated");
   let resizeEvent =
     BrowserTestUtils.waitForEvent(win, "resize");
-  let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = win.windowUtils;
   dwu.ensureDirtyRootFrame();
   win.resizeTo(width, height);
   await resizeEvent;
   forceImmediateToolbarOverflowHandling(win);
   await toolbarEvent;
 }
 
 /*
--- a/browser/base/content/test/performance/head.js
+++ b/browser/base/content/test/performance/head.js
@@ -9,18 +9,17 @@ ChromeUtils.defineModuleGetter(this, "Pl
 /**
  * This function can be called if the test needs to trigger frame dirtying
  * outside of the normal mechanism.
  *
  * @param win (dom window)
  *        The window in which the frame tree needs to be marked as dirty.
  */
 function dirtyFrame(win) {
-  let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = win.windowUtils;
   try {
     dwu.ensureDirtyRootFrame();
   } catch (e) {
     // If this fails, we should probably make note of it, but it's not fatal.
     info("Note: ensureDirtyRootFrame threw an exception:" + e);
   }
 }
 
@@ -230,18 +229,17 @@ async function ensureNoPreloadedBrowser(
  * debounce timeout to occur.
  */
 function forceImmediateToolbarOverflowHandling(win) {
   let overflowableToolbar = win.document.getElementById("nav-bar").overflowable;
   if (overflowableToolbar._lazyResizeHandler && overflowableToolbar._lazyResizeHandler.isArmed) {
     overflowableToolbar._lazyResizeHandler.disarm();
     // Ensure the root frame is dirty before resize so that, if we're
     // in the middle of a reflow test, we record the reflows deterministically.
-    let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIDOMWindowUtils);
+    let dwu = win.windowUtils;
     dwu.ensureDirtyRootFrame();
     overflowableToolbar._onLazyResize();
   }
 }
 
 async function prepareSettledWindow() {
   let win = await BrowserTestUtils.openNewBrowserWindow();
 
--- a/browser/base/content/test/plugins/browser_CTP_context_menu.js
+++ b/browser/base/content/test/plugins/browser_CTP_context_menu.js
@@ -35,18 +35,17 @@ add_task(async function() {
 
   // Display a context menu on the test plugin so we can test
   // activation menu options.
   await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
     let plugin = content.document.getElementById("test");
     let bounds = plugin.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("contextmenu", left, top, 2, 1, 0);
   });
 
   popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser);
   ok(popupNotification, "Should have a click-to-play notification");
   ok(popupNotification.dismissed, "notification should be dismissed");
 
   // fixes a occasional test timeout on win7 opt
--- a/browser/base/content/test/plugins/browser_CTP_drag_drop.js
+++ b/browser/base/content/test/plugins/browser_CTP_drag_drop.js
@@ -72,18 +72,17 @@ add_task(async function() {
   ok(!pluginInfo.activated, "plugin should not be activated");
 
   await ContentTask.spawn(gNewWindow.gBrowser.selectedBrowser, {}, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let bounds = plugin.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser).dismissed && gNewWindow.PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
 });
 
--- a/browser/base/content/test/plugins/browser_CTP_hide_overlay.js
+++ b/browser/base/content/test/plugins/browser_CTP_hide_overlay.js
@@ -33,18 +33,17 @@ add_task(async function() {
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
     let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon");
     let bounds = closeIcon.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
 
     Assert.ok(!overlay.classList.contains("visible"), "overlay should be hidden.");
   });
 });
 
 // Test that the overlay cannot be interacted with after the user closes the overlay
@@ -63,18 +62,17 @@ add_task(async function() {
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
     let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon");
     let closeIconBounds = closeIcon.getBoundingClientRect();
     let overlayBounds = overlay.getBoundingClientRect();
     let overlayLeft = (overlayBounds.left + overlayBounds.right) / 2;
     let overlayTop = (overlayBounds.left + overlayBounds.right) / 2 ;
     let closeIconLeft = (closeIconBounds.left + closeIconBounds.right) / 2;
     let closeIconTop = (closeIconBounds.top + closeIconBounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     // Simulate clicking on the close icon.
     utils.sendMouseEvent("mousedown", closeIconLeft, closeIconTop, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", closeIconLeft, closeIconTop, 0, 1, 0, false, 0, 0);
 
     // Simulate clicking on the overlay.
     utils.sendMouseEvent("mousedown", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0);
 
--- a/browser/base/content/test/plugins/browser_CTP_iframe.js
+++ b/browser/base/content/test/plugins/browser_CTP_iframe.js
@@ -32,17 +32,16 @@ add_task(async function() {
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
     Assert.ok(plugin && overlay.classList.contains("visible"),
       "Test 1, Plugin overlay should exist, not be hidden");
 
     let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon");
     let bounds = closeIcon.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = doc.defaultView.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
     Assert.ok(!overlay.classList.contains("visible"),
       "Test 1, Plugin overlay should exist, be hidden");
   });
 });
 
--- a/browser/base/content/test/plugins/browser_blocking.js
+++ b/browser/base/content/test/plugins/browser_blocking.js
@@ -68,18 +68,17 @@ add_task(async function() {
 
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
     let bounds = updateLink.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
   await promise;
 
   promise = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabClose", true);
   gBrowser.removeCurrentTab();
   await promise;
@@ -183,18 +182,17 @@ add_task(async function() {
   };
 
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let bounds = plugin.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
   await promise;
 
   ok(notification, "Test 18g, Should have a click-to-play notification");
   ok(!notification.dismissed, "Test 18g, notification should be open");
 
--- a/browser/base/content/test/plugins/browser_bug787619.js
+++ b/browser/base/content/test/plugins/browser_bug787619.js
@@ -36,18 +36,17 @@ add_task(async function() {
 
   // click the overlay to prompt
   let promise = promisePopupNotification("click-to-play-plugins");
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let plugin = content.document.getElementById("plugin");
     let bounds = plugin.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
   await promise;
 
   // check plugin state
   pluginInfo = await promiseForPluginInfo("plugin");
   ok(!pluginInfo.activated, "1b plugin should not be activated");
--- a/browser/base/content/test/plugins/browser_pluginnotification.js
+++ b/browser/base/content/test/plugins/browser_pluginnotification.js
@@ -88,18 +88,17 @@ add_task(async function() {
 
   // Simulate clicking the overlay
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let bounds = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   ok(!notification.dismissed, "A plugin notification should be shown.");
 
   clearAllPluginPermissions();
 });
@@ -230,18 +229,17 @@ add_task(async function() {
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let icon = doc.getAnonymousElementByAttribute(plugin, "class", "icon");
     let bounds = icon.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
   await promiseForCondition(condition);
 });
 
@@ -260,18 +258,17 @@ add_task(async function() {
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let text = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
     let bounds = text.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
   await promiseForCondition(condition);
 });
 
@@ -285,18 +282,17 @@ add_task(async function() {
 
   let pluginInfo = await promiseForPluginInfo("test");
   ok(!pluginInfo.activated, "Test 18g, Plugin should not be activated");
 
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed,
      "Test 19e, Doorhanger should start out dismissed");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", 50, 50, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", 50, 50, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed &&
     PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
   PopupNotifications.panel.firstChild.button.click();
@@ -367,18 +363,17 @@ add_task(async function() {
   ok(notification.dismissed, "Test 20c, Doorhanger should start out dismissed");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let bounds = plugin.getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = content.windowUtils;
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !notification.dismissed && !!PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
   PopupNotifications.panel.firstChild.button.click();
 
--- a/browser/base/content/test/tabs/head.js
+++ b/browser/base/content/test/tabs/head.js
@@ -84,18 +84,17 @@ async function play(tab, expectPlaying =
   if (expectPlaying) {
     await wait_for_tab_playing_event(tab, true);
   } else {
     await wait_for_tab_media_blocked_event(tab, true);
   }
 }
 
 function disable_non_test_mouse(disable) {
-  let utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+  let utils = window.windowUtils;
   utils.disableNonTestMouseEvents(disable);
 }
 
 function hover_icon(icon, tooltip) {
   disable_non_test_mouse(true);
 
   let popupShownPromise = BrowserTestUtils.waitForEvent(tooltip, "popupshown");
   EventUtils.synthesizeMouse(icon, 1, 1, {type: "mouseover"});
--- a/browser/base/content/test/urlbar/browser_page_action_menu.js
+++ b/browser/base/content/test/urlbar/browser_page_action_menu.js
@@ -593,18 +593,17 @@ add_task(async function sendToDevice_inU
     let bodyID =
       BrowserPageActions._panelViewNodeIDForActionID("sendToDevice", true) +
       "-body";
     let body = document.getElementById(bodyID);
     let deviceMenuItem = body.querySelector(".sendtab-target");
     Assert.notEqual(deviceMenuItem, null);
 
     // For good measure, wait until it's visible.
-    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+    let dwu = window.windowUtils;
     await BrowserTestUtils.waitForCondition(() => {
       let bounds = dwu.getBoundsWithoutFlushing(deviceMenuItem);
       return bounds.height > 0 && bounds.width > 0;
     }, "Waiting for first device menu item to appear");
 
     // Click it, which should cause the panel to close.
     let hiddenPromise =
       promisePanelHidden(BrowserPageActions._activatedActionPanelID);
--- a/browser/base/content/test/urlbar/head.js
+++ b/browser/base/content/test/urlbar/head.js
@@ -172,18 +172,17 @@ function promiseAutocompleteResultPopup(
     }
     win.gURLBar.controller.startSearch(inputText);
   }, win);
 
   return promiseSearchComplete(win, dontAnimate);
 }
 
 function promisePageActionPanelOpen() {
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     // Wait for the main page action button to become visible.  It's hidden for
     // some URIs, so depending on when this is called, it may not yet be quite
     // visible.  It's up to the caller to make sure it will be visible.
     info("Waiting for main page action button to have non-0 size");
     let bounds = dwu.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode);
     return bounds.width > 0 && bounds.height > 0;
   }).then(() => {
@@ -279,18 +278,17 @@ function promisePageActionViewShown() {
 }
 
 function promisePageActionViewChildrenVisible(panelViewNode) {
   return promiseNodeVisible(panelViewNode.firstChild.firstChild);
 }
 
 function promiseNodeVisible(node) {
   info(`promiseNodeVisible waiting, node.id=${node.id} node.localeName=${node.localName}\n`);
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     let bounds = dwu.getBoundsWithoutFlushing(node);
     if (bounds.width > 0 && bounds.height > 0) {
       info(`promiseNodeVisible OK, node.id=${node.id} node.localeName=${node.localName}\n`);
       return true;
     }
     return false;
   });
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -166,18 +166,17 @@ file, You can obtain one at http://mozil
         // Null out the one-offs' popup and textbox so that it cleans up its
         // internal state for both.  Most importantly, it removes the event
         // listeners that it added to both.
         this.popup.oneOffSearchButtons.popup = null;
         this.popup.oneOffSearchButtons.textbox = null;
       ]]></destructor>
 
       <field name="DOMWindowUtils">
-        window.QueryInterface(Ci.nsIInterfaceRequestor)
-              .getInterface(Ci.nsIDOMWindowUtils);
+        window.windowUtils;
       </field>
 
       <field name="scheme" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "scheme");
       </field>
 
       <field name="goButton">
         document.getAnonymousElementByAttribute(this, "anonid", "urlbar-go-button");
@@ -1816,19 +1815,17 @@ file, You can obtain one at http://mozil
       <handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/>
       <handler event="drop" phase="capturing" action="this.onDrop(event, this);"/>
       <handler event="select"><![CDATA[
         if (!Cc["@mozilla.org/widget/clipboard;1"]
                .getService(Ci.nsIClipboard)
                .supportsSelectionClipboard())
           return;
 
-        if (!window.QueryInterface(Ci.nsIInterfaceRequestor)
-                   .getInterface(Ci.nsIDOMWindowUtils)
-                   .isHandlingUserInput)
+        if (!window.windowUtils.isHandlingUserInput)
           return;
 
         var val = this._getSelectedValueForClipboard();
         if (!val)
           return;
 
         Cc["@mozilla.org/widget/clipboardhelper;1"]
           .getService(Ci.nsIClipboardHelper)
@@ -1888,18 +1885,17 @@ file, You can obtain one at http://mozil
     <implementation>
       <!--
         For performance reasons we want to limit the size of the text runs we
         build and show to the user.
       -->
       <field name="textRunsMaxLen">255</field>
 
       <field name="DOMWindowUtils">
-        window.QueryInterface(Ci.nsIInterfaceRequestor)
-              .getInterface(Ci.nsIDOMWindowUtils);
+        window.windowUtils;
       </field>
 
       <field name="_maxResults">0</field>
 
       <field name="_bundle" readonly="true">
         Cc["@mozilla.org/intl/stringbundle;1"].
           getService(Ci.nsIStringBundleService).
           createBundle("chrome://browser/locale/places/places.properties");
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -4517,17 +4517,17 @@ OverflowableToolbar.prototype = {
     let placements = gPlacements.get(this._toolbar.id);
     let win = this._target.ownerGlobal;
     while (this._list.firstChild) {
       let child = this._list.firstChild;
       let minSize = this._collapsed.get(child.id);
 
       if (!shouldMoveAllItems && minSize) {
         if (!targetWidth) {
-          let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+          let dwu = win.windowUtils;
           targetWidth = Math.floor(dwu.getBoundsWithoutFlushing(this._target).width);
         }
         if (targetWidth <= minSize) {
           break;
         }
       }
 
       this._collapsed.delete(child.id);
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -1642,17 +1642,17 @@ CustomizeMode.prototype = {
   },
 
   toggleDragSpace(aShouldShowDragSpace) {
     Services.prefs.setBoolPref(kExtraDragSpacePref, aShouldShowDragSpace);
   },
 
   get _dwu() {
     if (!this.__dwu) {
-      this.__dwu = this.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+      this.__dwu = this.window.windowUtils;
     }
     return this.__dwu;
   },
 
   get _dir() {
     if (!this.__dir) {
       this.__dir = this.window.getComputedStyle(this.document.documentElement).direction;
     }
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -173,18 +173,17 @@ var AssociatedToNode = class {
   }
 
   /**
    * nsIDOMWindowUtils for the window of this node.
    */
   get _dwu() {
     if (this.__dwu)
       return this.__dwu;
-    return this.__dwu = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIDOMWindowUtils);
+    return this.__dwu = this.window.windowUtils;
   }
 
   /**
    * Dispatches a custom event on this element.
    *
    * @param  {String}    eventName Name of the event to dispatch.
    * @param  {Object}    [detail]  Event detail object. Optional.
    * @param  {Boolean}   cancelable If the event can be canceled.
--- a/browser/components/customizableui/ScrollbarSampler.jsm
+++ b/browser/components/customizableui/ScrollbarSampler.jsm
@@ -33,18 +33,17 @@ var ScrollbarSampler = {
     let hwin = Services.appShell.hiddenDOMWindow;
     let hdoc = hwin.document.documentElement;
     let iframe = hwin.document.createElementNS("http://www.w3.org/1999/xhtml",
                                                "html:iframe");
     iframe.setAttribute("srcdoc", '<body style="overflow-y: scroll"></body>');
     hdoc.appendChild(iframe);
 
     let cwindow = iframe.contentWindow;
-    let utils = cwindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils);
+    let utils = cwindow.windowUtils;
 
     return new Promise(resolve => {
       cwindow.addEventListener("load", function(aEvent) {
         let sbWidth = {};
         try {
           utils.getScrollbarSize(true, sbWidth, {});
         } catch (e) {
           Cu.reportError("Could not sample scrollbar size: " + e + " -- " +
--- a/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
+++ b/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
@@ -14,18 +14,17 @@ function checkWrapper(id) {
   is(document.querySelectorAll("#wrapper-" + id).length, 1, "There should be exactly 1 wrapper for " + id + " in the customizing window.");
 }
 
 async function ensureVisible(node) {
   let isInPalette = node.parentNode.parentNode == gNavToolbox.palette;
   if (isInPalette) {
     node.scrollIntoView();
   }
-  window.QueryInterface(Ci.nsIInterfaceRequestor);
-  let dwu = window.getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   await BrowserTestUtils.waitForCondition(() => {
     let nodeBounds = dwu.getBoundsWithoutFlushing(node);
     if (isInPalette) {
       let paletteBounds = dwu.getBoundsWithoutFlushing(gNavToolbox.palette);
       if (!(nodeBounds.top >= paletteBounds.top && nodeBounds.bottom <= paletteBounds.bottom)) {
         return false;
       }
     }
--- a/browser/components/customizableui/test/head.js
+++ b/browser/components/customizableui/test/head.js
@@ -173,18 +173,17 @@ function todoAssertAreaPlacements(areaId
 function getAreaWidgetIds(areaId) {
   return CustomizableUI.getWidgetIdsInArea(areaId);
 }
 
 function simulateItemDrag(aToDrag, aTarget, aEvent = {}) {
   let ev = aEvent;
   if (ev == "end" || ev == "start") {
     let win = aTarget.ownerGlobal;
-    win.QueryInterface(Ci.nsIInterfaceRequestor);
-    const dwu = win.getInterface(Ci.nsIDOMWindowUtils);
+    const dwu = win.windowUtils;
     let bounds = dwu.getBoundsWithoutFlushing(aTarget);
     if (ev == "end") {
       ev = {clientX: bounds.right - 2, clientY: bounds.bottom - 2};
     } else {
       ev = {clientX: bounds.left + 2, clientY: bounds.top + 2};
     }
   }
   ev._domDispatchOnly = true;
@@ -473,15 +472,15 @@ function checkContextMenu(aContextMenu, 
 
 function waitForOverflowButtonShown(win = window) {
   let ov = win.document.getElementById("nav-bar-overflow-button");
   let icon = win.document.getAnonymousElementByAttribute(ov, "class", "toolbarbutton-icon");
   return waitForElementShown(icon);
 }
 function waitForElementShown(element) {
   let win = element.ownerGlobal;
-  let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = win.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     info("Waiting for overflow button to have non-0 size");
     let bounds = dwu.getBoundsWithoutFlushing(element);
     return bounds.width > 0 && bounds.height > 0;
   });
 }
--- a/browser/components/downloads/content/allDownloadsView.js
+++ b/browser/components/downloads/content/allDownloadsView.js
@@ -260,18 +260,17 @@ DownloadsPlacesView.prototype = {
 
     this._ensureVisibleTimer = setTimeout(() => {
       delete this._ensureVisibleTimer;
       if (!this._richlistbox.firstChild) {
         return;
       }
 
       let rlbRect = this._richlistbox.getBoundingClientRect();
-      let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
+      let winUtils = window.windowUtils;
       let nodes = winUtils.nodesFromRect(rlbRect.left, rlbRect.top,
                                          0, rlbRect.width, rlbRect.height, 0,
                                          true, false);
       // nodesFromRect returns nodes in z-index order, and for the same z-index
       // sorts them in inverted DOM order, thus starting from the one that would
       // be on top.
       let firstVisibleNode, lastVisibleNode;
       for (let node of nodes) {
--- a/browser/components/downloads/test/browser/head.js
+++ b/browser/components/downloads/test/browser/head.js
@@ -172,17 +172,17 @@ function openLibrary(aLeftPaneRoot) {
     waitForFocus(resolve, library);
   });
 }
 
 /**
  * Waits for a given button to become visible.
  */
 function promiseButtonShown(id) {
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     let target = document.getElementById(id);
     let bounds = dwu.getBoundsWithoutFlushing(target);
     return bounds.width > 0 && bounds.height > 0;
   }, `Waiting for button ${id} to have non-0 size`);
 }
 
 async function simulateDropAndCheck(win, dropTarget, urls) {
--- a/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js
+++ b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js
@@ -1,11 +1,9 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 add_task(async function test_policy_hardware_acceleration() {
-  let winUtils = Services.wm.getMostRecentWindow("").
-                 QueryInterface(Ci.nsIInterfaceRequestor).
-                 getInterface(Ci.nsIDOMWindowUtils);
+  let winUtils = Services.wm.getMostRecentWindow("").windowUtils;
   is(winUtils.layerManagerType, "Basic", "Hardware acceleration disabled");
 });
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
@@ -160,17 +160,17 @@ add_task(async function browseraction_co
       gBrowser.removeTab(tab);
     }
 
     return menu;
   }
 
   function waitForElementShown(element) {
     let win = element.ownerGlobal;
-    let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    let dwu = win.windowUtils;
     return BrowserTestUtils.waitForCondition(() => {
       info("Waiting for overflow button to have non-0 size");
       let bounds = dwu.getBoundsWithoutFlushing(element);
       return bounds.width > 0 && bounds.height > 0;
     });
   }
 
   async function main(customizing) {
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction.js
@@ -146,17 +146,17 @@ add_task(async function sidebar_isOpen()
 
   info("Switch back to extension1's sidebar");
   SidebarUI.show(sidebar1ID);
   await extension1.awaitMessage("sidebar");
   await sendMessage(extension1, "isOpen", {result: true});
   await sendMessage(extension2, "isOpen", {result: false});
 
   info("Test passing a windowId parameter");
-  let windowId = window.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
+  let windowId = window.windowUtils.outerWindowID;
   let WINDOW_ID_CURRENT = -2;
   await sendMessage(extension1, "isOpen", {arg: {windowId}, result: true});
   await sendMessage(extension2, "isOpen", {arg: {windowId}, result: false});
   await sendMessage(extension1, "isOpen", {arg: {windowId: WINDOW_ID_CURRENT}, result: true});
   await sendMessage(extension2, "isOpen", {arg: {windowId: WINDOW_ID_CURRENT}, result: false});
 
   info("Open a new window");
   let newWin = open();
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -28,19 +28,17 @@ ChromeUtils.import("resource://gre/modul
     "chrome,all,dialog=no,extrachrome,menubar,resizable,scrollbars,status," +
     "location,toolbar,personalbar," +
     `left=${screenX},top=${screenY}`;
   let win = Services.ww.openWindow(null, "about:blank", null,
                                    browserWindowFeatures, null);
 
   // Hide the titlebar if the actual browser window will draw in it.
   if (Services.prefs.getBoolPref("browser.tabs.drawInTitlebar")) {
-    win.QueryInterface(Ci.nsIInterfaceRequestor)
-       .getInterface(Ci.nsIDOMWindowUtils)
-       .setChromeMargin(0, 2, 2, 2);
+    win.windowUtils.setChromeMargin(0, 2, 2, 2);
   }
 
   if (AppConstants.platform != "macosx") {
     // On Windows/Linux the position is in device pixels rather than CSS pixels.
     let scale = win.devicePixelRatio;
     if (scale > 1)
       win.moveTo(screenX / scale, screenY / scale);
   }
--- a/browser/components/payments/test/PaymentTestUtils.jsm
+++ b/browser/components/payments/test/PaymentTestUtils.jsm
@@ -81,19 +81,17 @@ var PaymentTestUtils = {
      * @param {PaymentMethodData[]} methodData
      * @param {PaymentDetailsInit} details
      * @param {PaymentOptions} options
      */
     createAndShowRequest: ({methodData, details, options}) => {
       const rq = new content.PaymentRequest(methodData, details, options);
       content.rq = rq; // assign it so we can retrieve it later
 
-      const handle = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindowUtils)
-                            .setHandlingUserInput(true);
+      const handle = content.windowUtils.setHandlingUserInput(true);
       content.showPromise = rq.show();
 
       handle.destruct();
     },
   },
 
   DialogContentTasks: {
     getShippingOptions: () => {
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -1275,18 +1275,17 @@ PlacesToolbar.prototype = {
   },
 
   async _updateNodesVisibilityTimerCallback() {
     if (this._updatingNodesVisibility || window.closed) {
       return;
     }
     this._updatingNodesVisibility = true;
 
-    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+    let dwu = window.windowUtils;
 
     let scrollRect =
       await window.promiseDocumentFlushed(() => dwu.getBoundsWithoutFlushing(this._rootElt));
 
     let childOverflowed = false;
 
     // We're about to potentially update a bunch of nodes, so we do it
     // in a requestAnimationFrame so that other JS that's might execute
--- a/browser/components/places/tests/browser/head.js
+++ b/browser/components/places/tests/browser/head.js
@@ -243,19 +243,17 @@ var openContextMenuForContentSelector = 
   let contextPromise = BrowserTestUtils.waitForEvent(document.getElementById("contentAreaContextMenu"),
                                                      "popupshown");
   await ContentTask.spawn(browser, { selector }, async function(args) {
     let doc = content.document;
     let elt = doc.querySelector(args.selector);
     dump(`openContextMenuForContentSelector: found ${elt}\n`);
 
     /* Open context menu so chrome can access the element */
-    const domWindowUtils =
-      content.QueryInterface(Ci.nsIInterfaceRequestor)
-             .getInterface(Ci.nsIDOMWindowUtils);
+    const domWindowUtils = content.windowUtils;
     let rect = elt.getBoundingClientRect();
     let left = rect.left + rect.width / 2;
     let top = rect.top + rect.height / 2;
     domWindowUtils.sendMouseEvent("contextmenu", left, top, 2,
                                   1, 0, false, 0, 0, true);
   });
   await contextPromise;
 };
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -986,18 +986,17 @@
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="popupshowing"><![CDATA[
         // Force the panel to have the width of the searchbar rather than
         // the width of the textfield.
-        let DOMUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                             .getInterface(Ci.nsIDOMWindowUtils);
+        let DOMUtils = window.windowUtils;
         let textboxRect = DOMUtils.getBoundsWithoutFlushing(this.mInput);
         let inputRect = DOMUtils.getBoundsWithoutFlushing(this.mInput.inputField);
 
         // Ensure the panel is wide enough to fit at least 3 engines.
         let minWidth = Math.max(textboxRect.width,
                                 this.oneOffButtons.buttonWidth * 3);
         this.style.minWidth = Math.round(minWidth) + "px";
         // Alignment of the panel with the searchbar is obtained with negative
@@ -1437,18 +1436,17 @@
           // Skip this in compact mode, ie. for the urlbar.
           if (!this.compact)
             this._rebuildAddEngineList();
 
           // Check if the one-off buttons really need to be rebuilt.
           if (this._textbox) {
             // We can't get a reliable value for the popup width without flushing,
             // but the popup width won't change if the textbox width doesn't.
-            let DOMUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIDOMWindowUtils);
+            let DOMUtils = window.windowUtils;
             let textboxWidth =
               DOMUtils.getBoundsWithoutFlushing(this._textbox).width;
             // We can return early if neither the list of engines nor the panel
             // width has changed.
             if (this._engines && this._textboxWidth == textboxWidth) {
               return;
             }
             this._textboxWidth = textboxWidth;
@@ -1477,19 +1475,17 @@
 
           // There's one weird thing to guard against: when layout pixels
           // aren't an integral multiple of device pixels, the last button
           // of each row sometimes gets pushed to the next row, depending on the
           // panel and button widths.
           // This is likely because the clientWidth getter rounds the value, but
           // the panel's border width is not an integer.
           // As a workaround, decrement the width if the scale is not an integer.
-          let scale = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindowUtils)
-                            .screenPixelsPerCSSPixel;
+          let scale = window.windowUtils.screenPixelsPerCSSPixel;
           if (Math.floor(scale) != scale) {
             --panelWidth;
           }
 
           // The + 1 is because the last button doesn't have a right border.
           let enginesPerRow = Math.floor((panelWidth + 1) / this.buttonWidth);
           let buttonWidth = Math.floor(panelWidth / enginesPerRow);
           // There will be an emtpy area of:
--- a/browser/components/search/test/browser_oneOffHeader.js
+++ b/browser/components/search/test/browser_oneOffHeader.js
@@ -24,18 +24,17 @@ function getHeaderText() {
   let headerStrings = [];
   for (let label = headerChild; label; label = label.nextSibling) {
     headerStrings.push(label.value);
   }
   return headerStrings.join("");
 }
 
 const msg = isMac ? 5 : 1;
-const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+const utils = window.windowUtils;
 const scale = utils.screenPixelsPerCSSPixel;
 function synthesizeNativeMouseMove(aElement) {
   let rect = aElement.getBoundingClientRect();
   let win = aElement.ownerGlobal;
   let x = win.mozInnerScreenX + (rect.left + rect.right) / 2;
   let y = win.mozInnerScreenY + (rect.top + rect.bottom) / 2;
 
   // Wait for the mousemove event to occur before continuing.
--- a/browser/components/search/test/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser_searchbar_openpopup.js
@@ -7,18 +7,17 @@ var EventUtils = {};
 Services.scriptloader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
 
 const searchPopup = document.getElementById("PopupSearchAutoComplete");
 const kValues = ["long text", "long text 2", "long text 3"];
 
 const isWindows = Services.appinfo.OS == "WINNT";
 const mouseDown = isWindows ? 2 : 1;
 const mouseUp = isWindows ? 4 : 2;
-const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+const utils = window.windowUtils;
 const scale = utils.screenPixelsPerCSSPixel;
 
 function synthesizeNativeMouseClick(aElement) {
   let rect = aElement.getBoundingClientRect();
   let win = aElement.ownerGlobal;
   let x = win.mozInnerScreenX + (rect.left + rect.right) / 2;
   let y = win.mozInnerScreenY + (rect.top + rect.bottom) / 2;
 
--- a/browser/components/sessionstore/ContentSessionStore.jsm
+++ b/browser/components/sessionstore/ContentSessionStore.jsm
@@ -511,19 +511,17 @@ class SessionStorageListener extends Han
   handleEvent(event) {
     if (!this.mm.docShell) {
       return;
     }
 
     let {content} = this.mm;
 
     // How much data does DOMSessionStorage contain?
-    let usage = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils)
-                       .getStorageUsage(event.storageArea);
+    let usage = content.windowUtils.getStorageUsage(event.storageArea);
 
     // Don't store any data if we exceed the limit. Wipe any data we previously
     // collected so that we don't confuse websites with partial state.
     if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
       this.messageQueue.push("storage", () => null);
       this.removeEventListener();
       this.resetChanges();
       return;
--- a/browser/components/sessionstore/SessionStorage.jsm
+++ b/browser/components/sessionstore/SessionStorage.jsm
@@ -191,19 +191,17 @@ var SessionStorageInternal = {
       storage = null;
     }
 
     if (!storage || !storage.length) {
       return hostData;
     }
 
     // If the DOMSessionStorage contains too much data, ignore it.
-    let usage = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIDOMWindowUtils)
-                      .getStorageUsage(storage);
+    let usage = window.windowUtils.getStorageUsage(storage);
     if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
       return hostData;
     }
 
     for (let i = 0; i < storage.length; i++) {
       try {
         let key = storage.key(i);
         hostData[key] = storage.getItem(key);
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -4142,18 +4142,17 @@ var SessionStoreInternal = {
    * @param aSidebar
    *        Sidebar command
    */
   restoreDimensions: function ssi_restoreDimensions(aWindow, aWidth, aHeight, aLeft, aTop, aSizeMode, aSidebar) {
     var win = aWindow;
     var _this = this;
     function win_(aName) { return _this._getWindowDimension(win, aName); }
 
-    const dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                   .getInterface(Ci.nsIDOMWindowUtils);
+    const dwu = win.windowUtils;
     // find available space on the screen where this window is being placed
     let screen = gScreenManager.screenForRect(aLeft, aTop, aWidth, aHeight);
     if (screen) {
       let screenLeft = {}, screenTop = {}, screenWidth = {}, screenHeight = {};
       screen.GetAvailRectDisplayPix(screenLeft, screenTop, screenWidth, screenHeight);
       // screenX/Y are based on the origin of the screen's desktop-pixel coordinate space
       let screenLeftCss = screenLeft.value;
       let screenTopCss = screenTop.value;
--- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js
+++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js
@@ -20,18 +20,17 @@ const lameMultiWindowState = { windows: 
         { entries: [{ url: "http://example.com#4", triggeringPrincipal_base64 }], extData: { "uniq": r() } },
       ],
       selected: 3
     }
   ] };
 
 
 function getOuterWindowID(aWindow) {
-  return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
-         getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
+  return aWindow.windowUtils.outerWindowID;
 }
 
 function test() {
   /** Test for Bug 615394 - Session Restore should notify when it is beginning and ending a restore **/
   waitForExplicitFinish();
 
   // We'll track events per window so we are sure that they are each happening once
   // pre window.
--- a/browser/components/translation/TranslationDocument.jsm
+++ b/browser/components/translation/TranslationDocument.jsm
@@ -33,19 +33,17 @@ this.TranslationDocument.prototype = {
 
   /**
    * Initializes the object and populates
    * the roots lists.
    *
    * @param document  The document to be translated
    */
   _init(document) {
-    let window = document.defaultView;
-    let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindowUtils);
+    let winUtils = document.defaultView.windowUtils;
 
     // Get all the translation nodes in the document's body:
     // a translation node is a node from the document which
     // contains useful content for translation, and therefore
     // must be included in the translation process.
     let nodeList = winUtils.getTranslationNodes(document.body);
 
     let length = nodeList.length;
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -891,18 +891,17 @@ class FormAutofillHandler {
    * @param {FormLike} form Form that need to be auto filled
    */
   constructor(form) {
     this._updateForm(form);
 
     /**
      * A WindowUtils reference of which Window the form belongs
      */
-    this.winUtils = this.form.rootElement.ownerGlobal.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIDOMWindowUtils);
+    this.winUtils = this.form.rootElement.ownerGlobal.windowUtils;
 
     /**
      * Time in milliseconds since epoch when a user started filling in the form.
      */
     this.timeStartedFillingMS = null;
   }
 
   set focusedInput(element) {
--- a/browser/extensions/pocket/bootstrap.js
+++ b/browser/extensions/pocket/bootstrap.js
@@ -473,22 +473,22 @@ var PocketOverlay = {
       sib.parentNode.insertBefore(menu, sib);
     }
 
     // enable or disable reader button
     PocketReader.hidden = hidden;
   },
 
   addStyles(win) {
-    let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    let utils = win.windowUtils;
     utils.addSheet(this._cachedSheet, this._sheetType);
   },
 
   removeStyles(win) {
-    let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    let utils = win.windowUtils;
     utils.removeSheet(gPocketStyleURI, this._sheetType);
   }
 
 };
 
 // use enabled pref as a way for tests (e.g. test_contextmenu.html) to disable
 // the addon when running.
 function prefObserver(aSubject, aTopic, aData) {
--- a/browser/extensions/screenshots/test/browser/browser_screenshots_ui_check.js
+++ b/browser/extensions/screenshots/test/browser/browser_screenshots_ui_check.js
@@ -10,18 +10,17 @@ function checkElements(expectPresent, l)
 
 async function togglePageActionPanel() {
   await promiseOpenPageActionPanel();
   EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
   await promisePageActionPanelEvent("popuphidden");
 }
 
 function promiseOpenPageActionPanel() {
-  const dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+  const dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     // Wait for the main page action button to become visible.  It's hidden for
     // some URIs, so depending on when this is called, it may not yet be quite
     // visible.  It's up to the caller to make sure it will be visible.
     info("Waiting for main page action button to have non-0 size");
     const bounds = dwu.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode);
     return bounds.width > 0 && bounds.height > 0;
   }).then(() => {
@@ -50,18 +49,17 @@ function promisePageActionPanelEvent(eve
     panel.addEventListener(eventType, () => {
       executeSoon(resolve);
     }, { once: true });
   });
 }
 
 function promisePageActionViewChildrenVisible(panelViewNode) {
   info("promisePageActionViewChildrenVisible waiting for a child node to be visible");
-  const dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindowUtils);
+  const dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     const bodyNode = panelViewNode.firstChild;
     for (const childNode of bodyNode.childNodes) {
       const bounds = dwu.getBoundsWithoutFlushing(childNode);
       if (bounds.width > 0 && bounds.height > 0) {
         return true;
       }
     }
--- a/browser/extensions/webcompat-reporter/test/browser/head.js
+++ b/browser/extensions/webcompat-reporter/test/browser/head.js
@@ -12,18 +12,17 @@ function isButtonDisabled() {
   return document.getElementById(WC_PAGE_ACTION_ID).disabled;
 }
 
 function isURLButtonEnabled() {
   return document.getElementById(WC_PAGE_ACTION_URLBAR_ID) !== null;
 }
 
 function openPageActions() {
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     // Wait for the main page action button to become visible.  It's hidden for
     // some URIs, so depending on when this is called, it may not yet be quite
     // visible.  It's up to the caller to make sure it will be visible.
     info("Waiting for main page action button to have non-0 size");
     let bounds = dwu.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode);
     return bounds.width > 0 && bounds.height > 0;
   }).then(() => {
@@ -50,18 +49,17 @@ function promisePageActionPanelShown() {
     BrowserPageActions.panelNode.addEventListener("popupshown", () => {
       executeSoon(resolve);
     }, { once: true });
   });
 }
 
 function promisePageActionViewChildrenVisible(panelViewNode) {
   info("promisePageActionViewChildrenVisible waiting for a child node to be visible");
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     let bodyNode = panelViewNode.firstChild;
     for (let childNode of bodyNode.childNodes) {
       let bounds = dwu.getBoundsWithoutFlushing(childNode);
       if (bounds.width > 0 && bounds.height > 0) {
         return true;
       }
     }
--- a/browser/modules/ContentWebRTC.jsm
+++ b/browser/modules/ContentWebRTC.jsm
@@ -410,19 +410,17 @@ function getTabStateForContentWindow(aCo
 
   tabState.windowId = getInnerWindowIDForWindow(aContentWindow);
   tabState.documentURI = aContentWindow.document.documentURI;
 
   return tabState;
 }
 
 function getInnerWindowIDForWindow(aContentWindow) {
-  return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils)
-                       .currentInnerWindowID;
+  return aContentWindow.windowUtils.currentInnerWindowID;
 }
 
 function getMessageManagerForWindow(aContentWindow) {
   aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor);
 
   let docShell;
   try {
     // This throws NS_NOINTERFACE for closed tabs.
--- a/browser/modules/FormSubmitObserver.jsm
+++ b/browser/modules/FormSubmitObserver.jsm
@@ -198,31 +198,27 @@ FormSubmitObserver.prototype =
     } else {
       let win = aElement.ownerGlobal;
       let style = win.getComputedStyle(aElement);
       if (style.direction == "rtl") {
         offset = parseInt(style.paddingRight) + parseInt(style.borderRightWidth);
       } else {
         offset = parseInt(style.paddingLeft) + parseInt(style.borderLeftWidth);
       }
-      let zoomFactor = this._getWindowUtils().fullZoom;
+      let zoomFactor = this._content.windowUtils.fullZoom;
       panelData.offset = Math.round(offset * zoomFactor);
       panelData.position = "after_start";
     }
     this._mm.sendAsyncMessage("FormValidation:ShowPopup", panelData);
   },
 
   _hidePopup() {
     this._mm.sendAsyncMessage("FormValidation:HidePopup", {});
   },
 
-  _getWindowUtils() {
-    return this._content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
-  },
-
   _isRootDocumentEvent(aEvent) {
     if (this._content == null) {
       return true;
     }
     let target = aEvent.originalTarget;
     return (target == this._content.document ||
             (target.ownerDocument && target.ownerDocument == this._content.document));
   },
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -319,18 +319,17 @@ PluginContent.prototype = {
     let centerY = top + (bottom - top) / 2;
     let points = [[left, top],
                    [left, bottom],
                    [right, top],
                    [right, bottom],
                    [centerX, centerY]];
 
     let contentWindow = plugin.ownerGlobal;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
+    let cwu = contentWindow.windowUtils;
 
     for (let [x, y] of points) {
       if (x < 0 || y < 0) {
         continue;
       }
       let el = cwu.elementFromPoint(x, y, true, true);
       if (el === plugin) {
         return overlayDisplay;
@@ -652,18 +651,17 @@ PluginContent.prototype = {
       this._showClickToPlayNotification(plugin, true);
     event.stopPropagation();
     event.preventDefault();
     }
   },
 
   reshowClickToPlayNotification() {
     let contentWindow = this.global.content;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
+    let cwu = contentWindow.windowUtils;
     let plugins = cwu.plugins;
     for (let plugin of plugins) {
       let overlay = this.getPluginUI(plugin, "main");
       if (overlay)
         overlay.removeEventListener("click", this, true);
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       if (this.canActivatePlugin(objLoadingContent))
         this._handleClickToPlayEvent(plugin);
@@ -671,18 +669,17 @@ PluginContent.prototype = {
     this._showClickToPlayNotification(null, false);
   },
 
   /**
    * Activate the plugins that the user has specified.
    */
   activatePlugins(pluginInfo, newState) {
     let contentWindow = this.global.content;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
+    let cwu = contentWindow.windowUtils;
     let plugins = cwu.plugins;
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
 
     let pluginFound = false;
     for (let plugin of plugins) {
       plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       if (!this.isKnownPlugin(plugin)) {
         continue;
@@ -717,18 +714,17 @@ PluginContent.prototype = {
 
   _showClickToPlayNotification(plugin, showNow) {
     let plugins = [];
 
     // If plugin is null, that means the user has navigated back to a page with
     // plugins, and we need to collect all the plugins.
     if (plugin === null) {
       let contentWindow = this.content;
-      let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                             .getInterface(Ci.nsIDOMWindowUtils);
+      let cwu = contentWindow.windowUtils;
       // cwu.plugins may contain non-plugin <object>s, filter them out
       plugins = cwu.plugins.filter((p) =>
         p.getContentTypeForMIMEType(p.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
 
       if (plugins.length == 0) {
         this.removeNotification("click-to-play-plugins");
         return;
       }
@@ -814,18 +810,17 @@ PluginContent.prototype = {
         case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET:
         case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
           actions.set(action.permissionString, action);
           continue;
       }
     }
 
     // Remove plugins that are already active, or large enough to show an overlay.
-    let cwu = this.content.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIDOMWindowUtils);
+    let cwu = this.content.windowUtils;
     for (let plugin of cwu.plugins) {
       let info = this._getPluginInfo(plugin);
       if (!actions.has(info.permissionString)) {
         continue;
       }
       let fallbackType = info.fallbackType;
       if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
         actions.delete(info.permissionString);
@@ -962,18 +957,17 @@ PluginContent.prototype = {
   },
 
   NPAPIPluginProcessCrashed({pluginName, runID, state}) {
     let message =
       gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title",
                                             [pluginName], 1);
 
     let contentWindow = this.global.content;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
+    let cwu = contentWindow.windowUtils;
     let plugins = cwu.plugins;
 
     for (let plugin of plugins) {
       if (plugin instanceof Ci.nsIObjectLoadingContent &&
           plugin.runID == runID) {
         // The parent has told us that the plugin process has died.
         // It's possible that this content process hasn't yet noticed,
         // in which case we need to stash this data around until the
@@ -1048,18 +1042,17 @@ PluginContent.prototype = {
       // If a previous plugin on the page was too small and resulted in adding a
       // notification bar, then remove it because this plugin instance it big
       // enough to serve as in-content notification.
       this.hideNotificationBar("plugin-crashed");
       doc.mozNoPluginCrashedNotification = true;
 
       // Notify others that the crash reporter UI is now ready.
       // Currently, this event is only used by tests.
-      let winUtils = this.content.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIDOMWindowUtils);
+      let winUtils = this.content.windowUtils;
       let event = new this.content.CustomEvent("PluginCrashReporterDisplayed", {bubbles: true});
       winUtils.dispatchEventToChromeOnly(plugin, event);
     } else if (!doc.mozNoPluginCrashedNotification) {
       // If another plugin on the page was large enough to show our UI, we don't
       // want to show a notification bar.
       this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification",
                                    { messageString: message, pluginID: runID });
       // Remove the notification when the page is reloaded.
@@ -1067,18 +1060,17 @@ PluginContent.prototype = {
         this.hideNotificationBar("plugin-crashed");
       });
     }
   },
 
   NPAPIPluginCrashReportSubmitted({ runID, state }) {
     this.pluginCrashData.delete(runID);
     let contentWindow = this.global.content;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
+    let cwu = contentWindow.windowUtils;
     let plugins = cwu.plugins;
 
     for (let plugin of plugins) {
       if (plugin instanceof Ci.nsIObjectLoadingContent &&
           plugin.runID == runID) {
         let statusDiv = this.getPluginUI(plugin, "submitStatus");
         statusDiv.setAttribute("status", state);
       }
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -190,17 +190,17 @@ PreviewController.prototype = {
     // from nsIContentViewer due to conversion through appUnits.
     // We do -not- want screenPixelsPerCSSPixel here, because that would -also-
     // incorporate any scaling that is applied due to hi-dpi resolution options.
     return this.tab.linkedBrowser.fullZoom;
   },
 
   get screenPixelsPerCSSPixel() {
     let chromeWin = this.tab.ownerGlobal;
-    let windowUtils = chromeWin.getInterface(Ci.nsIDOMWindowUtils);
+    let windowUtils = chromeWin.windowUtils;
     return windowUtils.screenPixelsPerCSSPixel;
   },
 
   get browserDims() {
     return this.tab.linkedBrowser.getBoundingClientRect();
   },
 
   cacheBrowserDims() {
--- a/browser/modules/test/browser/browser_PageActions.js
+++ b/browser/modules/test/browser/browser_PageActions.js
@@ -1672,18 +1672,17 @@ add_task(async function transient() {
 });
 
 
 function assertActivatedPageActionPanelHidden() {
   Assert.ok(!document.getElementById(BrowserPageActions._activatedActionPanelID));
 }
 
 function promiseOpenPageActionPanel() {
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     // Wait for the main page action button to become visible.  It's hidden for
     // some URIs, so depending on when this is called, it may not yet be quite
     // visible.  It's up to the caller to make sure it will be visible.
     info("Waiting for main page action button to have non-0 size");
     let bounds = dwu.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode);
     return bounds.width > 0 && bounds.height > 0;
   }).then(() => {
@@ -1743,18 +1742,17 @@ function promisePageActionViewShown() {
     let panelViewNode = event.originalTarget;
     await promisePageActionViewChildrenVisible(panelViewNode);
     return panelViewNode;
   });
 }
 
 function promisePageActionViewChildrenVisible(panelViewNode) {
   info("promisePageActionViewChildrenVisible waiting for a child node to be visible");
-  let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils);
+  let dwu = window.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     let bodyNode = panelViewNode.firstChild;
     for (let childNode of bodyNode.childNodes) {
       let bounds = dwu.getBoundsWithoutFlushing(childNode);
       if (bounds.width > 0 && bounds.height > 0) {
         return true;
       }
     }
--- a/browser/tools/mozscreenshots/browser_screenshots_cropping.js
+++ b/browser/tools/mozscreenshots/browser_screenshots_cropping.js
@@ -37,18 +37,17 @@ async function draw(window, src) {
 
 async function compareImages(window, expected, test) {
   const testCanvas = await draw(window, test);
   const expectedCanvas = await draw(window, expected);
 
   is(testCanvas.width, expectedCanvas.width, "The test and expected images must be the same size");
   is(testCanvas.height, expectedCanvas.height, "The test and expected images must be the same size");
 
-  const nsIDOMWindowUtils = window.getInterface(Ci.nsIDOMWindowUtils);
-  return nsIDOMWindowUtils.compareCanvases(expectedCanvas, testCanvas, {});
+  return window.windowUtils.compareCanvases(expectedCanvas, testCanvas, {});
 }
 
 async function cropAndCompare(window, src, expected, test, region, subregions) {
   await TestRunner._cropImage(window, src, region, subregions, test);
 
   return compareImages(window, expected, OS.Path.toFileURI(test));
 }
 
--- a/toolkit/modules/tests/modules/MockDocument.jsm
+++ b/toolkit/modules/tests/modules/MockDocument.jsm
@@ -51,21 +51,20 @@ const MockDocument = {
     Object.defineProperty(aElement, "ownerDocument", {
       value: document,
     });
   },
 
   mockOwnerGlobalProperty(aElement) {
     Object.defineProperty(aElement, "ownerGlobal", {
       value: {
-        QueryInterface: ChromeUtils.generateQI([Ci.nsIInterfaceRequestor]),
-        getInterface: () => ({
+        windowUtils: {
           addManuallyManagedState() {},
           removeManuallyManagedState() {},
-        }),
+        },
         UIEvent: Event,
         Event,
       },
       configurable: true,
     });
   },
 
   createTestDocumentFromFile(aDocumentURL, aFile) {