Merge latest green b2g-inbound changeset and mozilla-central
authorEd Morley <emorley@mozilla.com>
Mon, 28 Oct 2013 15:43:40 +0000
changeset 166300 2a74ccca63438869c3459a9c9ddf74402849b510
parent 166299 366cb465a55532504131a12019289284eda67a09 (current diff)
parent 166291 00cba0743231d56b55f5e266017538ed39e56c32 (diff)
child 166301 d4a27d8eda2864f11e7f9fb50b347d5f71ea015f
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.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
Merge latest green b2g-inbound changeset and mozilla-central
browser/base/content/test/general/browser_CTP_iframe.js
browser/base/content/test/general/plugin_iframe.html
js/src/jit/IonCompartment.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -13,9 +13,9 @@
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
-Bug 914270 needs a clobber since moving variables to moz.build always requires a clobber (bug 852814)
+Bug 918345 needs a clobber due to WebIDL binding dependency issues (bug 928195).
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -19,17 +19,16 @@
 #include "nsIAccessibleRelation.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIEditor.h"
 #include "nsIFormControl.h"
 #include "nsINameSpaceManager.h"
 #include "nsIPersistentProperties2.h"
 #include "nsISelectionController.h"
-#include "jsapi.h"
 #include "nsIServiceManager.h"
 #include "nsITextControlFrame.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::a11y;
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -723,16 +723,17 @@ pref("font.size.inflation.minTwips", 120
 // And disable it for lingering master-process UI.
 pref("font.size.inflation.disabledInMasterProcess", true);
 
 // Enable freeing dirty pages when minimizing memory; this reduces memory
 // consumption when applications are sent to the background.
 pref("memory.free_dirty_pages", true);
 
 pref("layout.imagevisibility.enabled", false);
+pref("layout.imagevisibility.enabled_for_browser_elements_only", true);
 pref("layout.imagevisibility.numscrollportwidths", 1);
 pref("layout.imagevisibility.numscrollportheights", 1);
 
 // Enable native identity (persona/browserid)
 pref("dom.identity.enabled", true);
 
 // Wait up to this much milliseconds when orientation changed
 pref("layers.orientation.sync.timeout", 1000);
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -1,28 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict"
 
 function debug(str) {
-  //dump("-*- ContentPermissionPrompt: " + s + "\n");
+  //dump("-*- ContentPermissionPrompt: " + str + "\n");
 }
 
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 const Cc = Components.classes;
 
-const PROMPT_FOR_UNKNOWN    = ["geolocation", "desktop-notification",
-                               "audio-capture"];
+const PROMPT_FOR_UNKNOWN = ["audio-capture",
+                            "desktop-notification",
+                            "geolocation",
+                            "video-capture"];
 // Due to privary issue, permission requests like GetUserMedia should prompt
 // every time instead of providing session persistence.
-const PERMISSION_NO_SESSION = ["audio-capture"];
+const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
+const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Webapps.jsm");
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
 Cu.import("resource://gre/modules/PermissionsTable.jsm");
 
@@ -36,206 +39,311 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "@mozilla.org/permissionSettings;1",
                                    "nsIDOMPermissionSettings");
 
 XPCOMUtils.defineLazyServiceGetter(this,
                                    "AudioManager",
                                    "@mozilla.org/telephony/audiomanager;1",
                                    "nsIAudioManager");
 
-function rememberPermission(aPermission, aPrincipal, aSession)
+/**
+ * aTypesInfo is an array of {permission, access, action, deny} which keeps
+ * the information of each permission. This arrary is initialized in
+ * ContentPermissionPrompt.prompt and used among functions.
+ *
+ * aTypesInfo[].permission : permission name
+ * aTypesInfo[].access     : permission name + request.access
+ * aTypesInfo[].action     : the default action of this permission
+ * aTypesInfo[].deny       : true if security manager denied this app's origin
+ *                           principal.
+ * Note:
+ *   aTypesInfo[].permission will be sent to prompt only when
+ *   aTypesInfo[].action is PROMPT_ACTION and aTypesInfo[].deny is false.
+ */
+function rememberPermission(aTypesInfo, aPrincipal, aSession)
 {
   function convertPermToAllow(aPerm, aPrincipal)
   {
     let type =
       permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
     if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
         (type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
-        PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
+        PROMPT_FOR_UNKNOWN.indexOf(aPerm) >= 0)) {
+      debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
       if (!aSession) {
         permissionManager.addFromPrincipal(aPrincipal,
                                            aPerm,
                                            Ci.nsIPermissionManager.ALLOW_ACTION);
-      } else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
+      } else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
         permissionManager.addFromPrincipal(aPrincipal,
                                            aPerm,
                                            Ci.nsIPermissionManager.ALLOW_ACTION,
                                            Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
       }
     }
   }
 
-  // Expand the permission to see if we have multiple access properties to convert
-  let access = PermissionsTable[aPermission].access;
-  if (access) {
-    for (let idx in access) {
-      convertPermToAllow(aPermission + "-" + access[idx], aPrincipal);
+  for (let i in aTypesInfo) {
+    // Expand the permission to see if we have multiple access properties
+    // to convert
+    let perm = aTypesInfo[i].permission;
+    let access = PermissionsTable[perm].access;
+    if (access) {
+      for (let idx in access) {
+        convertPermToAllow(perm + "-" + access[idx], aPrincipal);
+      }
+    } else {
+      convertPermToAllow(perm, aPrincipal);
     }
-  } else {
-    convertPermToAllow(aPermission, aPrincipal);
   }
 }
 
 function ContentPermissionPrompt() {}
 
 ContentPermissionPrompt.prototype = {
 
-  handleExistingPermission: function handleExistingPermission(request) {
-    let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
-                                                                   request.type;
-    let result = Services.perms.testExactPermissionFromPrincipal(request.principal, access);
-    if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
+  handleExistingPermission: function handleExistingPermission(request,
+                                                              typesInfo) {
+    typesInfo.forEach(function(type) {
+      type.action =
+        Services.perms.testExactPermissionFromPrincipal(request.principal,
+                                                        type.access);
+    });
+
+    // If all permissions are allowed already, call allow() without prompting.
+    let checkAllowPermission = function(type) {
+      if (type.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
+        return true;
+      }
+      return false;
+    }
+    if (typesInfo.every(checkAllowPermission)) {
+      debug("all permission requests are allowed");
       request.allow();
       return true;
     }
-    if (result == Ci.nsIPermissionManager.DENY_ACTION ||
-        result == Ci.nsIPermissionManager.UNKNOWN_ACTION && PROMPT_FOR_UNKNOWN.indexOf(access) < 0) {
+
+    // If all permissions are DENY_ACTION or UNKNOWN_ACTION, call cancel()
+    // without prompting.
+    let checkDenyPermission = function(type) {
+      if (type.action == Ci.nsIPermissionManager.DENY_ACTION ||
+          type.action == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
+          PROMPT_FOR_UNKNOWN.indexOf(type.access) < 0) {
+        return true;
+      }
+      return false;
+    }
+    if (typesInfo.every(checkDenyPermission)) {
+      debug("all permission requests are denied");
       request.cancel();
       return true;
     }
     return false;
   },
 
-  handledByApp: function handledByApp(request) {
+  // multiple requests should be audio and video
+  checkMultipleRequest: function checkMultipleRequest(typesInfo) {
+    if (typesInfo.length == 1) {
+      return true;
+    } else if (typesInfo.length > 1) {
+      let checkIfAllowMultiRequest = function(type) {
+        return (ALLOW_MULTIPLE_REQUESTS.indexOf(type.access) !== -1);
+      }
+      if (typesInfo.every(checkIfAllowMultiRequest)) {
+        debug("legal multiple requests");
+        return true;
+      }
+    }
+
+    return false;
+  },
+
+  handledByApp: function handledByApp(request, typesInfo) {
     if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
         request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
       // This should not really happen
       request.cancel();
       return true;
     }
 
     let appsService = Cc["@mozilla.org/AppsService;1"]
                         .getService(Ci.nsIAppsService);
     let app = appsService.getAppByLocalId(request.principal.appId);
 
-    let url = Services.io.newURI(app.origin, null, null);
-    let principal = secMan.getAppCodebasePrincipal(url, request.principal.appId,
-                                                   /*mozbrowser*/false);
-    let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
-                                                                   request.type;
-    let result = Services.perms.testExactPermissionFromPrincipal(principal, access);
+    // Check each permission if it's denied by permission manager with app's
+    // URL.
+    let checkIfDenyAppPrincipal = function(type) {
+      let url = Services.io.newURI(app.origin, null, null);
+      let principal = secMan.getAppCodebasePrincipal(url,
+                                                     request.principal.appId,
+                                                     /*mozbrowser*/false);
+      let result = Services.perms.testExactPermissionFromPrincipal(principal,
+                                                                   type.access);
 
-    if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
-        result == Ci.nsIPermissionManager.PROMPT_ACTION) {
-      return false;
+      if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
+          result == Ci.nsIPermissionManager.PROMPT_ACTION) {
+        type.deny = false;
+      }
+      return type.deny;
+    }
+    if (typesInfo.every(checkIfDenyAppPrincipal)) {
+      request.cancel();
+      return true;
     }
 
-    request.cancel();
-    return true;
+    return false;
   },
 
-  handledByPermissionType: function handledByPermissionType(request) {
-    return permissionSpecificChecker.hasOwnProperty(request.type)
-             ? permissionSpecificChecker[request.type](request)
-             : false;
+  handledByPermissionType: function handledByPermissionType(request, typesInfo) {
+    for (let i in typesInfo) {
+      if (permissionSpecificChecker.hasOwnProperty(typesInfo[i].permission) &&
+          permissionSpecificChecker[typesInfo[i].permission](request)) {
+        return true;
+      }
+    }
+
+    return false;
   },
 
   _id: 0,
   prompt: function(request) {
     if (secMan.isSystemPrincipal(request.principal)) {
       request.allow();
-      return true;
+      return;
     }
 
-    if (this.handledByApp(request) ||
-        this.handledByPermissionType(request)) {
+    // Initialize the typesInfo and set the default value.
+    let typesInfo = [];
+    let perms = request.types.QueryInterface(Ci.nsIArray);
+    for (let idx = 0; idx < perms.length; idx++) {
+      let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
+      let tmp = {
+        permission: perm.type,
+        access: (perm.access && perm.access !== "unused") ?
+                  perm.type + "-" + perm.access : perm.type,
+        deny: true,
+        action: Ci.nsIPermissionManager.UNKNOWN_ACTION
+      };
+      typesInfo.push(tmp);
+    }
+    if (typesInfo.length == 0) {
+      request.cancel();
+      return;
+    }
+
+    if(!this.checkMultipleRequest(typesInfo)) {
+      request.cancel();
+      return;
+    }
+
+    if (this.handledByApp(request, typesInfo) ||
+        this.handledByPermissionType(request, typesInfo)) {
       return;
     }
 
     // returns true if the request was handled
-    if (this.handleExistingPermission(request))
+    if (this.handleExistingPermission(request, typesInfo)) {
        return;
+    }
+
+    // prompt PROMPT_ACTION request only.
+    typesInfo.forEach(function(aType, aIndex) {
+      if (aType.action != Ci.nsIPermissionManager.PROMPT_ACTION || aType.deny) {
+        typesInfo.splice(aIndex);
+      }
+    });
 
     let frame = request.element;
     let requestId = this._id++;
 
     if (!frame) {
-      this.delegatePrompt(request, requestId);
+      this.delegatePrompt(request, requestId, typesInfo);
       return;
     }
 
     frame = frame.wrappedJSObject;
     var cancelRequest = function() {
       frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
       request.cancel();
     }
 
     var self = this;
     var onVisibilityChange = function(evt) {
       if (evt.detail.visible === true)
         return;
 
-      self.cancelPrompt(request, requestId);
+      self.cancelPrompt(request, requestId, typesInfo);
       cancelRequest();
     }
 
     // If the request was initiated from a hidden iframe
     // we don't forward it to content and cancel it right away
     let domRequest = frame.getVisible();
     domRequest.onsuccess = function gv_success(evt) {
       if (!evt.target.result) {
         cancelRequest();
         return;
       }
 
       // Monitor the frame visibility and cancel the request if the frame goes
       // away but the request is still here.
       frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
 
-      self.delegatePrompt(request, requestId, function onCallback() {
+      self.delegatePrompt(request, requestId, typesInfo, function onCallback() {
         frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
       });
     };
 
     // Something went wrong. Let's cancel the request just in case.
     domRequest.onerror = function gv_error() {
       cancelRequest();
     }
   },
 
-  cancelPrompt: function(request, requestId) {
-    this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
+  cancelPrompt: function(request, requestId, typesInfo) {
+    this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
+                             typesInfo);
   },
 
-  delegatePrompt: function(request, requestId, callback) {
-    let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
-                                                                   request.type;
-    let principal = request.principal;
+  delegatePrompt: function(request, requestId, typesInfo, callback) {
 
-    this._permission = access;
-    this._uri = principal.URI.spec;
-    this._origin = principal.origin;
-
-    this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
+    this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
+                             function(type, remember) {
       if (type == "permission-allow") {
-        rememberPermission(request.type, principal, !remember);
+        rememberPermission(typesInfo, request.principal, !remember);
         if (callback) {
           callback();
         }
         request.allow();
         return;
       }
 
-      if (remember) {
-        Services.perms.addFromPrincipal(principal, access,
-                                        Ci.nsIPermissionManager.DENY_ACTION);
-      } else {
-        Services.perms.addFromPrincipal(principal, access,
-                                        Ci.nsIPermissionManager.DENY_ACTION,
-                                        Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
+      let addDenyPermission = function(type) {
+        debug("add " + type.permission +
+              " to permission manager with DENY_ACTION");
+        if (remember) {
+          Services.perms.addFromPrincipal(request.principal, type.access,
+                                          Ci.nsIPermissionManager.DENY_ACTION);
+        } else {
+          Services.perms.addFromPrincipal(request.principal, type.access,
+                                          Ci.nsIPermissionManager.DENY_ACTION,
+                                          Ci.nsIPermissionManager.EXPIRE_SESSION,
+                                          0);
+        }
       }
+      typesInfo.forEach(addDenyPermission);
 
       if (callback) {
         callback();
       }
       request.cancel();
     });
   },
 
-  sendToBrowserWindow: function(type, request, requestId, callback) {
+  sendToBrowserWindow: function(type, request, requestId, typesInfo, callback) {
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     let content = browser.getContentWindow();
     if (!content)
       return;
 
     if (callback) {
       content.addEventListener("mozContentEvent", function contentEvent(evt) {
         let detail = evt.detail;
@@ -248,20 +356,25 @@ ContentPermissionPrompt.prototype = {
     }
 
     let principal = request.principal;
     let isApp = principal.appStatus != Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED;
     let remember = (principal.appStatus == Ci.nsIPrincipal.APP_STATUS_PRIVILEGED ||
                     principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
                     ? true
                     : request.remember;
+    let permissions = [];
+    for (let i in typesInfo) {
+      debug("prompt " + typesInfo[i].permission);
+      permissions.push(typesInfo[i].permission);
+    }
 
     let details = {
       type: type,
-      permission: request.type,
+      permissions: permissions,
       id: requestId,
       origin: principal.origin,
       isApp: isApp,
       remember: remember
     };
 
     if (!isApp) {
       browser.shell.sendChromeEvent(details);
@@ -284,11 +397,10 @@ ContentPermissionPrompt.prototype = {
       request.cancel();
       return true;
     } else {
       return false;
     }
   };
 })();
 
-
 //module initialization
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -208,30 +208,22 @@ var gPluginHandler = {
     let pluginName = this.nameForSupportedPlugin(aMimeType);
     if (pluginName && "install" + os in this.supportedPlugins.plugins[pluginName]) {
       return true;
     }
     return false;
   },
 
   handleEvent : function(event) {
-    let plugin;
-    let doc;
+    let eventType = event.type;
+    let plugin = event.target;
+    let doc = plugin.ownerDocument;
 
-    let eventType = event.type;
-    if (eventType === "PluginRemoved") {
-      doc = event.target;
-    }
-    else {
-      plugin = event.target;
-      doc = plugin.ownerDocument;
-
-      if (!(plugin instanceof Ci.nsIObjectLoadingContent))
-        return;
-    }
+    if (!(plugin instanceof Ci.nsIObjectLoadingContent))
+      return;
 
     if (eventType == "PluginBindingAttached") {
       // The plugin binding fires this event when it is created.
       // As an untrusted event, ensure that this object actually has a binding
       // and make sure we don't handle it twice
       let overlay = this.getPluginUI(plugin, "main");
       if (!overlay || overlay._bindingHandled) {
         return;
@@ -303,23 +295,22 @@ var gPluginHandler = {
 
       case "PluginDisabled":
         let manageLink = this.getPluginUI(plugin, "managePluginsLink");
         this.addLinkClickCallback(manageLink, "managePlugins");
         shouldShowNotification = true;
         break;
 
       case "PluginInstantiated":
-      case "PluginRemoved":
         shouldShowNotification = true;
         break;
     }
 
     // Show the in-content UI if it's not too big. The crashed plugin handler already did this.
-    if (eventType != "PluginCrashed" && eventType != "PluginRemoved") {
+    if (eventType != "PluginCrashed") {
       let overlay = this.getPluginUI(plugin, "main");
       if (overlay != null) {
         if (!this.isTooSmall(plugin, overlay))
           overlay.style.visibility = "visible";
 
         plugin.addEventListener("overflow", function(event) {
           overlay.style.visibility = "hidden";
         });
@@ -331,17 +322,17 @@ var gPluginHandler = {
           }
         });
       }
     }
 
     // Only show the notification after we've done the isTooSmall check, so
     // that the notification can decide whether to show the "alert" icon
     if (shouldShowNotification) {
-      this._showClickToPlayNotification(browser);
+      this._showClickToPlayNotification(browser, plugin, false);
     }
   },
 
   isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) {
     return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
             Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
   },
 
@@ -557,17 +548,17 @@ var gPluginHandler = {
         aEvent.target.removeEventListener("click", gPluginHandler._overlayClickListener, true);
         return;
       }
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       // Have to check that the target is not the link to update the plugin
       if (!(aEvent.originalTarget instanceof HTMLAnchorElement) &&
           (aEvent.originalTarget.getAttribute('anonid') != 'closeIcon') &&
           aEvent.button == 0 && aEvent.isTrusted) {
-        gPluginHandler._showClickToPlayNotification(browser, plugin);
+        gPluginHandler._showClickToPlayNotification(browser, plugin, true);
         aEvent.stopPropagation();
         aEvent.preventDefault();
       }
     }
   },
 
   _handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) {
     let doc = aPlugin.ownerDocument;
@@ -602,17 +593,17 @@ var gPluginHandler = {
 
       // cleaning up: removes overlay iframe from the DOM
       let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
       if (iframe)
         previewContent.removeChild(iframe);
     }, true);
 
     if (!playPreviewInfo.ignoreCTP) {
-      gPluginHandler._showClickToPlayNotification(browser);
+      gPluginHandler._showClickToPlayNotification(browser, aPlugin, false);
     }
   },
 
   reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() {
     let browser = gBrowser.selectedBrowser;
     let contentWindow = browser.contentWindow;
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
@@ -620,24 +611,30 @@ var gPluginHandler = {
     for (let plugin of plugins) {
       let overlay = this.getPluginUI(plugin, "main");
       if (overlay)
         overlay.removeEventListener("click", gPluginHandler._overlayClickListener, true);
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       if (gPluginHandler.canActivatePlugin(objLoadingContent))
         gPluginHandler._handleClickToPlayEvent(plugin);
     }
-    gPluginHandler._showClickToPlayNotification(browser);
+    gPluginHandler._showClickToPlayNotification(browser, null, false);
   },
 
   _clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) {
     if (event == "showing") {
-      gPluginHandler._makeCenterActions(this);
       Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_SHOWN")
         .add(!this.options.primaryPlugin);
+      // Histograms always start at 0, even though our data starts at 1
+      let histogramCount = this.options.centerActions.size - 1;
+      if (histogramCount > 4) {
+        histogramCount = 4;
+      }
+      Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
+        .add(histogramCount);
     }
     else if (event == "dismissed") {
       // Once the popup is dismissed, clicking the icon should show the full
       // list again
       this.options.primaryPlugin = null;
     }
   },
 
@@ -650,96 +647,16 @@ var gPluginHandler = {
     try {
       if (principal.URI.host)
         return principal.URI.host;
     } catch (e) {}
 
     return principal.origin;
   },
 
-  _makeCenterActions: function PH_makeCenterActions(notification) {
-    let contentWindow = notification.browser.contentWindow;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
-
-    let principal = contentWindow.document.nodePrincipal;
-    // This matches the behavior of nsPermssionManager, used for display purposes only
-    let principalHost = this._getHostFromPrincipal(principal);
-
-    let centerActions = [];
-    let pluginsFound = new Set();
-    for (let plugin of cwu.plugins) {
-      plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-      if (plugin.getContentTypeForMIMEType(plugin.actualType) != Ci.nsIObjectLoadingContent.TYPE_PLUGIN) {
-        continue;
-      }
-
-      let pluginInfo = this._getPluginInfo(plugin);
-      if (pluginInfo.permissionString === null) {
-        Components.utils.reportError("No permission string for active plugin.");
-        continue;
-      }
-      if (pluginsFound.has(pluginInfo.permissionString)) {
-        continue;
-      }
-      pluginsFound.add(pluginInfo.permissionString);
-
-      // Add the per-site permissions and details URLs to pluginInfo here
-      // because they are more expensive to compute and so we avoid it in
-      // the tighter loop above.
-      let permissionObj = Services.perms.
-        getPermissionObject(principal, pluginInfo.permissionString, false);
-      if (permissionObj) {
-        pluginInfo.pluginPermissionHost = permissionObj.host;
-        pluginInfo.pluginPermissionType = permissionObj.expireType;
-      }
-      else {
-        pluginInfo.pluginPermissionHost = principalHost;
-        pluginInfo.pluginPermissionType = undefined;
-      }
-
-      let url;
-      // TODO: allow the blocklist to specify a better link, bug 873093
-      if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) {
-        url = Services.urlFormatter.formatURLPref("plugins.update.url");
-      }
-      else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
-        url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
-      }
-      else {
-        url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
-      }
-      pluginInfo.detailsLink = url;
-
-      centerActions.push(pluginInfo);
-    }
-
-    if (centerActions.length == 0) {
-      // TODO: this is a temporary band-aid to avoid broken doorhangers
-      // until bug 926605 is landed.
-      notification.options.centerActions = [];
-      setTimeout(() => PopupNotifications.remove(notification), 0);
-      return;
-    }
-
-    centerActions.sort(function(a, b) {
-      return a.pluginName.localeCompare(b.pluginName);
-    });
-
-    notification.options.centerActions = centerActions;
-
-    // Histograms always start at 0, even though our data starts at 1
-    let histogramCount = centerActions.length - 1;
-    if (histogramCount > 4) {
-      histogramCount = 4;
-    }
-    Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
-      .add(histogramCount);
-  },
-
   /**
    * Called from the plugin doorhanger to set the new permissions for a plugin
    * and activate plugins if necessary.
    * aNewState should be either "allownow" "allowalways" or "block"
    */
   _updatePluginPermission: function PH_setPermissionForPlugins(aNotification, aPluginInfo, aNewState) {
     let permission;
     let expireType;
@@ -793,81 +710,163 @@ var gPluginHandler = {
 
     // Manually activate the plugins that would have been automatically
     // activated.
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
     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);
       // canActivatePlugin will return false if this isn't a known plugin type,
       // so the pluginHost.getPermissionStringForType call is protected
       if (gPluginHandler.canActivatePlugin(plugin) &&
           aPluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
         let overlay = this.getPluginUI(plugin, "main");
         if (overlay) {
           overlay.removeEventListener("click", gPluginHandler._overlayClickListener, true);
         }
         plugin.playPlugin();
+        pluginFound = true;
       }
     }
+
+    // If there are no instances of the plugin on the page any more, what the
+    // user probably needs is for us to allow and then refresh.
+    if (!pluginFound) {
+      browser.reload();
+    }
   },
 
-  _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPrimaryPlugin) {
+  _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPlugin, aShowNow) {
     let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
+    let plugins = [];
+
+    // if aPlugin is null, that means the user has navigated back to a page with plugins, and we need
+    // to collect all the plugins
+    if (aPlugin === null) {
+      let contentWindow = aBrowser.contentWindow;
+      let contentDoc = aBrowser.contentDocument;
+      let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                             .getInterface(Ci.nsIDOMWindowUtils);
+      // cwu.plugins may contain non-plugin <object>s, filter them out
+      plugins = cwu.plugins.filter((plugin) =>
+        plugin.getContentTypeForMIMEType(plugin.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
+
+      if (plugins.length == 0) {
+        if (notification) {
+          PopupNotifications.remove(notification);
+        }
+        return;
+      }
+    } else {
+      plugins = [aPlugin];
+    }
+
+    // If this is a new notification, create a centerActions map, otherwise append
+    let centerActions;
+    if (notification) {
+      centerActions = notification.options.centerActions;
+    } else {
+      centerActions = new Map();
+    }
+
+    let principal = aBrowser.contentDocument.nodePrincipal;
+    let principalHost = this._getHostFromPrincipal(principal);
+
+    for (var plugin of plugins) {
+      let pluginInfo = this._getPluginInfo(plugin);
+      if (pluginInfo.permissionString === null) {
+        Cu.reportError("No permission string for active plugin.");
+        continue;
+      }
+      if (centerActions.has(pluginInfo.permissionString)) {
+        continue;
+      }
+
+      // Assume that plugins are hidden and then set override later
+      pluginInfo.hidden = true;
+
+      let overlay = this.getPluginUI(plugin, "main");
+      if (overlay && overlay.style.visibility != "hidden" && overlay.style.visibility != "") {
+        pluginInfo.hidden = false;
+      }
 
-    let contentWindow = aBrowser.contentWindow;
-    let contentDoc = aBrowser.contentDocument;
-    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowUtils);
-    // cwu.plugins may contain non-plugin <object>s, filter them out
-    let plugins = cwu.plugins.filter((plugin) =>
-      plugin.getContentTypeForMIMEType(plugin.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
-    if (plugins.length == 0) {
-      if (notification) {
-        PopupNotifications.remove(notification);
+      let permissionObj = Services.perms.
+        getPermissionObject(principal, pluginInfo.permissionString, false);
+      if (permissionObj) {
+        pluginInfo.pluginPermissionHost = permissionObj.host;
+        pluginInfo.pluginPermissionType = permissionObj.expireType;
+      }
+      else {
+        pluginInfo.pluginPermissionHost = principalHost;
+        pluginInfo.pluginPermissionType = undefined;
+      }
+
+      let url;
+      // TODO: allow the blocklist to specify a better link, bug 873093
+      if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) {
+        url = Services.urlFormatter.formatURLPref("plugins.update.url");
+      }
+      else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
+        url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
+      }
+      else {
+        url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
+      }
+      pluginInfo.detailsLink = url;
+      
+      centerActions.set(pluginInfo.permissionString, pluginInfo);
+    }
+
+    let pluginBlocked = false;
+    let pluginHidden = false;
+    for (let pluginInfo of centerActions.values()) {
+      let fallbackType = pluginInfo.fallbackType;
+      if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE ||
+          fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE ||
+          fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED) {
+        pluginBlocked = true;
+        pluginHidden = false;
+        break;
+      }
+      if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY && pluginInfo.hidden) {
+        pluginHidden = true;
+      }
+    }
+
+    let iconClasses = document.getElementById("plugins-notification-icon").classList;
+    iconClasses.toggle("plugin-blocked", pluginBlocked);
+    iconClasses.toggle("plugin-hidden", pluginHidden);
+
+    let primaryPluginPermission = null;
+    if (aShowNow) {
+      primaryPluginPermission = this._getPluginInfo(aPlugin).permissionString;
+    }
+
+    if (notification) {
+      // Don't modify the notification UI while it's on the screen, that would be
+      // jumpy and might allow clickjacking.
+      if (aShowNow) {
+        notification.options.primaryPlugin = primaryPluginPermission;
+        notification.reshow();
       }
       return;
     }
 
-    let icon = 'plugins-notification-icon';
-    for (let plugin of plugins) {
-      let fallbackType = plugin.pluginFallbackType;
-      if (fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE ||
-          fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE ||
-          fallbackType == plugin.PLUGIN_BLOCKLISTED) {
-        icon = 'blocked-plugins-notification-icon';
-        break;
-      }
-      if (fallbackType == plugin.PLUGIN_CLICK_TO_PLAY) {
-        let overlay = this.getPluginUI(plugin, "main");
-        if (!overlay || overlay.style.visibility == 'hidden') {
-          icon = 'alert-plugins-notification-icon';
-        }
-      }
-    }
-
-    let dismissed = notification ? notification.dismissed : true;
-    if (aPrimaryPlugin)
-      dismissed = false;
-
-    let primaryPluginPermission = null;
-    if (aPrimaryPlugin) {
-      primaryPluginPermission = this._getPluginInfo(aPrimaryPlugin).permissionString;
-    }
-
     let options = {
-      dismissed: dismissed,
+      dismissed: !aShowNow,
       eventCallback: this._clickToPlayNotificationEventCallback,
-      primaryPlugin: primaryPluginPermission
+      primaryPlugin: primaryPluginPermission,
+      centerActions: centerActions
     };
     PopupNotifications.show(aBrowser, "click-to-play-plugins",
-                            "", icon,
+                            "", "plugins-notification-icon",
                             null, null, options);
   },
 
   // Crashed-plugin observer. Notified once per plugin crash, before events
   // are dispatched to individual plugin instances.
   pluginCrashed : function(subject, topic, data) {
     let propertyBag = subject;
     if (!(propertyBag instanceof Ci.nsIPropertyBag2) ||
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -751,17 +751,16 @@ var gBrowserInit = {
 
     gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
 
     // Note that the XBL binding is untrusted
     gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
     gBrowser.addEventListener("PluginCrashed",         gPluginHandler, true);
     gBrowser.addEventListener("PluginOutdated",        gPluginHandler, true);
     gBrowser.addEventListener("PluginInstantiated",    gPluginHandler, true);
-    gBrowser.addEventListener("PluginRemoved",         gPluginHandler, true);
 
     gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
 
     Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
 
     window.addEventListener("AppCommand", HandleAppCommandEvent, true);
 
     messageManager.loadFrameScript("chrome://browser/content/content.js", true);
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -529,18 +529,16 @@
             <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="alert-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button"/>
           </box>
           <!-- Use onclick instead of normal popup= syntax since the popup
@@ -566,17 +564,17 @@
           <hbox id="urlbar-icons">
             <image id="page-report-button"
                    class="urlbar-icon"
                    hidden="true"
                    tooltiptext="&pageReportIcon.tooltip;"
                    onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
             <image id="star-button"
                    class="urlbar-icon"
-                   onclick="BookmarkingUI.onCommand(event);"/>
+                   onclick="if (event.button === 0) BookmarkingUI.onCommand(event);"/>
             <image id="go-button"
                    class="urlbar-icon"
                    tooltiptext="&goEndCap.tooltip;"
                    onclick="gURLBar.handleCommand(event);"/>
           </hbox>
           <toolbarbutton id="urlbar-go-button"
                          class="chromeclass-toolbar-additional"
                          onclick="gURLBar.handleCommand(event);"
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1272,17 +1272,17 @@ nsContextMenu.prototype = {
         this.sendMedia();
   },
 
   sendMedia: function() {
     MailIntegration.sendMessage(this.mediaURL, "");
   },
 
   playPlugin: function() {
-    gPluginHandler._showClickToPlayNotification(this.browser, this.target);
+    gPluginHandler._showClickToPlayNotification(this.browser, this.target, true);
   },
 
   hidePlugin: function() {
     gPluginHandler.hideClickToPlayOverlay(this.target);
   },
 
   // Generate email address and put it on clipboard.
   copyEmail: function() {
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -55,17 +55,16 @@ support-files =
   plugin_bug752516.html
   plugin_bug787619.html
   plugin_bug797677.html
   plugin_bug820497.html
   plugin_clickToPlayAllow.html
   plugin_clickToPlayDeny.html
   plugin_data_url.html
   plugin_hidden_to_visible.html
-  plugin_iframe.html
   plugin_small.html
   plugin_test.html
   plugin_test2.html
   plugin_test3.html
   plugin_two_types.html
   plugin_unknown.html
   print_postdata.sjs
   redirect_bug623155.sjs
@@ -82,17 +81,16 @@ support-files =
   test_no_mcb_on_http_site_img.css
   test_no_mcb_on_http_site_font.html
   test_no_mcb_on_http_site_font.css
   test_no_mcb_on_http_site_font2.html
   test_no_mcb_on_http_site_font2.css
 
 [browser_CTP_data_urls.js]
 [browser_CTP_drag_drop.js]
-[browser_CTP_iframe.js]
 [browser_CTP_nonplugins.js]
 [browser_CTP_resize.js]
 [browser_URLBarSetURI.js]
 [browser_aboutHealthReport.js]
 [browser_aboutHome.js]
 [browser_aboutSyncProgress.js]
 [browser_addKeywordSearch.js]
 [browser_addon_bar_aomlistener.js]
--- a/browser/base/content/test/general/browser_CTP_context_menu.js
+++ b/browser/base/content/test/general/browser_CTP_context_menu.js
@@ -66,37 +66,48 @@ function runAfterPluginBindingAttached(f
 function test1() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 1, Should have a click-to-play notification");
 
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 1, Plugin should not be activated");
 
-  window.document.addEventListener("popupshown", test2, false);
+  // When the popupshown DOM event is fired, the actual showing of the popup
+  // may still be pending. Clear the event loop before continuing so that
+  // subsequently-opened popups aren't cancelled by accident.
+  let goToNext = function() {
+    window.document.removeEventListener("popupshown", goToNext, false);
+    executeSoon(test2);
+  };
+  window.document.addEventListener("popupshown", goToNext, false);
   EventUtils.synthesizeMouseAtCenter(plugin,
                                      { type: "contextmenu", button: 2 },
                                      gTestBrowser.contentWindow);
 }
 
 function test2() {
-  window.document.removeEventListener("popupshown", test2, false);
   let activate = window.document.getElementById("context-ctp-play");
   ok(activate, "Test 2, Should have a context menu entry for activating the plugin");
 
+  let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(notification, "Test 2, Should have a click-to-play notification");
+  ok(notification.dismissed, "Test 2, notification should be dismissed");
+
   // Trigger the click-to-play popup
   activate.doCommand();
 
-  let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 2, Should have a click-to-play notification");
-  ok(!notification.dismissed, "Test 2, The click-to-play notification should not be dismissed");
+  waitForCondition(() => !notification.dismissed,
+		   test3, "Test 2, waited too long for context activation");
+}
 
+function test3() {
   // Activate the plugin
   PopupNotifications.panel.firstChild._primaryButton.click();
 
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  waitForCondition(() => objLoadingContent.activated, test3, "Waited too long for plugin to activate");
+  waitForCondition(() => objLoadingContent.activated, test4, "Waited too long for plugin to activate");
 }
 
-function test3() {
+function test4() {
   finishTest();
 }
--- a/browser/base/content/test/general/browser_CTP_data_urls.js
+++ b/browser/base/content/test/general/browser_CTP_data_urls.js
@@ -156,20 +156,20 @@ function test2a() {
 }
 
 function test2b() {
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 2b, Should have a click-to-play notification");
 
   // Simulate choosing "Allow now" for the test plugin
   notification.reshow();
-  is(notification.options.centerActions.length, 2, "Test 2b, Should have two types of plugin in the notification");
+  is(notification.options.centerActions.size, 2, "Test 2b, Should have two types of plugin in the notification");
 
   var centerAction = null;
-  for (var action of notification.options.centerActions) {
+  for (var action of notification.options.centerActions.values()) {
     if (action.pluginName == "Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "Test 2b, found center action for the Test plugin");
 
   var centerItem = null;
--- a/browser/base/content/test/general/browser_CTP_drag_drop.js
+++ b/browser/base/content/test/general/browser_CTP_drag_drop.js
@@ -59,23 +59,21 @@ function part4() {
   gNextTest = part5;
   gBrowser.selectedBrowser.contentDocument.location = gHttpTestRoot + "plugin_test.html";
 }
 
 function part5() {
   gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
   ok(PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should have a click-to-play notification in the initial tab");
 
-  gNextTest = part6;
   gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
-  gNewWindow.addEventListener("load", handleEvent, true);
+  waitForFocus(part6, gNewWindow);
 }
 
 function part6() {
-  gNewWindow.removeEventListener("load", handleEvent);
   let condition = function() PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser);
   waitForCondition(condition, part7, "Waited too long for click-to-play notification");
 }
 
 function part7() {
   ok(PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser), "Should have a click-to-play notification in the tab in the new window");
   ok(!PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should not have a click-to-play notification in the old window now");
 
deleted file mode 100644
--- a/browser/base/content/test/general/browser_CTP_iframe.js
+++ /dev/null
@@ -1,135 +0,0 @@
-var rootDir = getRootDirectory(gTestPath);
-const gTestRoot = rootDir;
-const gHttpTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
-
-var gTestBrowser = null;
-var gNextTest = null;
-var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
-var gPageLoads = 0;
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-// This listens for the next opened tab and checks it is of the right url.
-// opencallback is called when the new tab is fully loaded
-// closecallback is called when the tab is closed
-function TabOpenListener(url, opencallback, closecallback) {
-  this.url = url;
-  this.opencallback = opencallback;
-  this.closecallback = closecallback;
-
-  gBrowser.tabContainer.addEventListener("TabOpen", this, false);
-}
-
-TabOpenListener.prototype = {
-  url: null,
-  opencallback: null,
-  closecallback: null,
-  tab: null,
-  browser: null,
-
-  handleEvent: function(event) {
-    if (event.type == "TabOpen") {
-      gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
-      this.tab = event.originalTarget;
-      this.browser = this.tab.linkedBrowser;
-      gBrowser.addEventListener("pageshow", this, false);
-    } else if (event.type == "pageshow") {
-      if (event.target.location.href != this.url)
-        return;
-      gBrowser.removeEventListener("pageshow", this, false);
-      this.tab.addEventListener("TabClose", this, false);
-      var url = this.browser.contentDocument.location.href;
-      is(url, this.url, "Should have opened the correct tab");
-      this.opencallback(this.tab, this.browser.contentWindow);
-    } else if (event.type == "TabClose") {
-      if (event.originalTarget != this.tab)
-        return;
-      this.tab.removeEventListener("TabClose", this, false);
-      this.opencallback = null;
-      this.tab = null;
-      this.browser = null;
-      // Let the window close complete
-      executeSoon(this.closecallback);
-      this.closecallback = null;
-    }
-  }
-};
-
-function test() {
-  waitForExplicitFinish();
-  registerCleanupFunction(function() {
-    clearAllPluginPermissions();
-    Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
-  });
-  Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
-
-  var newTab = gBrowser.addTab();
-  gBrowser.selectedTab = newTab;
-  gTestBrowser = gBrowser.selectedBrowser;
-  gTestBrowser.addEventListener("load", pageLoad, true);
-
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
-
-  prepareTest(runAfterPluginBindingAttached(test1), gHttpTestRoot + "plugin_iframe.html");
-}
-
-function finishTest() {
-  clearAllPluginPermissions();
-  gTestBrowser.removeEventListener("load", pageLoad, true);
-  gBrowser.removeCurrentTab();
-  window.focus();
-  finish();
-}
-
-function pageLoad() {
-  // Wait for the iframe to be loaded as well.
-  if (gPageLoads++ < 1)
-    return;
-
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we then go on to test the states.
-  executeSoon(gNextTest);
-}
-
-function prepareTest(nextTest, url) {
-  gNextTest = nextTest;
-  gTestBrowser.contentWindow.location = url;
-}
-
-// Due to layout being async, "PluginBindAttached" may trigger later.
-// This wraps a function to force a layout flush, thus triggering it,
-// and schedules the function execution so they're definitely executed
-// afterwards.
-function runAfterPluginBindingAttached(func) {
-  return function() {
-    let doc = gTestBrowser.contentDocument.getElementById('frame').contentDocument;
-    let elems = doc.getElementsByTagName('embed');
-    if (elems.length < 1) {
-      elems = doc.getElementsByTagName('object');
-    }
-    elems[0].clientTop;
-    executeSoon(func);
-  };
-}
-
-// Test that we don't show a doorhanger after removing the last plugin
-// when the plugin was in an iframe.
-
-function test1() {
-  let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(popupNotification, "Test 1, Should have a click-to-play notification");
-
-  let frame = gTestBrowser.contentDocument.getElementById("frame");
-  frame.parentElement.removeChild(frame);
-
-  let condition = () => {
-    let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-    if (notification) {
-      notification.reshow();
-    }
-    return !notification;
-  }
-
-  waitForCondition(condition, finishTest, "Test1, Waited too long for notification too be removed");
-}
--- a/browser/base/content/test/general/browser_CTP_nonplugins.js
+++ b/browser/base/content/test/general/browser_CTP_nonplugins.js
@@ -144,17 +144,17 @@ function test1() {
 
 function test2() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 2, Should have a click-to-play notification");
 
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   plugin.parentNode.removeChild(plugin);
 
-  runAfterPluginRemoved(() => executeSoon(test3));
+  executeSoon(test3);
 }
 
 function test3() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(!popupNotification, "Test 3, Should not have a click-to-play notification");
+  ok(popupNotification, "Test 3, Should still have a click-to-play notification");
 
   finishTest();
 }
--- a/browser/base/content/test/general/browser_bug820497.js
+++ b/browser/base/content/test/general/browser_bug820497.js
@@ -35,25 +35,25 @@ function pluginBindingAttached() {
     var testplugin = doc.getElementById("test");
     ok(testplugin, "should have test plugin");
     var secondtestplugin = doc.getElementById("secondtest");
     ok(!secondtestplugin, "should not yet have second test plugin");
     var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
     ok(notification, "should have popup notification");
     // We don't set up the action list until the notification is shown
     notification.reshow();
-    is(notification.options.centerActions.length, 1, "should be 1 type of plugin in the popup notification");
+    is(notification.options.centerActions.size, 1, "should be 1 type of plugin in the popup notification");
     XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).addSecondPlugin();
   } else if (gNumPluginBindingsAttached == 2) {
     var doc = gTestBrowser.contentDocument;
     var testplugin = doc.getElementById("test");
     ok(testplugin, "should have test plugin");
     var secondtestplugin = doc.getElementById("secondtest");
     ok(secondtestplugin, "should have second test plugin");
     var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
     ok(notification, "should have popup notification");
     notification.reshow();
-    is(notification.options.centerActions.length, 2, "should be 2 types of plugin in the popup notification");
+    is(notification.options.centerActions.size, 2, "should be 2 types of plugin in the popup notification");
     finish();
   } else {
     ok(false, "if we've gotten here, something is quite wrong");
   }
 }
--- a/browser/base/content/test/general/browser_pluginnotification.js
+++ b/browser/base/content/test/general/browser_pluginnotification.js
@@ -174,17 +174,17 @@ function prepareTest5() {
 function test5() {
   info("test5");
   ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 5, Should not have displayed the missing plugin notification");
   let notification = PopupNotifications.getNotification("click-to-play-plugins");
   ok(notification, "Test 5: There should be a plugin notification for blocked plugins");
   ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default");
 
   notification.reshow();
-  is(notification.options.centerActions.length, 1, "Test 5: Only the blocked plugin should be present in the notification");
+  is(notification.options.centerActions.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
   ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
 
   ok(!gTestBrowser.missingPlugins, "Test 5, Should not be a missing plugin list");
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 5, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED");
 
@@ -436,20 +436,21 @@ function test18e() {
 function test18f() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 18f, Should have a click-to-play notification");
   ok(notification.dismissed, "Test 18f, notification should start dismissed");
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 18f, Plugin should not be activated");
 
-  // XXXBAD: this code doesn't do what you think it does! it is actually
-  // observing the "removed" event of the old notification, since we create
-  // a *new* one when the plugin is clicked.
-  notification.options.eventCallback = function() { executeSoon(test18g); };
+  var oldEventCallback = notification.options.eventCallback;
+  notification.options.eventCallback = function() {
+    oldEventCallback();
+    executeSoon(test18g);
+  };
   EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
 }
 
 function test18g() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 18g, Should have a click-to-play notification");
   ok(!notification.dismissed, "Test 18g, notification should be open");
   notification.options.eventCallback = null;
@@ -598,20 +599,20 @@ function test21a() {
     ok(rect.width == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
     ok(rect.height == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
     var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "Test 21a, Plugin with id=" + plugin.id + " should not be activated");
   }
 
   // we have to actually show the panel to get the bindings to instantiate
   notification.reshow();
-  is(notification.options.centerActions.length, 2, "Test 21a, Should have two types of plugin in the notification");
+  is(notification.options.centerActions.size, 2, "Test 21a, Should have two types of plugin in the notification");
 
   var centerAction = null;
-  for (var action of notification.options.centerActions) {
+  for (var action of notification.options.centerActions.values()) {
     if (action.pluginName == "Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "Test 21b, found center action for the Test plugin");
 
   var centerItem = null;
@@ -635,17 +636,17 @@ function test21a() {
   waitForCondition(condition, test21c, "Test 21b, Waited too long for plugin to activate");
 }
 
 function test21c() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 21c, Should have a click-to-play notification");
 
   notification.reshow();
-  ok(notification.options.centerActions.length == 2, "Test 21c, Should have one type of plugin in the notification");
+  ok(notification.options.centerActions.size == 2, "Test 21c, Should have one type of plugin in the notification");
 
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
   ok(rect.width == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
   ok(rect.height == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should be activated");
@@ -656,17 +657,17 @@ function test21c() {
     var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
     ok(rect.width == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
     ok(rect.height == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
     var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should not be activated");
   }
 
   var centerAction = null;
-  for (var action of notification.options.centerActions) {
+  for (var action of notification.options.centerActions.values()) {
     if (action.pluginName == "Second Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "Test 21d, found center action for the Second Test plugin");
 
   var centerItem = null;
--- a/browser/base/content/test/general/browser_plugins_added_dynamically.js
+++ b/browser/base/content/test/general/browser_plugins_added_dynamically.js
@@ -63,17 +63,17 @@ function testActivateAddSameTypePart2() 
 
   popupNotification.reshow();
   testActivateAddSameTypePart3();
 }
 
 function testActivateAddSameTypePart3() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   let centerAction = null;
-  for (let action of popupNotification.options.centerActions) {
+  for (let action of popupNotification.options.centerActions.values()) {
     if (action.pluginName == "Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "testActivateAddSameTypePart3: found center action for the Test plugin");
 
   let centerItem = null;
@@ -137,17 +137,17 @@ function testActivateAddDifferentTypePar
 
   // we have to actually show the panel to get the bindings to instantiate
   popupNotification.reshow();
   testActivateAddDifferentTypePart3();
 }
 
 function testActivateAddDifferentTypePart3() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  is(popupNotification.options.centerActions.length, 1, "Should be one plugin action");
+  is(popupNotification.options.centerActions.size, 1, "Should be one plugin action");
 
   let plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[0];
   ok(!plugin.activated, "testActivateAddDifferentTypePart3: plugin should not be activated");
 
   // "click" the button to activate the Test plugin
   PopupNotifications.panel.firstChild._primaryButton.click();
 
   let condition = function() plugin.activated;
deleted file mode 100644
--- a/browser/base/content/test/general/plugin_iframe.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body>
-<iframe src="plugin_test.html" id="frame" width="300" height="300">
-  This should load plugin_test.html
-</iframe>
-</body>
-</html>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1562,24 +1562,30 @@
         document.getAnonymousElementByAttribute(this, "anonid", "button-container")
       </field>
       <field name="_brandShortName">
         document.getElementById("bundle_brand").getString("brandShortName")
       </field>
       <field name="_items">[]</field>
       <constructor><![CDATA[
         const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-        for (let action of this.notification.options.centerActions) {
+        let sortedActions = [];
+        for (let action of this.notification.options.centerActions.values()) {
+          sortedActions.push(action);
+        }
+        sortedActions.sort((a, b) => a.pluginName.localeCompare(b.pluginName));
+
+        for (let action of sortedActions) {
           let item = document.createElementNS(XUL_NS, "row");
           item.setAttribute("class", "plugin-popupnotification-centeritem");
           item.action = action;
           this.appendChild(item);
           this._items.push(item);
         }
-        switch (this.notification.options.centerActions.length) {
+        switch (this._items.length) {
           case 0:
             PopupNotifications._dismiss();
             break;
           case 1:
             this._setState(this._states.SINGLE);
             break;
           default:
             if (this.notification.options.primaryPlugin) {
@@ -1634,17 +1640,17 @@
             }
             showBox.hidden = true;
           }
           this._setupLink(null);
         ]]></body>
       </method>
       <method name="_setupSingleState">
         <body><![CDATA[
-          var action = this.notification.options.centerActions[0];
+          var action = this._items[0].action;
           var host = action.pluginPermissionHost;
 
           let label, linkLabel, linkUrl, button1, button2;
 
           if (action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
             button1 = {
               label: "pluginBlockNow.label",
               accesskey: "pluginBlockNow.accesskey",
@@ -1798,41 +1804,41 @@
         <body><![CDATA[
           let methodName = aButton.getAttribute("action");
           this[methodName]();
         ]]></body>
       </method>
       <method name="_singleActivateNow">
         <body><![CDATA[
           gPluginHandler._updatePluginPermission(this.notification,
-            this.notification.options.centerActions[0],
+            this._items[0].action,
             "allownow");
           this._cancel();
         ]]></body>
       </method>
       <method name="_singleBlock">
         <body><![CDATA[
           gPluginHandler._updatePluginPermission(this.notification,
-            this.notification.options.centerActions[0],
+            this._items[0].action,
             "block");
             this._cancel();
         ]]></body>
       </method>
       <method name="_singleActivateAlways">
         <body><![CDATA[
           gPluginHandler._updatePluginPermission(this.notification,
-            this.notification.options.centerActions[0],
+            this._items[0].action,
             "allowalways");
           this._cancel();
         ]]></body>
       </method>
       <method name="_singleContinue">
         <body><![CDATA[
           gPluginHandler._updatePluginPermission(this.notification,
-            this.notification.options.centerActions[0],
+            this._items[0].action,
             "continue");
           this._cancel();
         ]]></body>
       </method>
       <method name="_multiAccept">
         <body><![CDATA[
           for (let item of this._items) {
             let action = item.action;
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1959,53 +1959,61 @@ ContentPermissionPrompt.prototype = {
     }
 
     this._showPrompt(aRequest, message, "pointerLock", actions, "pointerLock",
                      "pointerLock-notification-icon", null);
   },
 
   prompt: function CPP_prompt(request) {
 
+    // Only allow exactly one permission rquest here.
+    let types = request.types.QueryInterface(Ci.nsIArray);
+    if (types.length != 1) {
+      request.cancel();
+      return;
+    }
+    let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
+
     const kFeatureKeys = { "geolocation" : "geo",
                            "desktop-notification" : "desktop-notification",
                            "pointerLock" : "pointerLock",
                          };
 
     // Make sure that we support the request.
-    if (!(request.type in kFeatureKeys)) {
+    if (!(perm.type in kFeatureKeys)) {
         return;
     }
 
     var requestingPrincipal = request.principal;
     var requestingURI = requestingPrincipal.URI;
 
     // Ignore requests from non-nsIStandardURLs
     if (!(requestingURI instanceof Ci.nsIStandardURL))
       return;
 
     var autoAllow = false;
-    var permissionKey = kFeatureKeys[request.type];
+    var permissionKey = kFeatureKeys[perm.type];
     var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
 
     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
       request.cancel();
       return;
     }
 
     if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
       autoAllow = true;
       // For pointerLock, we still want to show a warning prompt.
-      if (request.type != "pointerLock") {
+      if (perm.type != "pointerLock") {
         request.allow();
         return;
       }
     }
 
     // Show the prompt.
-    switch (request.type) {
+    switch (perm.type) {
     case "geolocation":
       this._promptGeo(request);
       break;
     case "desktop-notification":
       this._promptWebNotifications(request);
       break;
     case "pointerLock":
       this._promptPointerLock(request, autoAllow);
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
@@ -59,31 +59,31 @@ function test() {
     is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
        "LastDir should be the expected display dir");
     // Check gDownloadLastDir value.
     is(gDownloadLastDir.file.path, aDisplayDir.path,
        "gDownloadLastDir should be the expected display dir");
 
     MockFilePicker.returnFiles = [aFile];
     MockFilePicker.displayDirectory = null;
-    aWin.getTargetFile(params, function() {
+    aWin.promiseTargetFile(params).then(function() {
       // File picker should start with expected display dir.
       is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
          "File picker should start with browser.download.lastDir");
       // browser.download.lastDir should be modified on not private windows
       is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
          "LastDir should be the expected last dir");
       // gDownloadLastDir should be usable outside of private windows
       is(gDownloadLastDir.file.path, aGlobalLastDir.path,
          "gDownloadLastDir should be the expected global last dir");
 
       gDownloadLastDir.cleanupPrivateFile();
       aWin.close();
       aCallback();
-    });
+    }).then(null, function() { ok(false); });
   }
 
   testOnWindow(false, function(win, downloadDir) {
     testDownloadDir(win, downloadDir, file1, tmpDir, dir1, dir1, function() {
       testOnWindow(true, function(win, downloadDir) {
         testDownloadDir(win, downloadDir, file2, dir1, dir1, dir2, function() {
           testOnWindow(false, function(win, downloadDir) {
             testDownloadDir(win, downloadDir, file3, dir1, dir3, dir3, finish);
--- a/browser/devtools/shadereditor/test/head.js
+++ b/browser/devtools/shadereditor/test/head.js
@@ -130,17 +130,17 @@ function once(aTarget, aEventName, aUseC
     }
   }
 
   return deferred.promise;
 }
 
 function waitForFrame(aDebuggee) {
   let deferred = promise.defer();
-  aDebuggee.mozRequestAnimationFrame(deferred.resolve);
+  aDebuggee.requestAnimationFrame(deferred.resolve);
   return deferred.promise;
 }
 
 function isApprox(aFirst, aSecond, aMargin = 1) {
   return Math.abs(aFirst - aSecond) <= aMargin;
 }
 
 function isApproxColor(aFirst, aSecond, aMargin) {
--- a/browser/devtools/shared/widgets/SideMenuWidget.jsm
+++ b/browser/devtools/shared/widgets/SideMenuWidget.jsm
@@ -482,17 +482,16 @@ function SideMenuGroup(aWidget, aName, a
     name.setAttribute("value", aName);
     name.setAttribute("crop", "end");
     name.setAttribute("flex", "1");
 
     // Show a checkbox before the content.
     if (aOptions.showCheckbox) {
       let checkbox = this._checkbox = makeCheckbox(title, { description: aName });
       checkbox.className = "side-menu-widget-group-checkbox";
-      checkbox.setAttribute("align", "start");
     }
 
     title.appendChild(name);
     target.appendChild(title);
     target.appendChild(list);
   }
   // Skip a few redundant nodes when no title is shown.
   else {
@@ -587,17 +586,16 @@ function SideMenuItem(aGroup, aContents,
 
     let target = this._target = this.document.createElement("vbox");
     target.className = "side-menu-widget-item-contents";
 
     // Show a checkbox before the content.
     if (aOptions.showCheckbox) {
       let checkbox = this._checkbox = makeCheckbox(container, aAttachment);
       checkbox.className = "side-menu-widget-item-checkbox";
-      checkbox.setAttribute("align", "start");
     }
 
     container.appendChild(target);
 
     // Show a horizontal arrow towards the content.
     if (aOptions.showArrow) {
       let arrow = this._arrow = this.document.createElement("hbox");
       arrow.className = "side-menu-widget-item-arrow";
--- a/browser/devtools/shared/widgets/widgets.css
+++ b/browser/devtools/shared/widgets/widgets.css
@@ -19,16 +19,21 @@
   overflow-x: hidden;
   overflow-y: auto;
 }
 
 .side-menu-widget-item-contents {
   -moz-user-focus: normal;
 }
 
+.side-menu-widget-group-checkbox .checkbox-label-box,
+.side-menu-widget-item-checkbox .checkbox-label-box {
+  display: none; /* See bug 669507 */
+}
+
 /* VariablesView */
 
 .variables-view-container {
   overflow-x: hidden;
   overflow-y: auto;
 }
 
 .variables-view-element-details:not([open]) {
--- a/browser/devtools/webconsole/test/browser_webconsole_property_provider.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_property_provider.js
@@ -26,14 +26,16 @@ function testPropertyProvider() {
   is (completion, null, "no match for 'window[1].acb");
 
   // A very advanced completion case.
   var strComplete =
     'function a() { }document;document.getElementById(window.locatio';
   completion = JSPropertyProvider(content, strComplete);
   ok(completion.matches.length == 2, "two matches found");
   ok(completion.matchProp == "locatio", "matching part is 'test'");
-  ok(completion.matches[0] == "location", "the first match is 'location'");
-  ok(completion.matches[1] == "locationbar", "the second match is 'locationbar'");
+  var matches = completion.matches;
+  matches.sort();
+  ok(matches[0] == "location", "the first match is 'location'");
+  ok(matches[1] == "locationbar", "the second match is 'locationbar'");
 
   finishTest();
 }
 
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,4 +1,4 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 0.8.629
+Current extension version is: 0.8.641
 
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -15,18 +15,18 @@
  * limitations under the License.
  */
 
 // Initializing PDFJS global object (if still undefined)
 if (typeof PDFJS === 'undefined') {
   (typeof window !== 'undefined' ? window : this).PDFJS = {};
 }
 
-PDFJS.version = '0.8.629';
-PDFJS.build = 'b16b3be';
+PDFJS.version = '0.8.641';
+PDFJS.build = '19485c3';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* Copyright 2012 Mozilla Foundation
@@ -6570,16 +6570,21 @@ var CanvasGraphics = (function CanvasGra
       }
       assert(group.bbox, 'Bounding box is required.');
 
       // Based on the current transform figure out how big the bounding box
       // will actually be.
       var bounds = Util.getAxialAlignedBoundingBox(
                     group.bbox,
                     currentCtx.mozCurrentTransform);
+      // Clip the bounding box to the current canvas.
+      bounds = Util.intersect(bounds, [0,
+                                       0,
+                                       currentCtx.canvas.width,
+                                       currentCtx.canvas.height]);
       // Use ceil in case we're between sizes so we don't create canvas that is
       // too small and make the canvas at least 1x1 pixels.
       var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
       var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1);
 
       var scratchCanvas = CachedCanvases.getCanvas(
         'groupAt' + this.groupLevel, drawnWidth, drawnHeight, true);
       var groupCtx = scratchCanvas.context;
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -15,18 +15,18 @@
  * limitations under the License.
  */
 
 // Initializing PDFJS global object (if still undefined)
 if (typeof PDFJS === 'undefined') {
   (typeof window !== 'undefined' ? window : this).PDFJS = {};
 }
 
-PDFJS.version = '0.8.629';
-PDFJS.build = 'b16b3be';
+PDFJS.version = '0.8.641';
+PDFJS.build = '19485c3';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* Copyright 2012 Mozilla Foundation
--- a/browser/extensions/pdfjs/content/web/viewer.html
+++ b/browser/extensions/pdfjs/content/web/viewer.html
@@ -218,17 +218,17 @@ limitations under the License.
           <menuitem id="contextLastPage" label="Last Page"
                     data-l10n-id="last_page"></menuitem>
           <menuitem id="contextPageRotateCw" label="Rotate Clockwise"
                     data-l10n-id="page_rotate_cw"></menuitem>
           <menuitem id="contextPageRotateCcw" label="Rotate Counter-Clockwise"
                     data-l10n-id="page_rotate_ccw"></menuitem>
         </menu>
 
-      <div id="viewerContainer">   
+        <div id="viewerContainer" tabindex="0">
           <div id="viewer"></div>
         </div>
 
         <div id="errorWrapper" hidden='true'>
           <div id="errorMessageLeft">
             <span id="errorMessage"></span>
             <button id="errorShowMore" data-l10n-id="error_more_info">
               More Information
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -1294,33 +1294,35 @@ var PDFHistory = {
 
 var SecondaryToolbar = {
   opened: false,
   previousContainerHeight: null,
   newContainerHeight: null,
 
   initialize: function secondaryToolbarInitialize(options) {
     this.toolbar = options.toolbar;
+    this.presentationMode = options.presentationMode;
     this.buttonContainer = this.toolbar.firstElementChild;
 
     // Define the toolbar buttons.
     this.toggleButton = options.toggleButton;
-    this.presentationMode = options.presentationMode;
+    this.presentationModeButton = options.presentationModeButton;
     this.openFile = options.openFile;
     this.print = options.print;
     this.download = options.download;
     this.firstPage = options.firstPage;
     this.lastPage = options.lastPage;
     this.pageRotateCw = options.pageRotateCw;
     this.pageRotateCcw = options.pageRotateCcw;
 
     // Attach the event listeners.
     var elements = [
       { element: this.toggleButton, handler: this.toggle },
-      { element: this.presentationMode, handler: this.presentationModeClick },
+      { element: this.presentationModeButton,
+        handler: this.presentationModeClick },
       { element: this.openFile, handler: this.openFileClick },
       { element: this.print, handler: this.printClick },
       { element: this.download, handler: this.downloadClick },
       { element: this.firstPage, handler: this.firstPageClick },
       { element: this.lastPage, handler: this.lastPageClick },
       { element: this.pageRotateCw, handler: this.pageRotateCwClick },
       { element: this.pageRotateCcw, handler: this.pageRotateCcwClick }
     ];
@@ -1330,17 +1332,17 @@ var SecondaryToolbar = {
       if (element) {
         element.addEventListener('click', elements[item].handler.bind(this));
       }
     }
   },
 
   // Event handling functions.
   presentationModeClick: function secondaryToolbarPresentationModeClick(evt) {
-    PresentationMode.request();
+    this.presentationMode.request();
     this.close();
   },
 
   openFileClick: function secondaryToolbarOpenFileClick(evt) {
     document.getElementById('fileInput').click();
     this.close(evt.target);
   },
 
@@ -1367,17 +1369,17 @@ var SecondaryToolbar = {
   },
 
   pageRotateCcwClick: function secondaryToolbarPageRotateCcwClick(evt) {
     PDFView.rotatePages(-90);
   },
 
   // Misc. functions for interacting with the toolbar.
   setMaxHeight: function secondaryToolbarSetMaxHeight(container) {
-    if (!container) {
+    if (!container || !this.buttonContainer) {
       return;
     }
     this.newContainerHeight = container.clientHeight;
     if (this.previousContainerHeight === this.newContainerHeight) {
       return;
     }
     this.buttonContainer.setAttribute('style',
       'max-height: ' + (this.newContainerHeight - SCROLLBAR_PADDING) + 'px;');
@@ -1405,20 +1407,16 @@ var SecondaryToolbar = {
   },
 
   toggle: function secondaryToolbarToggle() {
     if (this.opened) {
       this.close();
     } else {
       this.open();
     }
-  },
-
-  get isOpen() {
-    return this.opened;
   }
 };
 
 
 var PasswordPrompt = {
   visible: false,
   updatePassword: null,
   reason: null,
@@ -1501,16 +1499,18 @@ var PresentationMode = {
   active: false,
   args: null,
   contextMenuOpen: false,
 
   initialize: function presentationModeInitialize(options) {
     this.container = options.container;
     this.secondaryToolbar = options.secondaryToolbar;
 
+    this.viewer = this.container.firstElementChild;
+
     this.firstPage = options.firstPage;
     this.lastPage = options.lastPage;
     this.pageRotateCw = options.pageRotateCw;
     this.pageRotateCcw = options.pageRotateCcw;
 
     this.firstPage.addEventListener('click', function() {
       this.contextMenuOpen = false;
       this.secondaryToolbar.firstPageClick();
@@ -1533,17 +1533,18 @@ var PresentationMode = {
   get isFullscreen() {
     return (document.fullscreenElement ||
             document.mozFullScreen ||
             document.webkitIsFullScreen ||
             document.msFullscreenElement);
   },
 
   request: function presentationModeRequest() {
-    if (!PDFView.supportsFullscreen || this.isFullscreen) {
+    if (!PDFView.supportsFullscreen || this.isFullscreen ||
+        !this.viewer.hasChildNodes()) {
       return false;
     }
 
     if (this.container.requestFullscreen) {
       this.container.requestFullscreen();
     } else if (this.container.mozRequestFullScreen) {
       this.container.mozRequestFullScreen();
     } else if (this.container.webkitRequestFullScreen) {
@@ -1715,18 +1716,20 @@ var PDFView = {
 
     PDFFindController.initialize({
       pdfPageSource: this,
       integratedFind: this.supportsIntegratedFind
     });
 
     SecondaryToolbar.initialize({
       toolbar: document.getElementById('secondaryToolbar'),
+      presentationMode: PresentationMode,
       toggleButton: document.getElementById('secondaryToolbarToggle'),
-      presentationMode: document.getElementById('secondaryPresentationMode'),
+      presentationModeButton:
+        document.getElementById('secondaryPresentationMode'),
       openFile: document.getElementById('secondaryOpenFile'),
       print: document.getElementById('secondaryPrint'),
       download: document.getElementById('secondaryDownload'),
       firstPage: document.getElementById('firstPage'),
       lastPage: document.getElementById('lastPage'),
       pageRotateCw: document.getElementById('pageRotateCw'),
       pageRotateCcw: document.getElementById('pageRotateCcw')
     });
@@ -1963,18 +1966,18 @@ var PDFView = {
     Object.defineProperty(this, 'loadingBar', { value: bar,
                                                 enumerable: true,
                                                 configurable: true,
                                                 writable: false });
     return bar;
   },
 
   get isHorizontalScrollbarEnabled() {
-    var div = document.getElementById('viewerContainer');
-    return div.scrollWidth > div.clientWidth;
+    return (PresentationMode.active ? false :
+            (this.container.scrollWidth > this.container.clientWidth));
   },
 
   initPassiveLoading: function pdfViewInitPassiveLoading() {
     var pdfDataRangeTransport = {
       rangeListeners: [],
       progressListeners: [],
 
       addRangeListener: function PdfDataRangeTransport_addRangeListener(
@@ -3225,16 +3228,17 @@ var PageView = function pageView(contain
 
   this.getPagePoint = function pageViewGetPagePoint(x, y) {
     return this.viewport.convertToPdfPoint(x, y);
   };
 
   this.scrollIntoView = function pageViewScrollIntoView(dest) {
     if (PresentationMode.active) { // Avoid breaking presentation mode.
       dest = null;
+      PDFView.setScale(PDFView.currentScaleValue, true, true);
     }
     if (!dest) {
       scrollIntoView(div);
       return;
     }
 
     var x = 0, y = 0;
     var width = 0, height = 0, widthScale, heightScale;
@@ -4549,17 +4553,17 @@ window.addEventListener('DOMMouseScroll'
   } else if (PresentationMode.active) {
     var FIREFOX_DELTA_FACTOR = -40;
     PDFView.mouseScroll(evt.detail * FIREFOX_DELTA_FACTOR);
   }
 }, false);
 
 window.addEventListener('click', function click(evt) {
   if (!PresentationMode.active) {
-    if (SecondaryToolbar.isOpen && PDFView.container.contains(evt.target)) {
+    if (SecondaryToolbar.opened && PDFView.container.contains(evt.target)) {
       SecondaryToolbar.close();
     }
   } else if (evt.button === 0) {
     // Necessary since preventDefault() in 'mousedown' won't stop
     // the event propagation in all circumstances in presentation mode.
     evt.preventDefault();
   }
 }, false);
@@ -4644,16 +4648,19 @@ window.addEventListener('keydown', funct
     }
   }
   var controlsElement = document.getElementById('toolbar');
   while (curElement) {
     if (curElement === controlsElement && !PresentationMode.active)
       return; // ignoring if the 'toolbar' element is focused
     curElement = curElement.parentNode;
   }
+  // Workaround for issue in Firefox, that prevents scroll keys from working
+  // when elements with 'tabindex' are focused.
+  PDFView.container.blur();
 
   if (cmd === 0) { // no control key pressed at all.
     switch (evt.keyCode) {
       case 38: // up arrow
       case 33: // pg up
       case 8: // backspace
         if (!PresentationMode.active &&
             PDFView.currentScaleValue !== 'page-fit') {
@@ -4668,17 +4675,17 @@ window.addEventListener('keydown', funct
         }
         /* falls through */
       case 75: // 'k'
       case 80: // 'p'
         PDFView.page--;
         handled = true;
         break;
       case 27: // esc key
-        if (SecondaryToolbar.isOpen) {
+        if (SecondaryToolbar.opened) {
           SecondaryToolbar.close();
           handled = true;
         }
         if (!PDFView.supportsIntegratedFind && PDFFindBar.opened) {
           PDFFindBar.close();
           handled = true;
         }
         break;
--- a/browser/extensions/pdfjs/extension-files
+++ b/browser/extensions/pdfjs/extension-files
@@ -1,16 +1,16 @@
 chrome.manifest
 components/PdfRedirector.js
 components/PdfStreamConverter.js
+content/PdfJs.jsm
+content/PdfJsTelemetry.jsm
 content/build/pdf.js
 content/build/pdf.worker.js
 content/network.js
-content/PdfJs.jsm
-content/PdfJsTelemetry.jsm
 content/web/debugger.js
 content/web/images/annotation-check.svg
 content/web/images/annotation-comment.svg
 content/web/images/annotation-help.svg
 content/web/images/annotation-insert.svg
 content/web/images/annotation-key.svg
 content/web/images/annotation-newparagraph.svg
 content/web/images/annotation-note.svg
--- a/browser/metro/base/content/helperui/IndexedDB.js
+++ b/browser/metro/base/content/helperui/IndexedDB.js
@@ -39,33 +39,35 @@ let IndexedDB = {
     } else if (topic == this._quotaCancel) {
       payload.permission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
       browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
       // XXX Need to actually save this?
       return;
     }
 
     let prompt = Cc["@mozilla.org/content-permission/prompt;1"].createInstance(Ci.nsIContentPermissionPrompt);
+    let types = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+    types.appendElement({type: type, access: "unused"}, false);
 
     // If the user waits a long time before responding, we default to UNKNOWN_ACTION.
     let timeoutId = setTimeout(function() {
       payload.permission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
       browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
       timeoutId = null;
     }, 30000);
  
     function checkTimeout() {
       if (timeoutId === null) return true;
       clearTimeout(timeoutId);
       timeoutId = null;
       return false;
     }
 
     prompt.prompt({
-      type: type,
+      types: types,
       uri: Services.io.newURI(payload.location, null, null),
       window: null,
       element: aMessage.target,
 
       cancel: function() {
         if (checkTimeout()) return;
         payload.permission = Ci.nsIPermissionManager.DENY_ACTION;
         browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
--- a/browser/metro/components/ContentPermissionPrompt.js
+++ b/browser/metro/components/ContentPermissionPrompt.js
@@ -51,78 +51,86 @@ ContentPermissionPrompt.prototype = {
       let requestingWindow = request.window.top;
       let windowID = request.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
       let browser = chromeWin.Browser.getBrowserForWindowId(windowID);
       return chromeWin.getNotificationBox(browser);
     }
     return chromeWin.Browser.getNotificationBox(request.element);
   },
 
-  handleExistingPermission: function handleExistingPermission(request) {
-    let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
+  handleExistingPermission: function handleExistingPermission(request, type) {
+    let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
     if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
       request.allow();
       return true;
     }
     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
       request.cancel();
       return true;
     }
     return false;
   },
 
   prompt: function(request) {
+    // Only allow exactly one permission rquest here.
+    let types = request.types.QueryInterface(Ci.nsIArray);
+    if (types.length != 1) {
+      request.cancel();
+      return;
+    }
+    let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
+
     // returns true if the request was handled
-    if (this.handleExistingPermission(request))
+    if (this.handleExistingPermission(request, perm.type))
        return;
 
     let pm = Services.perms;
     let notificationBox = this.getNotificationBoxForRequest(request);
     let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
     
-    let notification = notificationBox.getNotificationWithValue(request.type);
+    let notification = notificationBox.getNotificationWithValue(perm.type);
     if (notification)
       return;
 
-    let entityName = kEntities[request.type];
-    let icon = kIcons[request.type] || "";
+    let entityName = kEntities[perm.type];
+    let icon = kIcons[perm.type] || "";
 
     let buttons = [{
       label: browserBundle.GetStringFromName(entityName + ".allow"),
       accessKey: "",
       callback: function(notification) {
         request.allow();
       }
     },
     {
       label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"),
       accessKey: "",
       callback: function(notification) {
-        Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION);
+        Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
         request.allow();
       }
     },
     {
       label: browserBundle.GetStringFromName("contentPermissions.neverForSite"),
       accessKey: "",
       callback: function(notification) {
-        Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
+        Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
         request.cancel();
       }
     }];
 
     let message = browserBundle.formatStringFromName(entityName + ".wantsTo",
                                                      [request.principal.URI.host], 1);
     let newBar = notificationBox.appendNotification(message,
-                                                    request.type,
+                                                    perm.type,
                                                     icon,
                                                     notificationBox.PRIORITY_WARNING_MEDIUM,
                                                     buttons);
 
-    if (request.type == "geolocation") {
+    if (perm.type == "geolocation") {
       // Add the "learn more" link.
       let link = newBar.ownerDocument.createElement("label");
       link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
       link.setAttribute("class", "text-link notification-link");
       newBar.insertBefore(link, newBar.firstChild);
 
       let win = this.getChromeWindowForRequest(request);
       link.addEventListener("click", function() {
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1291,55 +1291,47 @@ toolbar[iconsize="small"] #webrtc-status
 
 #webapps-notification-icon {
   list-style-image: url(chrome://global/skin/icons/webapps-16.png);
 }
 
 #plugins-notification-icon {
   list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
 }
-
-#alert-plugins-notification-icon {
+#plugins-notification-icon.plugin-hidden {
   list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
 }
-
-#blocked-plugins-notification-icon {
+#plugins-notification-icon.plugin-blocked {
   list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
 }
 
-#plugins-notification-icon,
-#alert-plugins-notification-icon,
-#blocked-plugins-notification-icon {
+#plugins-notification-icon {
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
-#plugins-notification-icon:hover,
-#alert-plugins-notification-icon:hover,
-#blocked-plugins-notification-icon:hover {
+#plugins-notification-icon:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
-#plugins-notification-icon:active,
-#alert-plugins-notification-icon:active,
-#blocked-plugins-notification-icon:active {
+#plugins-notification-icon:active {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 #plugin-install-notification-icon {
   list-style-image: url(chrome://browser/skin/pluginInstall-16.png);
 }
 
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
 
-#blocked-plugins-notification-icon[showing] {
+#plugins-notification-icon.plugin-blocked[showing] {
   animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
 }
 
 @keyframes pluginBlockedNotification {
   from {
     opacity: 0;
   }
   to {
--- a/browser/themes/linux/devtools/debugger.css
+++ b/browser/themes/linux/devtools/debugger.css
@@ -19,18 +19,21 @@
 
 /* Sources toolbar */
 
 #sources-toolbar {
   border: none; /* Remove the devtools-toolbar's black bottom border. */
   -moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
 }
 
+#sources-toolbar .devtools-toolbarbutton {
+  min-width: 32px;
+}
+
 #pretty-print {
-  min-width: 0;
   font-weight: bold;
 }
 
 #black-box {
   list-style-image: url(debugger-blackbox.png);
   -moz-image-region: rect(0px,16px,16px,0px);
 }
 
--- a/browser/themes/linux/devtools/shadereditor.css
+++ b/browser/themes/linux/devtools/shadereditor.css
@@ -1,5 +1,9 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %include ../../shared/devtools/shadereditor.inc.css
+
+.side-menu-widget-item-checkbox > .checkbox-spacer-box {
+  -moz-appearance: none;
+}
--- a/browser/themes/linux/devtools/widgets.css
+++ b/browser/themes/linux/devtools/widgets.css
@@ -312,21 +312,16 @@
               0 -2px 0 hsla(206,37%,4%,.05) inset,
               0 -1px 1px hsla(206,37%,4%,.1) inset;
 }
 
 .side-menu-widget-group-title[theme="light"] {
   background-image: linear-gradient(#fff, #eee);
 }
 
-.side-menu-widget-group-checkbox {
-  margin: 0;
-  padding: 0;
-}
-
 /* SideMenuWidget items */
 
 .side-menu-widget-item[theme="dark"] {
   border-top: 1px solid hsla(210,8%,5%,.25);
   border-bottom: 1px solid hsla(210,16%,76%,.1);
   margin-top: -1px;
   margin-bottom: -1px;
 }
@@ -374,21 +369,16 @@
   padding: 4px 0px;
 }
 
 .side-menu-widget-item-arrow {
   -moz-margin-start: -8px;
   width: 8px;
 }
 
-.side-menu-widget-item-checkbox {
-  -moz-margin-start: 4px;
-  -moz-margin-end: -6px;
-}
-
 .side-menu-widget-item-other {
   background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
 }
 
 .side-menu-widget-item-other.selected {
   background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.15);
   box-shadow: inset 0 1px 0 hsla(210,40%,83%,.07),
               inset 0 -1px 0 hsla(210,40%,83%,.07);
@@ -398,16 +388,35 @@
   border-top-left-radius: 4px;
 }
 
 .side-menu-widget-item-other > label {
   color: #f5f7fa;
   text-shadow: 0 1px 1px #111;
 }
 
+/* SideMenuWidget checkboxes */
+
+.side-menu-widget-group-checkbox {
+  margin: 0;
+  -moz-margin-end: 4px;
+}
+
+.side-menu-widget-item-checkbox {
+  margin: 0;
+  -moz-margin-start: 4px;
+  -moz-margin-end: -4px;
+}
+
+.side-menu-widget-group-checkbox .checkbox-spacer-box,
+.side-menu-widget-item-checkbox .checkbox-spacer-box {
+  margin: 0;
+  border: none;
+}
+
 /* SideMenuWidget misc */
 
 .side-menu-widget-empty-notice-container {
   padding: 12px;
 }
 
 .side-menu-widget-empty-notice-container[theme="dark"] {
   background: url(background-noise-toolbar.png), hsl(208,11%,27%);
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3202,70 +3202,58 @@ toolbarbutton.chevron > .toolbarbutton-m
     list-style-image: url(chrome://global/skin/icons/webapps-16@2x.png);
   }
 }
 
 #plugins-notification-icon {
   list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
 }
 
-#alert-plugins-notification-icon {
+#plugins-notification-icon.plugin-hidden {
   list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
 }
 
-#blocked-plugins-notification-icon {
+#plugins-notification-icon.plugin-blocked {
   list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
 }
 
-#plugins-notification-icon,
-#alert-plugins-notification-icon,
-#blocked-plugins-notification-icon {
+#plugins-notification-icon {
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
-#plugins-notification-icon:hover,
-#alert-plugins-notification-icon:hover,
-#blocked-plugins-notification-icon:hover {
+#plugins-notification-icon:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
-#plugins-notification-icon:active,
-#alert-plugins-notification-icon:active,
-#blocked-plugins-notification-icon:active {
+#plugins-notification-icon:active {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 @media (min-resolution: 2dppx) {
   #plugins-notification-icon {
     list-style-image: url(chrome://browser/skin/notification-pluginNormal@2x.png);
   }
 
-  #alert-plugins-notification-icon {
+  #plugins-notification-icon.plugin-hidden {
     list-style-image: url(chrome://browser/skin/notification-pluginAlert@2x.png);
   }
 
-  #blocked-plugins-notification-icon {
+  #plugins-notification-icon.plugin-blocked {
     list-style-image: url(chrome://browser/skin/notification-pluginBlocked@2x.png);
   }
 
-  #plugins-notification-icon,
-  #alert-plugins-notification-icon,
-  #blocked-plugins-notification-icon {
+  #plugins-notification-icon {
     -moz-image-region: rect(0, 32px, 32px, 0);
   }
 
-  #plugins-notification-icon:hover,
-  #alert-plugins-notification-icon:hover,
-  #blocked-plugins-notification-icon:hover {
+  #plugins-notification-icon:hover {
     -moz-image-region: rect(0, 64px, 32px, 32px);
   }
 
-  #plugins-notification-icon:active,
-  #alert-plugins-notification-icon:active,
-  #blocked-plugins-notification-icon:active {
+  #plugins-notification-icon:active {
     -moz-image-region: rect(0, 96px, 32px, 64px);
   }
 }
 
 #plugin-install-notification-icon {
   list-style-image: url(chrome://browser/skin/pluginInstall-16.png);
 }
 @media (min-resolution: 2dppx) {
@@ -3276,17 +3264,17 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
 
-#blocked-plugins-notification-icon[showing] {
+#plugins-notification-icon.plugin-blocked[showing] {
   animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
 }
 
 @keyframes pluginBlockedNotification {
   from {
     opacity: 0;
   }
   to {
--- a/browser/themes/osx/devtools/debugger.css
+++ b/browser/themes/osx/devtools/debugger.css
@@ -21,18 +21,21 @@
 
 /* Sources toolbar */
 
 #sources-toolbar {
   border: none; /* Remove the devtools-toolbar's black bottom border. */
   -moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
 }
 
+#sources-toolbar .devtools-toolbarbutton {
+  min-width: 32px;
+}
+
 #pretty-print {
-  min-width: 0;
   font-weight: bold;
 }
 
 #black-box {
   list-style-image: url(debugger-blackbox.png);
   -moz-image-region: rect(0px,16px,16px,0px);
 }
 
--- a/browser/themes/osx/devtools/widgets.css
+++ b/browser/themes/osx/devtools/widgets.css
@@ -312,21 +312,16 @@
               0 -2px 0 hsla(206,37%,4%,.05) inset,
               0 -1px 1px hsla(206,37%,4%,.1) inset;
 }
 
 .side-menu-widget-group-title[theme="light"] {
   background-image: linear-gradient(#fff, #eee);
 }
 
-.side-menu-widget-group-checkbox {
-  margin: 0;
-  padding: 0;
-}
-
 /* SideMenuWidget items */
 
 .side-menu-widget-item[theme="dark"] {
   border-top: 1px solid hsla(210,8%,5%,.25);
   border-bottom: 1px solid hsla(210,16%,76%,.1);
   margin-top: -1px;
   margin-bottom: -1px;
 }
@@ -374,21 +369,16 @@
   padding: 4px 0px;
 }
 
 .side-menu-widget-item-arrow {
   -moz-margin-start: -8px;
   width: 8px;
 }
 
-.side-menu-widget-item-checkbox {
-  -moz-margin-start: 4px;
-  -moz-margin-end: -6px;
-}
-
 .side-menu-widget-item-other {
   background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
 }
 
 .side-menu-widget-item-other.selected {
   background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.15);
   box-shadow: inset 0 1px 0 hsla(210,40%,83%,.07),
               inset 0 -1px 0 hsla(210,40%,83%,.07);
@@ -398,16 +388,29 @@
   border-top-left-radius: 4px;
 }
 
 .side-menu-widget-item-other > label {
   color: #f5f7fa;
   text-shadow: 0 1px 1px #111;
 }
 
+/* SideMenuWidget checkboxes */
+
+.side-menu-widget-group-checkbox {
+  margin: 0;
+  -moz-margin-end: 4px;
+}
+
+.side-menu-widget-item-checkbox {
+  margin: 0;
+  -moz-margin-start: 4px;
+  -moz-margin-end: -4px;
+}
+
 /* SideMenuWidget misc */
 
 .side-menu-widget-empty-notice-container {
   padding: 12px;
 }
 
 .side-menu-widget-empty-notice-container[theme="dark"] {
   background: url(background-noise-toolbar.png), hsl(208,11%,27%);
--- a/browser/themes/shared/devtools/shadereditor.inc.css
+++ b/browser/themes/shared/devtools/shadereditor.inc.css
@@ -46,45 +46,43 @@
 }
 
 #shaders-pane + .devtools-side-splitter {
   -moz-border-start-color: transparent;
 }
 
 .side-menu-widget-item-checkbox {
   -moz-appearance: none;
-  -moz-margin-end: -6px;
-  padding: 0;
   opacity: 0;
   transition: opacity .15s ease-out 0s;
 }
 
 /* Only show the checkbox when the source is hovered over, is selected, or if it
  * is not checked. */
 .side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
 .side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
 .side-menu-widget-item-checkbox:not([checked]) {
   opacity: 1;
   transition: opacity .15s ease-out 0s;
 }
 
-.side-menu-widget-item-checkbox > .checkbox-check {
+.side-menu-widget-item-checkbox .checkbox-check {
   -moz-appearance: none;
   background: none;
-  background-image: url("chrome://browser/skin/devtools/itemToggle.png");
+  background-image: url(itemToggle.png);
   background-repeat: no-repeat;
   background-clip: content-box;
   background-size: 32px 16px;
   background-position: -16px 0;
   width: 16px;
   height: 16px;
   border: 0;
 }
 
-.side-menu-widget-item-checkbox[checked] > .checkbox-check {
+.side-menu-widget-item-checkbox[checked] .checkbox-check {
   background-position: 0 0;
 }
 
 .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
   color: #888;
 }
 
 /* Shader source editors */
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2563,55 +2563,48 @@ toolbarbutton.bookmark-item[dragover="tr
 
 #webapps-notification-icon {
   list-style-image: url(chrome://global/skin/icons/webapps-16.png);
 }
 
 #plugins-notification-icon {
   list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
 }
-
-#alert-plugins-notification-icon {
+#plugins-notification-icon.plugin-hidden {
   list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
 }
 
-#blocked-plugins-notification-icon {
+#plugins-notification-icon.plugin-blocked {
   list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
 }
 
-#plugins-notification-icon,
-#alert-plugins-notification-icon,
-#blocked-plugins-notification-icon {
+#plugins-notification-icon {
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
-#plugins-notification-icon:hover,
-#alert-plugins-notification-icon:hover,
-#blocked-plugins-notification-icon:hover {
+#plugins-notification-icon:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
-#plugins-notification-icon:active,
-#alert-plugins-notification-icon:active,
-#blocked-plugins-notification-icon:active {
+#plugins-notification-icon:active {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 #plugin-install-notification-icon {
   list-style-image: url(chrome://browser/skin/pluginInstall-16.png);
 }
 
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
 
-#blocked-plugins-notification-icon[showing] {
+#plugins-notification-icon.plugin-blocked[showing] {
   animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
 }
 
 @keyframes pluginBlockedNotification {
   from {
     opacity: 0;
   }
   to {
--- a/browser/themes/windows/devtools/debugger.css
+++ b/browser/themes/windows/devtools/debugger.css
@@ -19,18 +19,21 @@
 
 /* Sources toolbar */
 
 #sources-toolbar {
   border: none; /* Remove the devtools-toolbar's black bottom border. */
   -moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
 }
 
+#sources-toolbar .devtools-toolbarbutton {
+  min-width: 32px;
+}
+
 #pretty-print {
-  min-width: 0;
   font-weight: bold;
 }
 
 #black-box {
   list-style-image: url(debugger-blackbox.png);
   -moz-image-region: rect(0px,16px,16px,0px);
 }
 
--- a/browser/themes/windows/devtools/widgets.css
+++ b/browser/themes/windows/devtools/widgets.css
@@ -316,21 +316,16 @@
               0 -2px 0 hsla(206,37%,4%,.05) inset,
               0 -1px 1px hsla(206,37%,4%,.1) inset;
 }
 
 .side-menu-widget-group-title[theme="light"] {
   background-image: linear-gradient(#fff, #eee);
 }
 
-.side-menu-widget-group-checkbox {
-  margin: 0;
-  padding: 0;
-}
-
 /* SideMenuWidget items */
 
 .side-menu-widget-item[theme="dark"] {
   border-top: 1px solid hsla(210,8%,5%,.25);
   border-bottom: 1px solid hsla(210,16%,76%,.1);
   margin-top: -1px;
   margin-bottom: -1px;
 }
@@ -378,21 +373,16 @@
   padding: 4px 0px;
 }
 
 .side-menu-widget-item-arrow {
   -moz-margin-start: -8px;
   width: 8px;
 }
 
-.side-menu-widget-item-checkbox {
-  -moz-margin-start: 4px;
-  -moz-margin-end: -6px;
-}
-
 .side-menu-widget-item-other {
   background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
 }
 
 .side-menu-widget-item-other.selected {
   background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.15);
   box-shadow: inset 0 1px 0 hsla(210,40%,83%,.07),
               inset 0 -1px 0 hsla(210,40%,83%,.07);
@@ -401,16 +391,29 @@
 .side-menu-widget-item-other:first-of-type {
   border-top-left-radius: 4px;
 }
 
 .side-menu-widget-item-other > label {
   color: #f5f7fa;
 }
 
+/* SideMenuWidget checkboxes */
+
+.side-menu-widget-group-checkbox {
+  margin: 0;
+  -moz-margin-end: 4px;
+}
+
+.side-menu-widget-item-checkbox {
+  margin: 0;
+  -moz-margin-start: 4px;
+  -moz-margin-end: -4px;
+}
+
 /* SideMenuWidget misc */
 
 .side-menu-widget-empty-notice-container {
   padding: 12px;
 }
 
 .side-menu-widget-empty-notice-container[theme="dark"] {
   background: url(background-noise-toolbar.png), hsl(208,11%,27%);
--- a/caps/src/nsJSPrincipals.cpp
+++ b/caps/src/nsJSPrincipals.cpp
@@ -6,17 +6,16 @@
 #include "xpcprivate.h"
 #include "nsString.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObjectInputStream.h"
 #include "nsJSPrincipals.h"
 #include "plstr.h"
 #include "nsXPIDLString.h"
 #include "nsCOMPtr.h"
-#include "jsapi.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIServiceManager.h"
 #include "nsMemory.h"
 #include "nsStringBuffer.h"
 
 // for mozilla::dom::workers::kJSPrincipalsDebugToken
 #include "mozilla/dom/workers/Workers.h"
 
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -79,18 +79,16 @@
 #include "nsContentUtils.h"
 #include "ChildIterator.h"
 
 #include "nsIDOMEventListener.h"
 #include "nsIWebNavigation.h"
 #include "nsIBaseWindow.h"
 #include "nsIWidget.h"
 
-#include "jsapi.h"
-
 #include "nsNodeInfoManager.h"
 #include "nsICategoryManager.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsEventDispatcher.h"
@@ -2242,40 +2240,40 @@ Element::PostHandleEventForLinks(nsEvent
 
           nsEventStateManager::SetActiveManager(
             aVisitor.mPresContext->EventStateManager(), this);
         }
       }
     }
     break;
 
-  case NS_MOUSE_CLICK:
-    if (aVisitor.mEvent->IsLeftClickEvent()) {
-      WidgetInputEvent* inputEvent = aVisitor.mEvent->AsInputEvent();
-      if (inputEvent->IsControl() || inputEvent->IsMeta() ||
-          inputEvent->IsAlt() ||inputEvent->IsShift()) {
+  case NS_MOUSE_CLICK: {
+    WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+    if (mouseEvent->IsLeftClickEvent()) {
+      if (mouseEvent->IsControl() || mouseEvent->IsMeta() ||
+          mouseEvent->IsAlt() ||mouseEvent->IsShift()) {
         break;
       }
 
       // The default action is simply to dispatch DOMActivate
       nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
       if (shell) {
         // single-click
         nsEventStatus status = nsEventStatus_eIgnore;
-        InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
+        InternalUIEvent actEvent(mouseEvent->mFlags.mIsTrusted,
                                  NS_UI_ACTIVATE, 1);
 
         rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
         if (NS_SUCCEEDED(rv)) {
           aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
         }
       }
     }
     break;
-
+  }
   case NS_UI_ACTIVATE:
     {
       if (aVisitor.mEvent->originalTarget == this) {
         nsAutoString target;
         GetLinkTarget(target);
         nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
                                     true, true,
                                     aVisitor.mEvent->mFlags.mIsTrusted);
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -74,17 +74,17 @@
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 
 #include "nsIDOMEventListener.h"
 #include "nsIWebNavigation.h"
 #include "nsIBaseWindow.h"
 #include "nsIWidget.h"
 
-#include "jsapi.h"
+#include "js/GCAPI.h"
 
 #include "nsNodeInfoManager.h"
 #include "nsICategoryManager.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -210,16 +210,18 @@
 #include "mozilla/css/Rule.h"
 #include "nsIDOMLocation.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsISecurityConsoleMessage.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "mozilla/dom/XPathEvaluator.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIStructuredCloneContainer.h"
+#include "nsIMutableArray.h"
+#include "nsContentPermissionHelper.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
@@ -10642,27 +10644,21 @@ public:
   bool mUserInputOrChromeCaller;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
                              nsRunnable,
                              nsIContentPermissionRequest)
 
 NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetType(nsACString& aType)
-{
-  aType = "pointerLock";
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetAccess(nsACString& aAccess)
-{
-  aAccess = "unused";
-  return NS_OK;
+nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
+{
+  return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
+                               NS_LITERAL_CSTRING("unused"),
+                               aTypes);
 }
 
 NS_IMETHODIMP
 nsPointerLockPermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal)
 {
   nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
   if (d) {
     NS_ADDREF(*aPrincipal = d->NodePrincipal());
@@ -11086,45 +11082,49 @@ nsDocument::GetVisibilityState(nsAString
     VisibilityStateValues::strings[static_cast<int>(mVisibilityState)];
   aState.AssignASCII(entry.value, entry.length);
   return NS_OK;
 }
 
 /* virtual */ void
 nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
 {
-  aWindowSizes->mDOMOther +=
+  aWindowSizes->mDOMOtherSize +=
     nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
 
   if (mPresShell) {
     mPresShell->AddSizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
                                        &aWindowSizes->mArenaStats,
-                                       &aWindowSizes->mLayoutPresShell,
-                                       &aWindowSizes->mLayoutStyleSets,
-                                       &aWindowSizes->mLayoutTextRuns,
-                                       &aWindowSizes->mLayoutPresContext);
-  }
-
-  aWindowSizes->mPropertyTables +=
+                                       &aWindowSizes->mLayoutPresShellSize,
+                                       &aWindowSizes->mLayoutStyleSetsSize,
+                                       &aWindowSizes->mLayoutTextRunsSize,
+                                       &aWindowSizes->mLayoutPresContextSize);
+  }
+
+  aWindowSizes->mPropertyTablesSize +=
     mPropertyTable.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
   for (uint32_t i = 0, count = mExtraPropertyTables.Length();
        i < count; ++i) {
-    aWindowSizes->mPropertyTables +=
+    aWindowSizes->mPropertyTablesSize +=
       mExtraPropertyTables[i]->SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
   }
 
+  if (nsEventListenerManager* elm = GetExistingListenerManager()) {
+    aWindowSizes->mDOMEventListenersCount += elm->ListenerCount();
+  }
+
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
 
 void
 nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
-  aWindowSizes->mDOMOther += aWindowSizes->mMallocSizeOf(this);
+  aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
   DocAddSizeOfExcludingThis(aWindowSizes);
 }
 
 static size_t
 SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
                                       MallocSizeOf aMallocSizeOf,
                                       void* aData)
 {
@@ -11150,68 +11150,72 @@ nsDocument::DocAddSizeOfExcludingThis(ns
        node;
        node = node->GetNextNode(this))
   {
     size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
     size_t* p;
 
     switch (node->NodeType()) {
     case nsIDOMNode::ELEMENT_NODE:
-      p = &aWindowSizes->mDOMElementNodes;
+      p = &aWindowSizes->mDOMElementNodesSize;
       break;
     case nsIDOMNode::TEXT_NODE:
-      p = &aWindowSizes->mDOMTextNodes;
+      p = &aWindowSizes->mDOMTextNodesSize;
       break;
     case nsIDOMNode::CDATA_SECTION_NODE:
-      p = &aWindowSizes->mDOMCDATANodes;
+      p = &aWindowSizes->mDOMCDATANodesSize;
       break;
     case nsIDOMNode::COMMENT_NODE:
-      p = &aWindowSizes->mDOMCommentNodes;
+      p = &aWindowSizes->mDOMCommentNodesSize;
       break;
     default:
-      p = &aWindowSizes->mDOMOther;
+      p = &aWindowSizes->mDOMOtherSize;
       break;
     }
 
     *p += nodeSize;
-  }
-
-  aWindowSizes->mStyleSheets +=
+
+    if (nsEventListenerManager* elm = node->GetExistingListenerManager()) {
+      aWindowSizes->mDOMEventListenersCount += elm->ListenerCount();
+    }
+  }
+
+  aWindowSizes->mStyleSheetsSize +=
     mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
                                      aWindowSizes->mMallocSizeOf);
-  aWindowSizes->mStyleSheets +=
+  aWindowSizes->mStyleSheetsSize +=
     mCatalogSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
                                        aWindowSizes->mMallocSizeOf);
-  aWindowSizes->mStyleSheets +=
+  aWindowSizes->mStyleSheetsSize +=
     mAdditionalSheets[eAgentSheet].
       SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
                           aWindowSizes->mMallocSizeOf);
-  aWindowSizes->mStyleSheets +=
+  aWindowSizes->mStyleSheetsSize +=
     mAdditionalSheets[eUserSheet].
       SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
                           aWindowSizes->mMallocSizeOf);
-  aWindowSizes->mStyleSheets +=
+  aWindowSizes->mStyleSheetsSize +=
     mAdditionalSheets[eAuthorSheet].
       SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
                           aWindowSizes->mMallocSizeOf);
   // Lumping in the loader with the style-sheets size is not ideal,
   // but most of the things in there are in fact stylesheets, so it
   // doesn't seem worthwhile to separate it out.
-  aWindowSizes->mStyleSheets +=
+  aWindowSizes->mStyleSheetsSize +=
     CSSLoader()->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
 
-  aWindowSizes->mDOMOther +=
+  aWindowSizes->mDOMOtherSize +=
     mAttrStyleSheet ?
     mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
     0;
 
-  aWindowSizes->mDOMOther +=
+  aWindowSizes->mDOMOtherSize +=
     mStyledLinks.SizeOfExcludingThis(nullptr, aWindowSizes->mMallocSizeOf);
 
-  aWindowSizes->mDOMOther +=
+  aWindowSizes->mDOMOtherSize +=
     mIdentifierMap.SizeOfExcludingThis(nsIdentifierMapEntry::SizeOfExcludingThis,
                                        aWindowSizes->mMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
 
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -83,16 +83,17 @@
 #include "mozilla/unused.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/TextMetrics.h"
 #include "mozilla/dom/UnionTypes.h"
+#include "nsGlobalWindow.h"
 
 #ifdef USE_SKIA_GPU
 #undef free // apparently defined by some windows header, clashing with a free()
             // method in SkTypes.h
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "GLContextSkia.h"
 #include "SurfaceTypes.h"
@@ -2853,37 +2854,37 @@ CanvasRenderingContext2D::SetMozDashOffs
 {
   ContextState& state = CurrentState();
   if (!state.dash.IsEmpty()) {
     state.dashOffset = mozDashOffset;
   }
 }
 
 void
-CanvasRenderingContext2D::SetLineDash(const mozilla::dom::AutoSequence<double>& mSegments) {
+CanvasRenderingContext2D::SetLineDash(const mozilla::dom::AutoSequence<double>& aSegments) {
   FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
   dash.Clear();
 
-  for(mozilla::dom::AutoSequence<double>::index_type x = 0; x < mSegments.Length(); x++) {
-    dash.AppendElement(mSegments[x]);
+  for (uint32_t x = 0; x < aSegments.Length(); x++) {
+    dash.AppendElement(aSegments[x]);
   }
-  if(mSegments.Length()%2) { // If the number of elements is odd, concatenate again
-    for(mozilla::dom::AutoSequence<double>::index_type x = 0; x < mSegments.Length(); x++) {
-      dash.AppendElement(mSegments[x]);
+  if (aSegments.Length() % 2) { // If the number of elements is odd, concatenate again
+    for (uint32_t x = 0; x < aSegments.Length(); x++) {
+      dash.AppendElement(aSegments[x]);
     }
   }
 }
 
 void
-CanvasRenderingContext2D::GetLineDash(nsTArray<double>& mSegments) const {
+CanvasRenderingContext2D::GetLineDash(nsTArray<double>& aSegments) const {
   const FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
-  mSegments.Clear();
-
-  for(FallibleTArray<mozilla::gfx::Float>::index_type x = 0; x < dash.Length(); x++) {
-    mSegments.AppendElement(dash[x]);
+  aSegments.Clear();
+
+  for (uint32_t x = 0; x < dash.Length(); x++) {
+    aSegments.AppendElement(dash[x]);
   }
 }
 
 void
 CanvasRenderingContext2D::SetLineDashOffset(double mOffset) {
   CurrentState().dashOffset = mOffset;
 }
 
@@ -3219,17 +3220,17 @@ CanvasRenderingContext2D::GetGlobalCompo
     Demote();
   }
 #endif
 
 #undef CANVAS_OP_TO_GFX_OP
 }
 
 void
-CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
+CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
                                      double y, double w, double h,
                                      const nsAString& bgColor,
                                      uint32_t flags, ErrorResult& error)
 {
   // protect against too-large surfaces that will cause allocation
   // or overflow issues
   if (!gfxASurface::CheckSurfaceSize(gfxIntSize(int32_t(w), int32_t(h)),
                                      0xffff)) {
@@ -3248,26 +3249,23 @@ CanvasRenderingContext2D::DrawWindow(nsI
     // not permitted to use DrawWindow
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     error.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   // Flush layout updates
   if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
-    nsContentUtils::FlushLayoutForTree(window);
+    nsContentUtils::FlushLayoutForTree(&window);
   }
 
   nsRefPtr<nsPresContext> presContext;
-  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
-  if (win) {
-    nsIDocShell* docshell = win->GetDocShell();
-    if (docshell) {
-      docshell->GetPresContext(getter_AddRefs(presContext));
-    }
+  nsIDocShell* docshell = window.GetDocShell();
+  if (docshell) {
+    docshell->GetPresContext(getter_AddRefs(presContext));
   }
   if (!presContext) {
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   nscolor backgroundColor;
   if (!ParseColor(bgColor, &backgroundColor)) {
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -19,16 +19,17 @@
 #include "mozilla/dom/CanvasGradient.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasPattern.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 #include "imgIEncoder.h"
 
+class nsGlobalWindow;
 class nsXULElement;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 }
 
 namespace dom {
@@ -364,17 +365,17 @@ public:
 
   void SetImageSmoothingEnabled(bool imageSmoothingEnabled)
   {
     if (imageSmoothingEnabled != CurrentState().imageSmoothingEnabled) {
       CurrentState().imageSmoothingEnabled = imageSmoothingEnabled;
     }
   }
 
-  void DrawWindow(nsIDOMWindow* window, double x, double y, double w, double h,
+  void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h,
                   const nsAString& bgColor, uint32_t flags,
                   mozilla::ErrorResult& error);
   void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w,
                            double h, const nsAString& bgColor, uint32_t flags,
                            mozilla::ErrorResult& error);
 
   void Demote();
 
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -395,16 +395,21 @@ public:
    * false if there definitely isn't.
    */
   bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
 
   bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
+  uint32_t ListenerCount() const
+  {
+    return mListeners.Length();
+  }
+
   void MarkForCC();
 
   mozilla::dom::EventTarget* GetTarget() { return mTarget; }
 protected:
   void HandleEventInternal(nsPresContext* aPresContext,
                            mozilla::WidgetEvent* aEvent,
                            nsIDOMEvent** aDOMEvent,
                            mozilla::dom::EventTarget* aCurrentTarget,
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1004,32 +1004,33 @@ nsEventStateManager::PreHandleEvent(nsPr
 #ifdef DEBUG
   if (aEvent->HasDragEventMessage() && sIsPointerLocked) {
     NS_ASSERTION(sIsPointerLocked,
       "sIsPointerLocked is true. Drag events should be suppressed when the pointer is locked.");
   }
 #endif
   // Store last known screenPoint and clientPoint so pointer lock
   // can use these values as constants.
+  WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
   if (aEvent->mFlags.mIsTrusted &&
-      ((aEvent->IsMouseDerivedEvent() && IsMouseEventReal(aEvent)) ||
-       aEvent->eventStructType == NS_WHEEL_EVENT)) {
-    if (!sIsPointerLocked) {
-      sLastScreenPoint = nsDOMUIEvent::CalculateScreenPoint(aPresContext, aEvent);
-      sLastClientPoint = nsDOMUIEvent::CalculateClientPoint(aPresContext, aEvent, nullptr);
-    }
+      ((mouseEvent && IsMouseEventReal(mouseEvent)) ||
+       aEvent->eventStructType == NS_WHEEL_EVENT) &&
+      !sIsPointerLocked) {
+    sLastScreenPoint =
+      nsDOMUIEvent::CalculateScreenPoint(aPresContext, aEvent);
+    sLastClientPoint =
+      nsDOMUIEvent::CalculateClientPoint(aPresContext, aEvent, nullptr);
   }
 
   // Do not take account NS_MOUSE_ENTER/EXIT so that loading a page
   // when user is not active doesn't change the state to active.
   if (aEvent->mFlags.mIsTrusted &&
-      ((aEvent->eventStructType == NS_MOUSE_EVENT  &&
-        IsMouseEventReal(aEvent) &&
-        aEvent->message != NS_MOUSE_ENTER &&
-        aEvent->message != NS_MOUSE_EXIT) ||
+      ((mouseEvent && IsMouseEventReal(mouseEvent) &&
+        mouseEvent->message != NS_MOUSE_ENTER &&
+        mouseEvent->message != NS_MOUSE_EXIT) ||
        aEvent->eventStructType == NS_WHEEL_EVENT ||
        aEvent->eventStructType == NS_KEY_EVENT)) {
     if (gMouseOrKeyboardEventCounter == 0) {
       nsCOMPtr<nsIObserverService> obs =
         mozilla::services::GetObserverService();
       if (obs) {
         obs->NotifyObservers(nullptr, "user-interaction-active", nullptr);
         UpdateUserActivityTimer();
@@ -1039,17 +1040,16 @@ nsEventStateManager::PreHandleEvent(nsPr
   }
 
   *aStatus = nsEventStatus_eIgnore;
 
   nsMouseWheelTransaction::OnEvent(aEvent);
 
   switch (aEvent->message) {
   case NS_MOUSE_BUTTON_DOWN: {
-    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
     switch (mouseEvent->button) {
     case WidgetMouseEvent::eLeftButton:
 #ifndef XP_OS2
       BeginTrackingDragGesture(aPresContext, mouseEvent, aTargetFrame);
 #endif
       mLClickCount = mouseEvent->clickCount;
       SetClickCount(aPresContext, mouseEvent, aStatus);
       sNormalLMouseEventInProcess = true;
@@ -1064,17 +1064,16 @@ nsEventStateManager::PreHandleEvent(nsPr
 #endif
       mRClickCount = mouseEvent->clickCount;
       SetClickCount(aPresContext, mouseEvent, aStatus);
       break;
     }
     break;
   }
   case NS_MOUSE_BUTTON_UP: {
-    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
     switch (mouseEvent->button) {
       case WidgetMouseEvent::eLeftButton:
         if (Prefs::ClickHoldContextMenu()) {
           KillClickHoldTimer();
         }
 #ifndef XP_OS2
         StopTrackingDragGesture();
 #endif
@@ -1090,40 +1089,36 @@ nsEventStateManager::PreHandleEvent(nsPr
         break;
     }
     break;
   }
   case NS_MOUSE_EXIT:
     // If the event is not a top-level window exit, then it's not
     // really an exit --- we may have traversed widget boundaries but
     // we're still in our toplevel window.
-    {
-      WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
-      if (mouseEvent->exit != WidgetMouseEvent::eTopLevel) {
-        // Treat it as a synthetic move so we don't generate spurious
-        // "exit" or "move" events.  Any necessary "out" or "over" events
-        // will be generated by GenerateMouseEnterExit
-        mouseEvent->message = NS_MOUSE_MOVE;
-        mouseEvent->reason = WidgetMouseEvent::eSynthesized;
-        // then fall through...
-      } else {
-        GenerateMouseEnterExit(mouseEvent);
-        //This is a window level mouse exit event and should stop here
-        aEvent->message = 0;
-        break;
-      }
+    if (mouseEvent->exit != WidgetMouseEvent::eTopLevel) {
+      // Treat it as a synthetic move so we don't generate spurious
+      // "exit" or "move" events.  Any necessary "out" or "over" events
+      // will be generated by GenerateMouseEnterExit
+      mouseEvent->message = NS_MOUSE_MOVE;
+      mouseEvent->reason = WidgetMouseEvent::eSynthesized;
+      // then fall through...
+    } else {
+      GenerateMouseEnterExit(mouseEvent);
+      //This is a window level mouse exit event and should stop here
+      aEvent->message = 0;
+      break;
     }
   case NS_MOUSE_MOVE: {
     // on the Mac, GenerateDragGesture() may not return until the drag
     // has completed and so |aTargetFrame| may have been deleted (moving
     // a bookmark, for example).  If this is the case, however, we know
     // that ClearFrameRefs() has been called and it cleared out
     // |mCurrentTarget|. As a result, we should pass |mCurrentTarget|
     // into UpdateCursor().
-    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
     GenerateDragGesture(aPresContext, mouseEvent);
     UpdateCursor(aPresContext, aEvent, mCurrentTarget, aStatus);
     GenerateMouseEnterExit(mouseEvent);
     // Flush pending layout changes, so that later mouse move events
     // will go to the right nodes.
     FlushPendingEvents(aPresContext);
     break;
   }
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -12,16 +12,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIObserver.h"
 #include "mozilla/CORSMode.h"
 #include "DOMMediaStream.h"
 #include "AudioChannelCommon.h"
 #include "DecoderTraits.h"
 #include "nsIAudioChannelAgent.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/dom/TextTrackManager.h"
 
 // Define to output information on decoding and painting framerate
 /* #define DEBUG_FRAME_RATE 1 */
 
 class nsIChannel;
 class nsIHttpChannel;
 class nsILoadGroup;
@@ -508,22 +509,18 @@ public:
   uint32_t GetMozFrameBufferLength(ErrorResult& aRv) const;
 
   void SetMozFrameBufferLength(uint32_t aValue, ErrorResult& aRv);
 
   JSObject* MozGetMetadata(JSContext* aCx, ErrorResult& aRv);
 
   double MozFragmentEnd();
 
-  // XPCOM GetMozAudioChannelType() is OK
-
-  void SetMozAudioChannelType(const nsAString& aValue, ErrorResult& aRv)
-  {
-    SetHTMLAttr(nsGkAtoms::mozaudiochannel, aValue, aRv);
-  }
+  AudioChannel MozAudioChannelType() const;
+  void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
 
   TextTrackList* TextTracks() const;
 
   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
                                            const nsAString& aLabel,
                                            const nsAString& aLanguage);
 
   void AddTextTrack(TextTrack* aTextTrack) {
--- a/content/html/content/src/HTMLButtonElement.cpp
+++ b/content/html/content/src/HTMLButtonElement.cpp
@@ -193,18 +193,19 @@ HTMLButtonElement::PreHandleEvent(nsEven
   if (IsDisabledForEvents(aVisitor.mEvent->message)) {
     return NS_OK;
   }
 
   // Track whether we're in the outermost Dispatch invocation that will
   // cause activation of the input.  That is, if we're a click event, or a
   // DOMActivate that was dispatched directly, this will be set, but if we're
   // a DOMActivate dispatched from click handling, it will not be set.
+  WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
   bool outerActivateEvent =
-    (aVisitor.mEvent->IsLeftClickEvent() ||
+    ((mouseEvent && mouseEvent->IsLeftClickEvent()) ||
      (aVisitor.mEvent->message == NS_UI_ACTIVATE &&
       !mInInternalActivate));
 
   if (outerActivateEvent) {
     aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
     if (mType == NS_FORM_BUTTON_SUBMIT && mForm) {
       aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
       // tell the form that we are about to enter a click handler.
@@ -220,32 +221,35 @@ HTMLButtonElement::PreHandleEvent(nsEven
 nsresult
 HTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   nsresult rv = NS_OK;
   if (!aVisitor.mPresContext) {
     return rv;
   }
 
-  if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
-      aVisitor.mEvent->IsLeftClickEvent()) {
-    InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
-                             NS_UI_ACTIVATE, 1);
+  if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) {
+    WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+    if (mouseEvent && mouseEvent->IsLeftClickEvent()) {
+      InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
+                               NS_UI_ACTIVATE, 1);
 
-    nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
-    if (shell) {
-      nsEventStatus status = nsEventStatus_eIgnore;
-      mInInternalActivate = true;
-      shell->HandleDOMEventWithTarget(this, &actEvent, &status);
-      mInInternalActivate = false;
+      nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
+      if (shell) {
+        nsEventStatus status = nsEventStatus_eIgnore;
+        mInInternalActivate = true;
+        shell->HandleDOMEventWithTarget(this, &actEvent, &status);
+        mInInternalActivate = false;
 
-      // If activate is cancelled, we must do the same as when click is
-      // cancelled (revert the checkbox to its original value).
-      if (status == nsEventStatus_eConsumeNoDefault)
-        aVisitor.mEventStatus = status;
+        // If activate is cancelled, we must do the same as when click is
+        // cancelled (revert the checkbox to its original value).
+        if (status == nsEventStatus_eConsumeNoDefault) {
+          aVisitor.mEventStatus = status;
+        }
+      }
     }
   }
 
   // mForm is null if the event handler removed us from the document (bug 194582).
   if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
     // tell the form that we are about to exit a click handler
     // so the form knows not to defer subsequent submissions
     // the pending ones that were created during the handler
--- a/content/html/content/src/HTMLImageElement.cpp
+++ b/content/html/content/src/HTMLImageElement.cpp
@@ -368,17 +368,18 @@ HTMLImageElement::AfterSetAttr(int32_t a
 
 nsresult
 HTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   // If we are a map and get a mouse click, don't let it be handled by
   // the Generic Element as this could cause a click event to fire
   // twice, once by the image frame for the map and once by the Anchor
   // element. (bug 39723)
-  if (aVisitor.mEvent->IsLeftClickEvent()) {
+  WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+  if (mouseEvent && mouseEvent->IsLeftClickEvent()) {
     bool isMap = false;
     GetIsMap(&isMap);
     if (isMap) {
       aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -3107,18 +3107,19 @@ HTMLInputElement::PreHandleEvent(nsEvent
   //
   // This is a compatibility hack.
   //
 
   // Track whether we're in the outermost Dispatch invocation that will
   // cause activation of the input.  That is, if we're a click event, or a
   // DOMActivate that was dispatched directly, this will be set, but if we're
   // a DOMActivate dispatched from click handling, it will not be set.
+  WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
   bool outerActivateEvent =
-    (aVisitor.mEvent->IsLeftClickEvent() ||
+    ((mouseEvent && mouseEvent->IsLeftClickEvent()) ||
      (aVisitor.mEvent->message == NS_UI_ACTIVATE && !mInInternalActivate));
 
   if (outerActivateEvent) {
     aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
   }
 
   bool originalCheckedValue = false;
 
@@ -3337,24 +3338,28 @@ HTMLInputElement::MaybeInitPickers(nsEve
 {
   // Open a file picker when we receive a click on a <input type='file'>, or
   // open a color picker when we receive a click on a <input type='color'>.
   // A click is handled in the following cases:
   // - preventDefault() has not been called (or something similar);
   // - it's the left mouse button.
   // We do not prevent non-trusted click because authors can already use
   // .click(). However, the pickers will follow the rules of popup-blocking.
-  if (aVisitor.mEvent->IsLeftClickEvent() &&
-      !aVisitor.mEvent->mFlags.mDefaultPrevented) {
-    if (mType == NS_FORM_INPUT_FILE) {
-      return InitFilePicker(FILE_PICKER_FILE);
-    }
-    if (mType == NS_FORM_INPUT_COLOR) {
-      return InitColorPicker();
-    }
+  if (aVisitor.mEvent->mFlags.mDefaultPrevented) {
+    return NS_OK;
+  }
+  WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+  if (!(mouseEvent && mouseEvent->IsLeftClickEvent())) {
+    return NS_OK;
+  }
+  if (mType == NS_FORM_INPUT_FILE) {
+    return InitFilePicker(FILE_PICKER_FILE);
+  }
+  if (mType == NS_FORM_INPUT_COLOR) {
+    return InitColorPicker();
   }
   return NS_OK;
 }
 
 nsresult
 HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (!aVisitor.mPresContext) {
@@ -3390,33 +3395,36 @@ HTMLInputElement::PostHandleEvent(nsEven
   // Ideally we would make the default action for click and space just dispatch
   // DOMActivate, and the default action for DOMActivate flip the checkbox/
   // radio state and fire onchange.  However, for backwards compatibility, we
   // need to flip the state before firing click, and we need to fire click
   // when space is pressed.  So, we just nest the firing of DOMActivate inside
   // the click event handling, and allow cancellation of DOMActivate to cancel
   // the click.
   if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
-      !IsSingleLineTextControl(true) &&
-      aVisitor.mEvent->IsLeftClickEvent() &&
-      !ShouldPreventDOMActivateDispatch(aVisitor.mEvent->originalTarget)) {
-    InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
-                             NS_UI_ACTIVATE, 1);
-
-    nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
-    if (shell) {
-      nsEventStatus status = nsEventStatus_eIgnore;
-      mInInternalActivate = true;
-      rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
-      mInInternalActivate = false;
-
-      // If activate is cancelled, we must do the same as when click is
-      // cancelled (revert the checkbox to its original value).
-      if (status == nsEventStatus_eConsumeNoDefault)
-        aVisitor.mEventStatus = status;
+      !IsSingleLineTextControl(true)) {
+    WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+    if (mouseEvent && mouseEvent->IsLeftClickEvent() &&
+        !ShouldPreventDOMActivateDispatch(aVisitor.mEvent->originalTarget)) {
+      InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
+                               NS_UI_ACTIVATE, 1);
+
+      nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
+      if (shell) {
+        nsEventStatus status = nsEventStatus_eIgnore;
+        mInInternalActivate = true;
+        rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
+        mInInternalActivate = false;
+
+        // If activate is cancelled, we must do the same as when click is
+        // cancelled (revert the checkbox to its original value).
+        if (status == nsEventStatus_eConsumeNoDefault) {
+          aVisitor.mEventStatus = status;
+        }
+      }
     }
   }
 
   if (outerActivateEvent) {
     switch(oldType) {
       case NS_FORM_INPUT_SUBMIT:
       case NS_FORM_INPUT_IMAGE:
         if (mForm) {
--- a/content/html/content/src/HTMLLabelElement.cpp
+++ b/content/html/content/src/HTMLLabelElement.cpp
@@ -109,48 +109,47 @@ DestroyMouseDownPoint(void *    /*aObjec
 {
   LayoutDeviceIntPoint* pt = static_cast<LayoutDeviceIntPoint*>(aPropertyValue);
   delete pt;
 }
 
 nsresult
 HTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
+  WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
   if (mHandlingEvent ||
-      (!aVisitor.mEvent->IsLeftClickEvent() &&
+      (!(mouseEvent && mouseEvent->IsLeftClickEvent()) &&
        aVisitor.mEvent->message != NS_MOUSE_BUTTON_DOWN) ||
       aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
       !aVisitor.mPresContext ||
       // Don't handle the event if it's already been handled by another label
       aVisitor.mEvent->mFlags.mMultipleActionsPrevented) {
     return NS_OK;
   }
 
   // Strong ref because event dispatch is going to happen.
   nsRefPtr<Element> content = GetLabeledElement();
 
   if (content && !EventTargetIn(aVisitor.mEvent, content, this)) {
     mHandlingEvent = true;
     switch (aVisitor.mEvent->message) {
       case NS_MOUSE_BUTTON_DOWN:
-        if (aVisitor.mEvent->AsMouseEvent()->button ==
-              WidgetMouseEvent::eLeftButton) {
+        if (mouseEvent->button == WidgetMouseEvent::eLeftButton) {
           // We reset the mouse-down point on every event because there is
           // no guarantee we will reach the NS_MOUSE_CLICK code below.
           LayoutDeviceIntPoint* curPoint =
-            new LayoutDeviceIntPoint(aVisitor.mEvent->refPoint);
+            new LayoutDeviceIntPoint(mouseEvent->refPoint);
           SetProperty(nsGkAtoms::labelMouseDownPtProperty,
                       static_cast<void*>(curPoint),
                       DestroyMouseDownPoint);
         }
         break;
 
       case NS_MOUSE_CLICK:
-        if (aVisitor.mEvent->IsLeftClickEvent()) {
-          WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+        if (mouseEvent->IsLeftClickEvent()) {
           LayoutDeviceIntPoint* mouseDownPoint =
             static_cast<LayoutDeviceIntPoint*>(
               GetProperty(nsGkAtoms::labelMouseDownPtProperty));
 
           bool dragSelect = false;
           if (mouseDownPoint) {
             LayoutDeviceIntPoint dragDistance = *mouseDownPoint;
             DeleteProperty(nsGkAtoms::labelMouseDownPtProperty);
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3923,10 +3923,46 @@ HTMLMediaElement::AddTextTrack(TextTrack
 void
 HTMLMediaElement::PopulatePendingTextTrackList()
 {
   if (mTextTrackManager) {
     mTextTrackManager->PopulatePendingList();
   }
 }
 
+AudioChannel
+HTMLMediaElement::MozAudioChannelType() const
+{
+  switch (mAudioChannelType) {
+    case AUDIO_CHANNEL_CONTENT:
+      return AudioChannel::Content;
+
+    case AUDIO_CHANNEL_NOTIFICATION:
+      return AudioChannel::Notification;
+
+    case AUDIO_CHANNEL_ALARM:
+      return AudioChannel::Alarm;
+
+    case AUDIO_CHANNEL_TELEPHONY:
+      return AudioChannel::Telephony;
+
+    case AUDIO_CHANNEL_RINGER:
+      return AudioChannel::Ringer;
+
+    case AUDIO_CHANNEL_PUBLICNOTIFICATION:
+      return AudioChannel::Publicnotification;
+
+    default:
+      return AudioChannel::Normal;
+  }
+}
+
+void
+HTMLMediaElement::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
+{
+  nsString channel;
+  channel.AssignASCII(AudioChannelValues::strings[uint32_t(aValue)].value,
+                      AudioChannelValues::strings[uint32_t(aValue)].length);
+  SetHTMLAttr(nsGkAtoms::mozaudiochannel, channel, aRv);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLScriptElement.cpp
+++ b/content/html/content/src/HTMLScriptElement.cpp
@@ -6,17 +6,16 @@
 
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIDocument.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"  // for nsCaseInsensitiveStringComparator()
-#include "jsapi.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsServiceManagerUtils.h"
 #include "nsError.h"
 #include "nsIArray.h"
 #include "nsTArray.h"
 #include "nsDOMJSUtils.h"
--- a/content/html/content/src/HTMLVideoElement.cpp
+++ b/content/html/content/src/HTMLVideoElement.cpp
@@ -19,17 +19,16 @@
 #include "nsNetUtil.h"
 #include "nsXPCOMStrings.h"
 #include "prlock.h"
 #include "nsThreadUtils.h"
 #include "ImageContainer.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
-#include "jsapi.h"
 
 #include "nsITimer.h"
 
 #include "nsEventDispatcher.h"
 #include "nsIDOMProgressEvent.h"
 #include "nsIPowerManagerService.h"
 #include "MediaError.h"
 #include "MediaDecoder.h"
--- a/content/html/content/test/test_mozaudiochannel.html
+++ b/content/html/content/test/test_mozaudiochannel.html
@@ -38,16 +38,16 @@ audio2.mozAudioChannelType = "alarm";
 ok(audio2.mozAudioChannelType == "alarm", "Default audio2 channel == 'alarm'");
 
 var audio3 = document.getElementById("audio3");
 ok(audio3, "Audio Element exists");
 ok(audio3.mozAudioChannelType == "content", "Default audio3 channel == 'content'");
 try {
 audio3.mozAudioChannelType = "foo";
 } catch(e) {}
-ok(audio3.mozAudioChannelType == "normal", "audio3 channel == 'normal'");
+ok(audio3.mozAudioChannelType == "content", "audio3 channel == 'content'");
 audio3.mozAudioChannelType = "alarm";
 ok(audio3.mozAudioChannelType == "alarm", "audio3 channel == 'alarm'");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/encoder/ContainerWriter.h
+++ b/content/media/encoder/ContainerWriter.h
@@ -3,16 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ContainerWriter_h_
 #define ContainerWriter_h_
 
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
+#include "EncodedFrameContainer.h"
+#include "TrackMetadataBase.h"
 
 namespace mozilla {
 /**
  * ContainerWriter packs encoded track data into a specific media container.
  */
 class ContainerWriter {
 public:
   ContainerWriter()
@@ -26,31 +28,41 @@ public:
 
   /**
    * Writes encoded track data from aBuffer to a packet, and insert this packet
    * into the internal stream of container writer. aDuration is the playback
    * duration of this packet in number of samples. aFlags is true with
    * END_OF_STREAM if this is the last packet of track.
    * Currently, WriteEncodedTrack doesn't support multiple tracks.
    */
-  virtual nsresult WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer,
-                                     int aDuration, uint32_t aFlags = 0) = 0;
+  virtual nsresult WriteEncodedTrack(const EncodedFrameContainer& aData,
+                                     uint32_t aFlags = 0) = 0;
+
+  /**
+   * Set the meta data pointer into muxer
+   * This function will check the integrity of aMetadata.
+   * If the meta data isn't well format, this function will return NS_ERROR_FAILURE to caller,
+   * else save the pointer to mMetadata and return NS_OK.
+   */
+  virtual nsresult SetMetadata(nsRefPtr<TrackMetadataBase> aMetadata) = 0;
 
   enum {
-    FLUSH_NEEDED = 1 << 0
+    FLUSH_NEEDED = 1 << 0,
+    GET_HEADER = 1 << 1
   };
 
   /**
    * Copies the final container data to a buffer if it has accumulated enough
    * packets from WriteEncodedTrack. This buffer of data is appended to
    * aOutputBufs, and existing elements of aOutputBufs should not be modified.
    * aFlags is true with FLUSH_NEEDED will force OggWriter to flush an ogg page
    * even it is not full, and copy these container data to a buffer for
    * aOutputBufs to append.
    */
   virtual nsresult GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
                                     uint32_t aFlags = 0) = 0;
 
 protected:
+  nsRefPtr<TrackMetadataBase> mMetadata;
   bool mInitialized;
 };
 }
 #endif
new file mode 100644
--- /dev/null
+++ b/content/media/encoder/EncodedFrameContainer.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef EncodedFrameContainer_H_
+#define EncodedFrameContainer_H_
+
+#include "nsTArray.h"
+
+namespace mozilla {
+
+class EncodedFrame;
+
+/*
+ * This container is used to carry video or audio encoded data from encoder to muxer.
+ * The media data object is created by encoder and recycle by the destructor.
+ * Only allow to store audio or video encoded data in EncodedData.
+ */
+class EncodedFrameContainer
+{
+public:
+  // Append encoded frame data
+  void AppendEncodedFrame(EncodedFrame* aEncodedFrame)
+  {
+    mEncodedFrames.AppendElement(aEncodedFrame);
+  }
+  // Retrieve all of the encoded frames
+  const nsTArray<nsAutoPtr<EncodedFrame> >& GetEncodedFrames() const
+  {
+    return mEncodedFrames;
+  }
+private:
+  // This container is used to store the video or audio encoded packets.
+  // Muxer should check mFrameType and get the encoded data type from mEncodedFrames.
+  nsTArray<nsAutoPtr<EncodedFrame> > mEncodedFrames;
+};
+
+// Represent one encoded frame
+class EncodedFrame
+{
+public:
+  EncodedFrame() :
+    mTimeStamp(0),
+    mDuration(0),
+    mFrameType(UNKNOW)
+  {}
+  enum FrameType {
+    I_FRAME,      // intraframe
+    P_FRAME,      // predicted frame
+    B_FRAME,      // bidirectionally predicted frame
+    AUDIO_FRAME,  // audio frame
+    UNKNOW        // FrameType not set
+  };
+  const nsTArray<uint8_t>& GetFrameData() const
+  {
+    return mFrameData;
+  }
+  void SetFrameData(nsTArray<uint8_t> *aData)
+  {
+    mFrameData.SwapElements(*aData);
+  }
+  uint64_t GetTimeStamp() const { return mTimeStamp; }
+  void SetTimeStamp(uint64_t aTimeStamp) { mTimeStamp = aTimeStamp; }
+
+  uint64_t GetDuration() const { return mDuration; }
+  void SetDuration(uint64_t aDuration) { mDuration = aDuration; }
+
+  FrameType GetFrameType() const { return mFrameType; }
+  void SetFrameType(FrameType aFrameType) { mFrameType = aFrameType; }
+private:
+  // Encoded data
+  nsTArray<uint8_t> mFrameData;
+  uint64_t mTimeStamp;
+  // The playback duration of this packet in number of samples
+  uint64_t mDuration;
+  // Represent what is in the FrameData
+  FrameType mFrameType;
+};
+
+}
+#endif
--- a/content/media/encoder/MediaEncoder.cpp
+++ b/content/media/encoder/MediaEncoder.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "MediaEncoder.h"
 #include "MediaDecoder.h"
 #include "nsIPrincipal.h"
+
 #ifdef MOZ_OGG
 #include "OggWriter.h"
 #endif
 #ifdef MOZ_OPUS
 #include "OpusTrackEncoder.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
@@ -123,27 +124,25 @@ MediaEncoder::CreateEncoder(const nsAStr
                              videoEncoder.forget(), aMIMEType);
 
 
   return encoder.forget();
 }
 
 /**
  * GetEncodedData() runs as a state machine, starting with mState set to
- * ENCODE_HEADER, the procedure should be as follow:
+ * GET_METADDATA, the procedure should be as follow:
  *
  * While non-stop
- *   If mState is ENCODE_HEADER
- *     Create the header from audio/video encoder
- *     If a header is generated
- *       Insert header data into the container stream of writer
- *       Force copied the final container data from writer
- *       Return the copy of final container data
- *     Else
+ *   If mState is GET_METADDATA
+ *     Get the meta data from audio/video encoder
+ *     If a meta data is generated
+ *       Get meta data from audio/video encoder
  *       Set mState to ENCODE_TRACK
+ *       Return the final container data
  *
  *   If mState is ENCODE_TRACK
  *     Get encoded track data from audio/video encoder
  *     If a packet of track data is generated
  *       Insert encoded track data into the container stream of writer
  *       If the final container data is copied to aOutput
  *         Return the copy of final container data
  *       If this is the last packet of input stream
@@ -158,58 +157,46 @@ MediaEncoder::GetEncodedData(nsTArray<ns
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
   aMIMEType = mMIMEType;
 
   bool reloop = true;
   while (reloop) {
     switch (mState) {
-    case ENCODE_HEADER: {
-      nsTArray<uint8_t> buffer;
-      nsresult rv = mAudioEncoder->GetHeader(&buffer);
+    case ENCODE_METADDATA: {
+      nsRefPtr<TrackMetadataBase> meta = mAudioEncoder->GetMetadata();
+      MOZ_ASSERT(meta);
+      nsresult rv = mWriter->SetMetadata(meta);
       if (NS_FAILED(rv)) {
-        // Encoding might be canceled.
-        mState = ENCODE_DONE;
-        break;
+       mState = ENCODE_DONE;
+       break;
       }
 
-      if (!buffer.IsEmpty()) {
-        rv = mWriter->WriteEncodedTrack(buffer, 0);
-        if (NS_FAILED(rv)) {
-          LOG("ERROR! Fail to write header to the media container.");
-          mState = ENCODE_DONE;
-          break;
-        }
+      rv = mWriter->GetContainerData(aOutputBufs,
+                                     ContainerWriter::GET_HEADER);
+      if (NS_FAILED(rv)) {
+       mState = ENCODE_DONE;
+       break;
+      }
 
-        rv = mWriter->GetContainerData(aOutputBufs,
-                                       ContainerWriter::FLUSH_NEEDED);
-        if (NS_SUCCEEDED(rv)) {
-          // Successfully get the copy of final container data from writer.
-          reloop = false;
-        }
-      } else {
-        // No more headers, starts to encode tracks.
-        mState = ENCODE_TRACK;
-      }
+      mState = ENCODE_TRACK;
       break;
     }
 
     case ENCODE_TRACK: {
-      nsTArray<uint8_t> buffer;
-      int encodedDuration = 0;
-      nsresult rv = mAudioEncoder->GetEncodedTrack(&buffer, encodedDuration);
+      EncodedFrameContainer encodedData;
+      nsresult rv = mAudioEncoder->GetEncodedTrack(encodedData);
       if (NS_FAILED(rv)) {
         // Encoding might be canceled.
         LOG("ERROR! Fail to get encoded data from encoder.");
         mState = ENCODE_DONE;
         break;
       }
-
-      rv = mWriter->WriteEncodedTrack(buffer, encodedDuration,
+      rv = mWriter->WriteEncodedTrack(encodedData,
                                       mAudioEncoder->IsEncodingComplete() ?
                                       ContainerWriter::END_OF_STREAM : 0);
       if (NS_FAILED(rv)) {
         LOG("ERROR! Fail to write encoded track to the media container.");
         mState = ENCODE_DONE;
         break;
       }
 
--- a/content/media/encoder/MediaEncoder.h
+++ b/content/media/encoder/MediaEncoder.h
@@ -46,30 +46,30 @@ namespace mozilla {
  *
  * 4) To stop encoding, remove this component from its source stream.
  *    => sourceStream->RemoveListener(encoder);
  */
 class MediaEncoder : public MediaStreamListener
 {
 public :
   enum {
-    ENCODE_HEADER,
+    ENCODE_METADDATA,
     ENCODE_TRACK,
     ENCODE_DONE,
   };
 
   MediaEncoder(ContainerWriter* aWriter,
                AudioTrackEncoder* aAudioEncoder,
                VideoTrackEncoder* aVideoEncoder,
                const nsAString& aMIMEType)
     : mWriter(aWriter)
     , mAudioEncoder(aAudioEncoder)
     , mVideoEncoder(aVideoEncoder)
     , mMIMEType(aMIMEType)
-    , mState(MediaEncoder::ENCODE_HEADER)
+    , mState(MediaEncoder::ENCODE_METADDATA)
     , mShutdown(false)
   {}
 
   ~MediaEncoder() {};
 
   /**
    * Notified by the control loop of MediaStreamGraph; aQueueMedia is the raw
    * track data in form of MediaSegment.
--- a/content/media/encoder/OpusTrackEncoder.cpp
+++ b/content/media/encoder/OpusTrackEncoder.cpp
@@ -110,17 +110,16 @@ SerializeOpusCommentHeader(const nsCStri
     SerializeToBuffer(aComments[i], aOutput);
   }
 }
 
 }  // Anonymous namespace.
 
 OpusTrackEncoder::OpusTrackEncoder()
   : AudioTrackEncoder()
-  , mEncoderState(ID_HEADER)
   , mEncoder(nullptr)
   , mSourceSegment(new AudioSegment())
   , mLookahead(0)
   , mResampler(nullptr)
 {
 }
 
 OpusTrackEncoder::~OpusTrackEncoder()
@@ -182,72 +181,57 @@ OpusTrackEncoder::GetOutputSampleRate()
 }
 
 int
 OpusTrackEncoder::GetPacketDuration()
 {
   return GetOutputSampleRate() * kFrameDurationMs / 1000;
 }
 
-nsresult
-OpusTrackEncoder::GetHeader(nsTArray<uint8_t>* aOutput)
+nsRefPtr<TrackMetadataBase>
+OpusTrackEncoder::GetMetadata()
 {
   {
     // Wait if mEncoder is not initialized.
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     while (!mCanceled && !mEncoder) {
       mReentrantMonitor.Wait();
     }
   }
 
   if (mCanceled || mDoneEncoding) {
-    return NS_ERROR_FAILURE;
+    return nullptr;
+  }
+
+  OpusMetadata* meta = new OpusMetadata();
+
+  mLookahead = 0;
+  int error = opus_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&mLookahead));
+  if (error != OPUS_OK) {
+    mLookahead = 0;
   }
 
-  switch (mEncoderState) {
-  case ID_HEADER:
-  {
-    mLookahead = 0;
-    int error = opus_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&mLookahead));
-    if (error != OPUS_OK) {
-      mLookahead = 0;
-    }
+  // The ogg time stamping and pre-skip is always timed at 48000.
+  SerializeOpusIdHeader(mChannels, mLookahead*(kOpusSamplingRate/mSamplingRate),
+                        mSamplingRate, &meta->mIdHeader);
 
-    // The ogg time stamping and pre-skip is always timed at 48000.
-    SerializeOpusIdHeader(mChannels, mLookahead*(kOpusSamplingRate/mSamplingRate),
-                          mSamplingRate, aOutput);
+  nsCString vendor;
+  vendor.AppendASCII(opus_get_version_string());
 
-    mEncoderState = COMMENT_HEADER;
-    break;
-  }
-  case COMMENT_HEADER:
-  {
-    nsCString vendor;
-    vendor.AppendASCII(opus_get_version_string());
-
-    nsTArray<nsCString> comments;
-    comments.AppendElement(NS_LITERAL_CSTRING("ENCODER=Mozilla" MOZ_APP_UA_VERSION));
+  nsTArray<nsCString> comments;
+  comments.AppendElement(NS_LITERAL_CSTRING("ENCODER=Mozilla" MOZ_APP_UA_VERSION));
 
-    SerializeOpusCommentHeader(vendor, comments, aOutput);
+  SerializeOpusCommentHeader(vendor, comments,
+                             &meta->mCommentHeader);
 
-    mEncoderState = DATA;
-    break;
-  }
-  case DATA:
-    // No more headers.
-    break;
-  default:
-    MOZ_CRASH("Invalid state");
-  }
-  return NS_OK;
+  return meta;
 }
 
 nsresult
-OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
-                                  int &aOutputDuration)
+OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
 {
   {
     // Move all the samples from mRawSegment to mSourceSegment. We only hold
     // the monitor in this block.
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
     // Wait if mEncoder is not initialized, or when not enough raw data, but is
     // not the end of stream nor is being canceled.
@@ -292,16 +276,18 @@ OpusTrackEncoder::GetEncodedTrack(nsTArr
       memset(pcm.Elements() + frameCopied * mChannels, 0,
              frameToCopy * mChannels * sizeof(AudioDataValue));
     }
 
     frameCopied += frameToCopy;
     iter.Next();
   }
 
+  EncodedFrame* audiodata = new EncodedFrame();
+  audiodata->SetFrameType(EncodedFrame::AUDIO_FRAME);
   if (mResampler) {
     nsAutoTArray<AudioDataValue, 9600> resamplingDest;
     // We want to consume all the input data, so we slightly oversize the
     // resampled data buffer so we can fit the output data in. We cannot really
     // predict the output frame count at each call.
     uint32_t outframes = frameCopied * kOpusSamplingRate / mSamplingRate + 1;
     uint32_t inframes = frameCopied;
 
@@ -316,20 +302,20 @@ OpusTrackEncoder::GetEncodedTrack(nsTArr
     float* in = reinterpret_cast<float*>(pcm.Elements());
     float* out = reinterpret_cast<float*>(resamplingDest.Elements());
     speex_resampler_process_interleaved_float(mResampler, in, &inframes,
                                                           out, &outframes);
 #endif
 
     pcm = resamplingDest;
     // This is always at 48000Hz.
-    aOutputDuration = outframes;
+    audiodata->SetDuration(outframes);
   } else {
     // The ogg time stamping and pre-skip is always timed at 48000.
-    aOutputDuration = frameCopied * (kOpusSamplingRate / mSamplingRate);
+    audiodata->SetDuration(frameCopied * (kOpusSamplingRate / mSamplingRate));
   }
 
   // Remove the raw data which has been pulled to pcm buffer.
   // The value of frameCopied should equal to (or smaller than, if eos)
   // GetPacketDuration().
   mSourceSegment->RemoveLeading(frameCopied);
 
   // Has reached the end of input stream and all queued data has pulled for
@@ -343,32 +329,34 @@ OpusTrackEncoder::GetEncodedTrack(nsTArr
   }
 
   // Append null data to pcm buffer if the leftover data is not enough for
   // opus encoder.
   if (frameCopied < GetPacketDuration() && mEndOfStream) {
     memset(pcm.Elements() + frameCopied * mChannels, 0,
            (GetPacketDuration()-frameCopied)*mChannels*sizeof(AudioDataValue));
   }
-
+  nsTArray<uint8_t> frameData;
   // Encode the data with Opus Encoder.
-  aOutput->SetLength(MAX_DATA_BYTES);
+  frameData.SetLength(MAX_DATA_BYTES);
   // result is returned as opus error code if it is negative.
   int result = 0;
 #ifdef MOZ_SAMPLE_TYPE_S16
   const opus_int16* pcmBuf = static_cast<opus_int16*>(pcm.Elements());
   result = opus_encode(mEncoder, pcmBuf, GetPacketDuration(),
-                       aOutput->Elements(), MAX_DATA_BYTES);
+                       frameData.Elements(), MAX_DATA_BYTES);
 #else
   const float* pcmBuf = static_cast<float*>(pcm.Elements());
   result = opus_encode_float(mEncoder, pcmBuf, GetPacketDuration(),
-                             aOutput->Elements(), MAX_DATA_BYTES);
+                             frameData.Elements(), MAX_DATA_BYTES);
 #endif
-  aOutput->SetLength(result >= 0 ? result : 0);
+  frameData.SetLength(result >= 0 ? result : 0);
 
   if (result < 0) {
     LOG("[Opus] Fail to encode data! Result: %s.", opus_strerror(result));
   }
 
+  audiodata->SetFrameData(&frameData);
+  aData.AppendEncodedFrame(audiodata);
   return result >= 0 ? NS_OK : NS_ERROR_FAILURE;
 }
 
 }
--- a/content/media/encoder/OpusTrackEncoder.h
+++ b/content/media/encoder/OpusTrackEncoder.h
@@ -4,44 +4,49 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef OpusTrackEncoder_h_
 #define OpusTrackEncoder_h_
 
 #include <stdint.h>
 #include <speex/speex_resampler.h>
 #include "TrackEncoder.h"
-#include "nsCOMPtr.h"
 
 struct OpusEncoder;
 
 namespace mozilla {
 
+// Opus meta data structure
+class OpusMetadata : public TrackMetadataBase
+{
+public:
+  // The ID Header of OggOpus. refer to http://wiki.xiph.org/OggOpus.
+  nsTArray<uint8_t> mIdHeader;
+  // The Comment Header of OggOpus.
+  nsTArray<uint8_t> mCommentHeader;
+
+  MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_OPUS; }
+};
+
 class OpusTrackEncoder : public AudioTrackEncoder
 {
 public:
   OpusTrackEncoder();
   virtual ~OpusTrackEncoder();
 
-  nsresult GetHeader(nsTArray<uint8_t>* aOutput) MOZ_OVERRIDE;
+  nsRefPtr<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
 
-  nsresult GetEncodedTrack(nsTArray<uint8_t>* aOutput, int &aOutputDuration) MOZ_OVERRIDE;
+  nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
 
 protected:
   int GetPacketDuration() MOZ_OVERRIDE;
 
   nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
 
 private:
-  enum {
-    ID_HEADER,
-    COMMENT_HEADER,
-    DATA
-  } mEncoderState;
-
   /**
    * Get the samplerate of the data to be fed to the Opus encoder. This might be
    * different from the intput samplerate if resampling occurs.
    */
   int GetOutputSampleRate();
 
   /**
    * The Opus encoder from libopus.
--- a/content/media/encoder/TrackEncoder.h
+++ b/content/media/encoder/TrackEncoder.h
@@ -5,16 +5,18 @@
 
 #ifndef TrackEncoder_h_
 #define TrackEncoder_h_
 
 #include "mozilla/ReentrantMonitor.h"
 
 #include "AudioSegment.h"
 #include "StreamBuffer.h"
+#include "TrackMetadataBase.h"
+#include "EncodedFrameContainer.h"
 
 namespace mozilla {
 
 class MediaStreamGraph;
 
 /**
  * Base class of AudioTrackEncoder and VideoTrackEncoder. Lifetimes managed by
  * MediaEncoder. Most methods can only be called on the MediaEncoder's thread,
@@ -43,27 +45,24 @@ public:
 
   /**
    * Notified by the same callback of MediaEncoder when it has been removed from
    * MediaStreamGraph. Called on the MediaStreamGraph thread.
    */
   virtual void NotifyRemoved(MediaStreamGraph* aGraph) = 0;
 
   /**
-   * Creates and sets up header for a specific codec. Result data is returned
-   * in aOutput.
+   * Creates and sets up meta data for a specific codec
    */
-  virtual nsresult GetHeader(nsTArray<uint8_t>* aOutput) = 0;
+  virtual nsRefPtr<TrackMetadataBase> GetMetadata() = 0;
 
   /**
-   * Encodes raw segments. Result data is returned in aOutput. aOutputDuration
-   * is the playback duration of this packet in number of samples.
+   * Encodes raw segments. Result data is returned in aData.
    */
-  virtual nsresult GetEncodedTrack(nsTArray<uint8_t>* aOutput,
-                                   int &aOutputDuration) = 0;
+  virtual nsresult GetEncodedTrack(EncodedFrameContainer& aData) = 0;
 };
 
 class AudioTrackEncoder : public TrackEncoder
 {
 public:
   AudioTrackEncoder()
     : TrackEncoder()
     , mChannels(0)
new file mode 100644
--- /dev/null
+++ b/content/media/encoder/TrackMetadataBase.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TrackMetadataBase_h_
+#define TrackMetadataBase_h_
+
+#include "nsTArray.h"
+#include "nsCOMPtr.h"
+namespace mozilla {
+
+// A class represent meta data for various codec format. Only support one track information.
+class TrackMetadataBase
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackMetadataBase)
+  enum MetadataKind {
+    METADATA_OPUS,    // Represent the Opus metadata
+    METADATA_VP8,
+    METADATA_UNKNOW   // Metadata Kind not set
+  };
+  virtual ~TrackMetadataBase() {}
+  // Return the specific metadata kind
+  virtual MetadataKind GetKind() const = 0;
+};
+
+}
+#endif
--- a/content/media/encoder/moz.build
+++ b/content/media/encoder/moz.build
@@ -3,18 +3,20 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MODULE = 'content'
 
 EXPORTS += [
     'ContainerWriter.h',
+    'EncodedFrameContainer.h',
     'MediaEncoder.h',
     'TrackEncoder.h',
+    'TrackMetadataBase.h',
 ]
 
 SOURCES += [
     'MediaEncoder.cpp',
     'TrackEncoder.cpp',
 ]
 
 if CONFIG['MOZ_OPUS']:
--- a/content/media/ogg/OggWriter.cpp
+++ b/content/media/ogg/OggWriter.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "OggWriter.h"
 #include "prtime.h"
+#include "OpusTrackEncoder.h"
 
 #undef LOG
 #ifdef MOZ_WIDGET_GONK
 #include <android/log.h>
 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args);
 #else
 #define LOG(args, ...)
 #endif
@@ -41,19 +42,40 @@ OggWriter::Init()
   mPacket.bytes = 0;
 
   mInitialized = (rc == 0);
 
   return (rc == 0) ? NS_OK : NS_ERROR_NOT_INITIALIZED;
 }
 
 nsresult
-OggWriter::WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer, int aDuration,
+OggWriter::WriteEncodedTrack(const EncodedFrameContainer& aData,
                              uint32_t aFlags)
 {
+  for (uint32_t i = 0; i < aData.GetEncodedFrames().Length(); i++) {
+    if (aData.GetEncodedFrames()[i]->GetFrameType() != EncodedFrame::AUDIO_FRAME) {
+      LOG("[OggWriter] wrong encoded data type!");
+      return NS_ERROR_FAILURE;
+    }
+
+    nsresult rv = WriteEncodedData(aData.GetEncodedFrames()[i]->GetFrameData(),
+                                   aData.GetEncodedFrames()[i]->GetDuration(),
+                                   aFlags);
+    if (NS_FAILED(rv)) {
+      LOG("%p Failed to WriteEncodedTrack!", this);
+      return rv;
+    }
+  }
+  return NS_OK;
+}
+
+nsresult
+OggWriter::WriteEncodedData(const nsTArray<uint8_t>& aBuffer, int aDuration,
+                            uint32_t aFlags)
+{
   if (!mInitialized) {
     LOG("[OggWriter] OggWriter has not initialized!");
     return NS_ERROR_FAILURE;
   }
 
   MOZ_ASSERT(!ogg_stream_eos(&mOggStreamState),
              "No data can be written after eos has marked.");
 
@@ -82,38 +104,89 @@ OggWriter::WriteEncodedTrack(const nsTAr
     mPacket.b_o_s = 0;
   }
   mPacket.packetno++;
   mPacket.packet = nullptr;
 
   return NS_OK;
 }
 
+void
+OggWriter::ProduceOggPage(nsTArray<nsTArray<uint8_t> >* aOutputBufs)
+{
+  aOutputBufs->AppendElement();
+  aOutputBufs->LastElement().SetLength(mOggPage.header_len +
+                                       mOggPage.body_len);
+  memcpy(aOutputBufs->LastElement().Elements(), mOggPage.header,
+         mOggPage.header_len);
+  memcpy(aOutputBufs->LastElement().Elements() + mOggPage.header_len,
+         mOggPage.body, mOggPage.body_len);
+}
+
 nsresult
 OggWriter::GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
                             uint32_t aFlags)
 {
   int rc = -1;
+  // Generate the oggOpus Header
+  if (aFlags & ContainerWriter::GET_HEADER) {
+    OpusMetadata* meta = static_cast<OpusMetadata*>(mMetadata.get());
+    NS_ASSERTION(meta, "should have meta data");
+    NS_ASSERTION(meta->GetKind() == TrackMetadataBase::METADATA_OPUS,
+                 "should have Opus meta data");
+
+    nsresult rv = WriteEncodedData(meta->mIdHeader, 0);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rc = ogg_stream_flush(&mOggStreamState, &mOggPage);
+    NS_ENSURE_TRUE(rc > 0, NS_ERROR_FAILURE);
+    ProduceOggPage(aOutputBufs);
+
+    rv = WriteEncodedData(meta->mCommentHeader, 0);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rc = ogg_stream_flush(&mOggStreamState, &mOggPage);
+    NS_ENSURE_TRUE(rc > 0, NS_ERROR_FAILURE);
+
+    ProduceOggPage(aOutputBufs);
+    return NS_OK;
+
   // Force generate a page even if the amount of packet data is not enough.
   // Usually do so after a header packet.
-  if (aFlags & ContainerWriter::FLUSH_NEEDED) {
+  } else if (aFlags & ContainerWriter::FLUSH_NEEDED) {
     // rc = 0 means no packet to put into a page, or an internal error.
     rc = ogg_stream_flush(&mOggStreamState, &mOggPage);
   } else {
     // rc = 0 means insufficient data has accumulated to fill a page, or an
     // internal error has occurred.
     rc = ogg_stream_pageout(&mOggStreamState, &mOggPage);
   }
 
   if (rc) {
-    aOutputBufs->AppendElement();
-    aOutputBufs->LastElement().SetLength(mOggPage.header_len +
-                                         mOggPage.body_len);
-    memcpy(aOutputBufs->LastElement().Elements(), mOggPage.header,
-           mOggPage.header_len);
-    memcpy(aOutputBufs->LastElement().Elements() + mOggPage.header_len,
-           mOggPage.body, mOggPage.body_len);
+    ProduceOggPage(aOutputBufs);
   }
 
   return (rc > 0) ? NS_OK : NS_ERROR_FAILURE;
 }
 
+nsresult
+OggWriter::SetMetadata(nsRefPtr<TrackMetadataBase> aMetadata)
+{
+  if (aMetadata->GetKind() != TrackMetadataBase::METADATA_OPUS) {
+    LOG("wrong meta data type!");
+    return NS_ERROR_FAILURE;
+  }
+  // Validate each field of METADATA
+  OpusMetadata* meta = static_cast<OpusMetadata*>(aMetadata.get());
+  if (meta->mIdHeader.Length() == 0) {
+    LOG("miss mIdHeader!");
+    return NS_ERROR_FAILURE;
+  }
+  if (meta->mCommentHeader.Length() == 0) {
+    LOG("miss mCommentHeader!");
+    return NS_ERROR_FAILURE;
+  }
+
+  mMetadata = aMetadata;
+  return NS_OK;
 }
+
+}
--- a/content/media/ogg/OggWriter.h
+++ b/content/media/ogg/OggWriter.h
@@ -17,23 +17,31 @@ namespace mozilla {
  * For more details, please reference:
  * http://www.xiph.org/ogg/doc/libogg/encoding.html
  */
 class OggWriter : public ContainerWriter
 {
 public:
   OggWriter();
 
-  nsresult WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer, int aDuration,
+  nsresult WriteEncodedTrack(const EncodedFrameContainer &aData,
                              uint32_t aFlags = 0) MOZ_OVERRIDE;
 
   nsresult GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
                             uint32_t aFlags = 0) MOZ_OVERRIDE;
 
+  // Check metadata type integrity and reject unacceptable track encoder.
+  nsresult SetMetadata(nsRefPtr<TrackMetadataBase> aMetadata) MOZ_OVERRIDE;
+
 private:
   nsresult Init();
 
+  nsresult WriteEncodedData(const nsTArray<uint8_t>& aBuffer, int aDuration,
+                            uint32_t aFlags = 0);
+
+  void ProduceOggPage(nsTArray<nsTArray<uint8_t> >* aOutputBufs);
+
   ogg_stream_state mOggStreamState;
   ogg_page mOggPage;
   ogg_packet mPacket;
 };
 }
 #endif
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AudioContext_h_
 #define AudioContext_h_
 
-#include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "EnableWebAudioCheck.h"
 #include "MediaBufferDecoder.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/TypedArray.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMEventTargetHelper.h"
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AudioDestinationNode_h_
 #define AudioDestinationNode_h_
 
-#include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "AudioNode.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAudioChannelAgent.h"
 #include "AudioChannelCommon.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -28,17 +28,16 @@
 #include "nsXBLPrototypeBinding.h"
 #include "nsXBLDocumentInfo.h"
 #include "mozilla/dom/XBLChildrenElement.h"
 
 #include "nsIStyleRuleProcessor.h"
 #include "nsRuleProcessorData.h"
 #include "nsIWeakReference.h"
 
-#include "jsapi.h"
 #include "nsIXPConnect.h"
 #include "nsDOMCID.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsTHashtable.h"
 
 #include "nsIScriptContext.h"
 #include "nsBindingManager.h"
--- a/content/xul/document/src/nsXULContentSink.cpp
+++ b/content/xul/document/src/nsXULContentSink.cpp
@@ -9,17 +9,16 @@
  * to build a content model (the "prototype" document) from XUL.
  *
  * For more information on XUL,
  * see http://developer.mozilla.org/en/docs/XUL
  */
 
 #include "nsXULContentSink.h"
 
-#include "jsapi.h"
 #include "jsfriendapi.h"
 
 #include "nsCOMPtr.h"
 #include "nsForwardReference.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIContentSink.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -17,17 +17,16 @@
 #include "nsIObjectOutputStream.h"
 #include "nsIObserverService.h"
 #include "nsIStringStream.h"
 #include "nsIStorageStream.h"
 
 #include "nsNetUtil.h"
 #include "nsAppDirectoryServiceDefs.h"
 
-#include "jsapi.h"
 #include "js/Tracer.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
--- a/content/xul/templates/src/nsXULContentBuilder.cpp
+++ b/content/xul/templates/src/nsXULContentBuilder.cpp
@@ -28,17 +28,16 @@
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsAttrName.h"
 #include "nsNodeUtils.h"
 #include "mozAutoDocUpdate.h"
 #include "nsTextNode.h"
 
-#include "jsapi.h"
 #include "pldhash.h"
 #include "rdf.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 //
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -8746,17 +8746,17 @@ nsDocShell::InternalLoad(nsIURI * aURI,
         NS_ASSERTION(requestingElement, "A frame but no DOM element!?");
         contentType = nsIContentPolicy::TYPE_SUBDOCUMENT;
     } else {
         contentType = nsIContentPolicy::TYPE_DOCUMENT;
     }
 
     nsISupports* context = requestingElement;
     if (!context) {
-        context = nsGlobalWindow::ToSupports(mScriptGlobal);
+        context = ToSupports(mScriptGlobal);
     }
 
     // XXXbz would be nice to know the loading principal here... but we don't
     nsCOMPtr<nsIPrincipal> loadingPrincipal = do_QueryInterface(aOwner);
     if (!loadingPrincipal && aReferrer) {
         nsCOMPtr<nsIScriptSecurityManager> secMan =
             do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/apps/src/PermissionsTable.jsm
+++ b/dom/apps/src/PermissionsTable.jsm
@@ -297,16 +297,21 @@ this.PermissionsTable =  { geolocation: 
                              privileged: DENY_ACTION,
                              certified: ALLOW_ACTION
                            },
                            "audio-capture": {
                              app: PROMPT_ACTION,
                              privileged: PROMPT_ACTION,
                              certified: PROMPT_ACTION
                            },
+                           "video-capture": {
+                             app: PROMPT_ACTION,
+                             privileged: PROMPT_ACTION,
+                             certified: PROMPT_ACTION
+                           },
                          };
 
 /**
  * Append access modes to the permission name as suffixes.
  *   e.g. permission name 'contacts' with ['read', 'write'] =
  *   ['contacts-read', contacts-write']
  * @param string aPermName
  * @param array aAccess
--- a/dom/apps/tests/chrome.ini
+++ b/dom/apps/tests/chrome.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 
 [test_apps_service.xul]
 [test_operator_app_install.js]
 [test_operator_app_install.xul]
+# bug 928262
+ skip-if = os == "win"
--- a/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/DOMException.h"
 
-#include "jsapi.h"
 #include "jsprf.h"
 #include "js/OldDebugAPI.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/Util.h"
 #include "mozilla/dom/Exceptions.h"
 #include "nsContentUtils.h"
 #include "nsCOMPtr.h"
 #include "nsIClassInfoImpl.h"
--- a/dom/base/WindowNamedPropertiesHandler.cpp
+++ b/dom/base/WindowNamedPropertiesHandler.cpp
@@ -86,17 +86,17 @@ WindowNamedPropertiesHandler::getOwnProp
 
   nsDependentJSString str(aId);
 
   // Grab the DOM window.
   XPCWrappedNative* wrapper = XPCWrappedNative::Get(global);
   nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper);
   MOZ_ASSERT(piWin);
   nsGlobalWindow* win = static_cast<nsGlobalWindow*>(piWin.get());
-  if (win->GetLength() > 0) {
+  if (win->Length() > 0) {
     nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str);
     if (childWin && ShouldExposeChildWindow(str, childWin)) {
       // We found a subframe of the right name. Shadowing via |var foo| in
       // global scope is still allowed, since |var| only looks up |own|
       // properties. But unqualified shadowing will fail, per-spec.
       JS::Rooted<JS::Value> v(aCx);
       if (!WrapObject(aCx, aProxy, childWin, &v)) {
         return false;
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -1,44 +1,178 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsContentPermissionHelper.h"
-#include "nsIContentPermissionPrompt.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMElement.h"
 #include "nsIPrincipal.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/PContentPermission.h"
+#include "mozilla/dom/PermissionMessageUtils.h"
+#include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/unused.h"
 #include "nsComponentManagerUtils.h"
+#include "nsArrayUtils.h"
+#include "nsIMutableArray.h"
+#include "nsContentPermissionHelper.h"
 
 using mozilla::unused;          // <snicker>
 using namespace mozilla::dom;
 
+namespace mozilla {
+namespace dom {
+
+class ContentPermissionRequestParent : public PContentPermissionRequestParent
+{
+ public:
+  ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
+                                 Element* element,
+                                 const IPC::Principal& principal);
+  virtual ~ContentPermissionRequestParent();
+
+  bool IsBeingDestroyed();
+
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsCOMPtr<Element> mElement;
+  nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
+  nsTArray<PermissionRequest> mRequests;
+
+ private:
+  virtual bool Recvprompt();
+  virtual void ActorDestroy(ActorDestroyReason why);
+};
+
+ContentPermissionRequestParent::ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
+                                                               Element* aElement,
+                                                               const IPC::Principal& aPrincipal)
+{
+  MOZ_COUNT_CTOR(ContentPermissionRequestParent);
+
+  mPrincipal = aPrincipal;
+  mElement   = aElement;
+  mRequests  = aRequests;
+}
+
+ContentPermissionRequestParent::~ContentPermissionRequestParent()
+{
+  MOZ_COUNT_DTOR(ContentPermissionRequestParent);
+}
+
+bool
+ContentPermissionRequestParent::Recvprompt()
+{
+  mProxy = new nsContentPermissionRequestProxy();
+  NS_ASSERTION(mProxy, "Alloc of request proxy failed");
+  if (NS_FAILED(mProxy->Init(mRequests, this))) {
+    mProxy->Cancel();
+  }
+  return true;
+}
+
+void
+ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
+{
+  if (mProxy) {
+    mProxy->OnParentDestroyed();
+  }
+}
+
+bool
+ContentPermissionRequestParent::IsBeingDestroyed()
+{
+  // When TabParent::Destroy() is called, we are being destroyed. It's unsafe
+  // to send out any message now.
+  TabParent* tabParent = static_cast<TabParent*>(Manager());
+  return tabParent->IsDestroyed();
+}
+
+NS_IMPL_ISUPPORTS1(ContentPermissionType, nsIContentPermissionType)
+
+ContentPermissionType::ContentPermissionType(const nsACString& aType,
+                                             const nsACString& aAccess)
+{
+  mType = aType;
+  mAccess = aAccess;
+}
+
+ContentPermissionType::~ContentPermissionType()
+{
+}
+
+NS_IMETHODIMP
+ContentPermissionType::GetType(nsACString& aType)
+{
+  aType = mType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ContentPermissionType::GetAccess(nsACString& aAccess)
+{
+  aAccess = mAccess;
+  return NS_OK;
+}
+
+uint32_t
+ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
+                                nsIMutableArray* aDesArray)
+{
+  uint32_t len = aSrcArray.Length();
+  for (uint32_t i = 0; i < len; i++) {
+    nsRefPtr<ContentPermissionType> cpt =
+      new ContentPermissionType(aSrcArray[i].type(), aSrcArray[i].access());
+    aDesArray->AppendElement(cpt, false);
+  }
+  return len;
+}
+
+nsresult
+CreatePermissionArray(const nsACString& aType,
+                      const nsACString& aAccess,
+                      nsIArray** aTypesArray)
+{
+  nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  nsRefPtr<ContentPermissionType> permType = new ContentPermissionType(aType,
+                                                                       aAccess);
+  types->AppendElement(permType, false);
+  types.forget(aTypesArray);
+
+  return NS_OK;
+}
+
+PContentPermissionRequestParent*
+CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
+                                     Element* element,
+                                     const IPC::Principal& principal)
+{
+  return new ContentPermissionRequestParent(aRequests, element, principal);
+}
+
+} // namespace dom
+} // namespace mozilla
+
 nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
 {
   MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
 }
 
 nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
 {
   MOZ_COUNT_DTOR(nsContentPermissionRequestProxy);
 }
 
 nsresult
-nsContentPermissionRequestProxy::Init(const nsACString & type,
-                                      const nsACString & access,
+nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
                                       ContentPermissionRequestParent* parent)
 {
   NS_ASSERTION(parent, "null parent");
   mParent = parent;
-  mType   = type;
-  mAccess = access;
+  mPermissionRequests = requests;
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (!prompt) {
     return NS_ERROR_FAILURE;
   }
 
   prompt->Prompt(this);
   return NS_OK;
@@ -48,27 +182,24 @@ void
 nsContentPermissionRequestProxy::OnParentDestroyed()
 {
   mParent = nullptr;
 }
 
 NS_IMPL_ISUPPORTS1(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
 
 NS_IMETHODIMP
-nsContentPermissionRequestProxy::GetType(nsACString & aType)
+nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
 {
-  aType = mType;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
-{
-  aAccess = mAccess;
-  return NS_OK;
+  nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
+    types.forget(aTypes);
+    return NS_OK;
+  }
+  return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
   *aRequestingWindow = nullptr; // ipc doesn't have a window
   return NS_OK;
@@ -129,60 +260,8 @@ nsContentPermissionRequestProxy::Allow()
   if (mParent->IsBeingDestroyed()) {
     return NS_ERROR_FAILURE;
   }
 
   unused << ContentPermissionRequestParent::Send__delete__(mParent, true);
   mParent = nullptr;
   return NS_OK;
 }
-
-namespace mozilla {
-namespace dom {
-
-ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
-                                                               const nsACString& aAccess,
-                                                               Element* aElement,
-                                                               const IPC::Principal& aPrincipal)
-{
-  MOZ_COUNT_CTOR(ContentPermissionRequestParent);
-
-  mPrincipal = aPrincipal;
-  mElement   = aElement;
-  mType      = aType;
-  mAccess    = aAccess;
-}
-
-ContentPermissionRequestParent::~ContentPermissionRequestParent()
-{
-  MOZ_COUNT_DTOR(ContentPermissionRequestParent);
-}
-
-bool
-ContentPermissionRequestParent::Recvprompt()
-{
-  mProxy = new nsContentPermissionRequestProxy();
-  NS_ASSERTION(mProxy, "Alloc of request proxy failed");
-  if (NS_FAILED(mProxy->Init(mType, mAccess, this))) {
-    mProxy->Cancel();
-  }
-  return true;
-}
-
-void
-ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
-{
-  if (mProxy) {
-    mProxy->OnParentDestroyed();
-  }
-}
-
-bool
-ContentPermissionRequestParent::IsBeingDestroyed()
-{
-  // When TabParent::Destroy() is called, we are being destroyed. It's unsafe
-  // to send out any message now.
-  TabParent* tabParent = static_cast<TabParent*>(Manager());
-  return tabParent->IsDestroyed();
-}
-
-} // namespace dom
-} // namespace mozilla
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -1,65 +1,80 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsContentPermissionHelper_h
 #define nsContentPermissionHelper_h
 
 #include "nsIContentPermissionPrompt.h"
-#include "nsString.h"
-
-#include "mozilla/dom/PermissionMessageUtils.h"
-#include "mozilla/dom/PContentPermissionRequestParent.h"
+#include "nsTArray.h"
+#include "nsIMutableArray.h"
 
 class nsContentPermissionRequestProxy;
 
+// Forward declare IPC::Principal here which is defined in
+// PermissionMessageUtils.h. Include this file will transitively includes
+// "windows.h" and it defines
+//   #define CreateEvent CreateEventW
+//   #define LoadImage LoadImageW
+// That will mess up windows build.
+namespace IPC {
+class Principal;
+}
+
 namespace mozilla {
 namespace dom {
 
 class Element;
+class PermissionRequest;
+class ContentPermissionRequestParent;
+class PContentPermissionRequestParent;
 
-class ContentPermissionRequestParent : public PContentPermissionRequestParent
+class ContentPermissionType : public nsIContentPermissionType
 {
- public:
-  ContentPermissionRequestParent(const nsACString& type,
-                                 const nsACString& access,
-                                 Element* element,
-                                 const IPC::Principal& principal);
-  virtual ~ContentPermissionRequestParent();
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICONTENTPERMISSIONTYPE
 
-  bool IsBeingDestroyed();
+  ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
+  virtual ~ContentPermissionType();
 
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-  nsCOMPtr<Element> mElement;
-  nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
+protected:
   nsCString mType;
   nsCString mAccess;
+};
 
- private:
-  virtual bool Recvprompt();
-  virtual void ActorDestroy(ActorDestroyReason why);
-};
+uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
+                                         nsIMutableArray* aDesArray);
+
+nsresult CreatePermissionArray(const nsACString& aType,
+                               const nsACString& aAccess,
+                               nsIArray** aTypesArray);
+
+PContentPermissionRequestParent*
+CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
+                                     Element* element,
+                                     const IPC::Principal& principal);
 
 } // namespace dom
 } // namespace mozilla
 
 class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
 {
  public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICONTENTPERMISSIONREQUEST
+
   nsContentPermissionRequestProxy();
   virtual ~nsContentPermissionRequestProxy();
 
-  nsresult Init(const nsACString& type, const nsACString& access, mozilla::dom::ContentPermissionRequestParent* parent);
+  nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
+                mozilla::dom::ContentPermissionRequestParent* parent);
   void OnParentDestroyed();
 
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSICONTENTPERMISSIONREQUEST
-
  private:
   // Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
   mozilla::dom::ContentPermissionRequestParent* mParent;
-  nsCString mType;
-  nsCString mAccess;
+  nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
 };
+
 #endif // nsContentPermissionHelper_h
-
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -58,17 +58,18 @@ DOMCI_CASTABLE_INTERFACE(nsDOMEvent, nsI
 DOMCI_CASTABLE_INTERFACE(nsIDocument, nsIDocument, 4, _extra)                 \
 DOMCI_CASTABLE_INTERFACE(nsDocument, nsIDocument, 5, _extra)                  \
 DOMCI_CASTABLE_INTERFACE(nsGenericHTMLElement, nsIContent, 6, _extra)         \
 DOMCI_CASTABLE_INTERFACE(nsHTMLDocument, nsIDocument, 7, _extra)              \
 DOMCI_CASTABLE_INTERFACE(nsStyledElement, nsStyledElement, 8, _extra)         \
 DOMCI_CASTABLE_INTERFACE(nsSVGElement, nsIContent, 9, _extra)                 \
 /* NOTE: When removing the casts below, remove the nsDOMEventBase class */    \
 DOMCI_CASTABLE_INTERFACE(nsDOMMouseEvent, nsDOMEventBase, 10, _extra)         \
-DOMCI_CASTABLE_INTERFACE(nsDOMUIEvent, nsDOMEventBase, 11, _extra)
+DOMCI_CASTABLE_INTERFACE(nsDOMUIEvent, nsDOMEventBase, 11, _extra)            \
+DOMCI_CASTABLE_INTERFACE(nsGlobalWindow, nsIDOMEventTarget, 12, _extra)
 
 // Make sure all classes mentioned in DOMCI_CASTABLE_INTERFACES
 // have been declared.
 #define DOMCI_CASTABLE_NODECL_INTERFACE(_interface, _u1, _u2, _u3) /* Nothing */
 #define DOMCI_CASTABLE_INTERFACE(_interface, _u1, _u2, _u3) class _interface;
 DOMCI_CASTABLE_INTERFACES(unused)
 #undef DOMCI_CASTABLE_INTERFACE
 #undef DOMCI_CASTABLE_NODECL_INTERFACE
--- a/dom/base/nsDOMJSUtils.h
+++ b/dom/base/nsDOMJSUtils.h
@@ -1,26 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-
 #ifndef nsDOMJSUtils_h__
 #define nsDOMJSUtils_h__
 
 #include "nsIScriptContext.h"
+#include "jsapi.h"
 
 class nsIJSArgArray;
 
 // seems like overkill for just this 1 function - but let's see what else
 // falls out first.
 inline nsIScriptContext *
 GetScriptContextFromJSContext(JSContext *cx)
 {
-  if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
+  if (!(JS::ContextOptionsRef(cx).privateIsNSISupports())) {
     return nullptr;
   }
 
   nsCOMPtr<nsIScriptContext> scx =
     do_QueryInterface(static_cast<nsISupports *>
                                  (::JS_GetContextPrivate(cx)));
 
   // This will return a pointer to something that's about to be
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsGlobalWindow.h"
 
 #include <algorithm>
@@ -45,17 +45,16 @@
 #undef CreateEvent
 #endif
 #endif // XP_WIN
 
 // Helper Classes
 #include "nsJSUtils.h"
 #include "jsapi.h"              // for JSAutoRequest
 #include "js/OldDebugAPI.h"     // for JS_ClearWatchPointsForObject
-#include "jsfriendapi.h"        // for JS_GetGlobalForFrame
 #include "jswrapper.h"
 #include "nsReadableUtils.h"
 #include "nsDOMClassInfo.h"
 #include "nsJSEnvironment.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Likely.h"
 
 // Other Classes
@@ -214,16 +213,17 @@
 #include "prrng.h"
 #include "nsSandboxFlags.h"
 #include "TimeChangeObserver.h"
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/TabChild.h"
+#include "nsIDOMMediaQueryList.h"
 
 #ifdef MOZ_WEBSPEECH
 #include "mozilla/dom/SpeechSynthesis.h"
 #endif
 
 #ifdef MOZ_JSDEBUGGER
 #include "jsdIDebuggerService.h"
 #endif
@@ -311,16 +311,29 @@ nsGlobalWindow::DOMMinTimeoutValue() con
     if (!outer) {                                                             \
       NS_WARNING("No outer window available!");                               \
       return err_rval;                                                        \
     }                                                                         \
     return outer->method args;                                                \
   }                                                                           \
   PR_END_MACRO
 
+#define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval)        \
+  PR_BEGIN_MACRO                                                              \
+  if (IsInnerWindow()) {                                                      \
+    nsGlobalWindow *outer = GetOuterWindowInternal();                         \
+    if (!outer) {                                                             \
+      NS_WARNING("No outer window available!");                               \
+      errorresult.Throw(NS_ERROR_NOT_INITIALIZED);                            \
+      return err_rval;                                                        \
+    }                                                                         \
+    return outer->method args;                                                \
+  }                                                                           \
+  PR_END_MACRO
+
 #define FORWARD_TO_OUTER_VOID(method, args)                                   \
   PR_BEGIN_MACRO                                                              \
   if (IsInnerWindow()) {                                                      \
     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     if (!outer) {                                                             \
       NS_WARNING("No outer window available!");                               \
       return;                                                                 \
     }                                                                         \
@@ -370,16 +383,28 @@ nsGlobalWindow::DOMMinTimeoutValue() con
     if (!mInnerWindow) {                                                      \
       NS_WARNING("No inner window available!");                               \
       return err_rval;                                                        \
     }                                                                         \
     return GetCurrentInnerWindowInternal()->method args;                      \
   }                                                                           \
   PR_END_MACRO
 
+#define FORWARD_TO_INNER_OR_THROW(method, args, errorresult, err_rval)        \
+  PR_BEGIN_MACRO                                                              \
+  if (IsOuterWindow()) {                                                      \
+    if (!mInnerWindow) {                                                      \
+      NS_WARNING("No inner window available!");                               \
+      errorresult.Throw(NS_ERROR_NOT_INITIALIZED);                            \
+      return err_rval;                                                        \
+    }                                                                         \
+    return GetCurrentInnerWindowInternal()->method args;                      \
+  }                                                                           \
+  PR_END_MACRO
+
 #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval)         \
   PR_BEGIN_MACRO                                                              \
   if (IsOuterWindow()) {                                                      \
     if (!mInnerWindow) {                                                      \
       NS_WARNING("No inner window available!");                               \
       return err_rval;                                                        \
     }                                                                         \
     return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
@@ -921,17 +946,17 @@ nsOuterWindowProxy::GetSubframeWindow(JS
   bool unused;
   return win->IndexedGetter(index, unused);
 }
 
 bool
 nsOuterWindowProxy::AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
                                                JS::AutoIdVector &props)
 {
-  uint32_t length = GetWindow(proxy)->GetLength();
+  uint32_t length = GetWindow(proxy)->Length();
   MOZ_ASSERT(int32_t(length) >= 0);
   if (!props.reserve(props.length() + length)) {
     return false;
   }
   for (int32_t i = 0; i < int32_t(length); ++i) {
     props.append(INT_TO_JSID(i));
   }
 
@@ -3309,101 +3334,143 @@ nsPIDOMWindow::UnmuteAudioContexts()
       mAudioContexts[i]->Unmute();
     }
   }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetDocument(nsIDOMDocument** aDocument)
 {
-  nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetDoc());
+  nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetDocument());
   document.forget(aDocument);
   return NS_OK;
 }
 
+nsIDOMWindow*
+nsGlobalWindow::GetWindow(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetWindow, (aError), aError, nullptr);
+
+  return this;
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetWindow(nsIDOMWindow** aWindow)
 {
-  FORWARD_TO_OUTER(GetWindow, (aWindow), NS_ERROR_NOT_INITIALIZED);
-
-  *aWindow = static_cast<nsIDOMWindow*>(this);
-  NS_ADDREF(*aWindow);
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMWindow> window = GetWindow(rv);
+  window.forget(aWindow);
+
+  return rv.ErrorCode();
+}
+
+nsIDOMWindow*
+nsGlobalWindow::GetSelf(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetSelf, (aError), aError, nullptr);
+
+  return this;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetSelf(nsIDOMWindow** aWindow)
 {
-  FORWARD_TO_OUTER(GetSelf, (aWindow), NS_ERROR_NOT_INITIALIZED);
-
-  *aWindow = static_cast<nsIDOMWindow*>(this);
-  NS_ADDREF(*aWindow);
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMWindow> window = GetSelf(rv);
+  window.forget(aWindow);
+
+  return rv.ErrorCode();
+}
+
+Navigator*
+nsGlobalWindow::GetNavigator(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetNavigator, (aError), aError, nullptr);
+
+  if (!mNavigator) {
+    mNavigator = new Navigator(this);
+  }
+
+  return mNavigator;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator)
 {
-  FORWARD_TO_INNER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
-
-  *aNavigator = nullptr;
-
-  if (!mNavigator) {
-    mNavigator = new Navigator(this);
-  }
-
-  NS_ADDREF(*aNavigator = mNavigator);
-
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMNavigator> navigator = GetNavigator(rv);
+  navigator.forget(aNavigator);
+
+  return rv.ErrorCode();
+}
+
+nsScreen*
+nsGlobalWindow::GetScreen(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetScreen, (aError), aError, nullptr);
+
+  if (!mScreen) {
+    mScreen = nsScreen::Create(this);
+    if (!mScreen) {
+      aError.Throw(NS_ERROR_UNEXPECTED);
+      return nullptr;
+    }
+  }
+
+  return mScreen;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen)
 {
-  FORWARD_TO_INNER(GetScreen, (aScreen), NS_ERROR_NOT_INITIALIZED);
-
-  *aScreen = nullptr;
-
-  if (!mScreen) {
-    mScreen = nsScreen::Create(this);
-    if (!mScreen) {
-      return NS_ERROR_UNEXPECTED;
-    }
-  }
-
-  NS_IF_ADDREF(*aScreen = mScreen);
-
-  return NS_OK;
+  ErrorResult rv;
+  nsRefPtr<nsScreen> screen = GetScreen(rv);
+  screen.forget(aScreen);
+
+  return rv.ErrorCode();
+}
+
+nsHistory*
+nsGlobalWindow::GetHistory(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetHistory, (aError), aError, nullptr);
+
+  if (!mHistory) {
+    mHistory = new nsHistory(this);
+  }
+
+  return mHistory;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetHistory(nsISupports** aHistory)
 {
-  FORWARD_TO_INNER(GetHistory, (aHistory), NS_ERROR_NOT_INITIALIZED);
-
-  *aHistory = nullptr;
-
-  if (!mHistory) {
-    mHistory = new nsHistory(this);
-    if (!mHistory) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_IF_ADDREF(*aHistory = mHistory);
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> history = GetHistory(rv);
+  history.forget(aHistory);
+
+  return rv.ErrorCode();
+}
+
+nsPerformance*
+nsGlobalWindow::GetPerformance(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetPerformance, (aError), aError, nullptr);
+
+  return nsPIDOMWindow::GetPerformance();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPerformance(nsISupports** aPerformance)
 {
-  FORWARD_TO_INNER(GetPerformance, (aPerformance), NS_ERROR_NOT_INITIALIZED);
-
-  NS_IF_ADDREF(*aPerformance = nsPIDOMWindow::GetPerformance());
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> performance = GetPerformance(rv);
+  performance.forget(aPerformance);
+
+  return rv.ErrorCode();
 }
 
 nsPerformance*
 nsPIDOMWindow::GetPerformance()
 {
   MOZ_ASSERT(IsInnerWindow());
   CreatePerformanceObjectIfNeeded();
   return mPerformance;
@@ -3426,66 +3493,76 @@ nsPIDOMWindow::CreatePerformanceObjectIf
   if (timing) {
     mPerformance = new nsPerformance(this, timing, timedChannel);
   }
 }
 
 // nsISpeechSynthesisGetter
 
 #ifdef MOZ_WEBSPEECH
-NS_IMETHODIMP
-nsGlobalWindow::GetSpeechSynthesis(nsISupports** aSpeechSynthesis)
-{
-  FORWARD_TO_INNER(GetSpeechSynthesis, (aSpeechSynthesis), NS_ERROR_NOT_INITIALIZED);
-
-  NS_IF_ADDREF(*aSpeechSynthesis = GetSpeechSynthesisInternal());
-  return NS_OK;
-}
-
 SpeechSynthesis*
-nsGlobalWindow::GetSpeechSynthesisInternal()
-{
-  MOZ_ASSERT(IsInnerWindow());
-
-  if (!SpeechSynthesis::PrefEnabled()) {
-    return nullptr;
-  }
+nsGlobalWindow::GetSpeechSynthesis(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetSpeechSynthesis, (aError), aError, nullptr);
 
   if (!mSpeechSynthesis) {
     mSpeechSynthesis = new SpeechSynthesis(this);
   }
 
   return mSpeechSynthesis;
 }
+
+NS_IMETHODIMP
+nsGlobalWindow::GetSpeechSynthesis(nsISupports** aSpeechSynthesis)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> speechSynthesis;
+  if (SpeechSynthesis::PrefEnabled()) {
+    speechSynthesis = GetSpeechSynthesis(rv);
+  }
+  speechSynthesis.forget(aSpeechSynthesis);
+
+  return rv.ErrorCode();
+}
 #endif
 
+already_AddRefed<nsIDOMWindow>
+nsGlobalWindow::GetParent(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetParent, (aError), aError, nullptr);
+
+  if (!mDocShell) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDOMWindow> parent;
+  if (mDocShell->GetIsBrowserOrApp()) {
+    parent = this;
+  } else {
+    aError = GetRealParent(getter_AddRefs(parent));
+  }
+
+  return parent.forget();
+}
+
 /**
  * GetScriptableParent is called when script reads window.parent.
  *
  * In contrast to GetRealParent, GetScriptableParent respects <iframe
  * mozbrowser> boundaries, so if |this| is contained by an <iframe
  * mozbrowser>, we will return |this| as its own parent.
  */
 NS_IMETHODIMP
 nsGlobalWindow::GetScriptableParent(nsIDOMWindow** aParent)
 {
-  FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_NOT_INITIALIZED);
-
-  *aParent = NULL;
-  if (!mDocShell) {
-    return NS_OK;
-  }
-
-  if (mDocShell->GetIsBrowserOrApp()) {
-    nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this);
-    parent.swap(*aParent);
-    return NS_OK;
-  }
-
-  return GetRealParent(aParent);
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMWindow> parent = GetParent(rv);
+  parent.forget(aParent);
+
+  return rv.ErrorCode();
 }
 
 /**
  * nsIDOMWindow::GetParent (when called from C++) is just a wrapper around
  * GetRealParent.
  */
 NS_IMETHODIMP
 nsGlobalWindow::GetRealParent(nsIDOMWindow** aParent)
@@ -3568,34 +3645,77 @@ nsGlobalWindow::GetTopImpl(nsIDOMWindow*
 
   if (parent) {
     parent.swap(*aTop);
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
-{
-  FORWARD_TO_OUTER(GetContent, (aContent), NS_ERROR_NOT_INITIALIZED);
-  *aContent = nullptr;
-
+JSObject*
+nsGlobalWindow::GetContent(JSContext* aCx, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetContent, (aCx, aError), aError, nullptr);
+
+  nsCOMPtr<nsIDOMWindow> content = GetContentInternal(aError);
+  if (aError.Failed()) {
+    return nullptr;
+  }
+
+  if (content) {
+    JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
+    if (!global) {
+      aError.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+
+    JS::Rooted<JS::Value> val(aCx);
+    aError = nsContentUtils::WrapNative(aCx, global, content, &val);
+    if (aError.Failed()) {
+      return nullptr;
+    }
+
+    return &val.toObject();
+  }
+
+  if (!nsContentUtils::IsCallerChrome() || !IsChromeWindow()) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  // Something tries to get .content on a ChromeWindow, try to fetch the CPOW.
+  nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
+  if (!treeOwner) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  JS::Rooted<JS::Value> val(aCx);
+  aError = treeOwner->GetContentWindow(aCx, val.address());
+  if (aError.Failed()) {
+    return nullptr;
+  }
+
+  return &val.toObject();
+}
+
+already_AddRefed<nsIDOMWindow>
+nsGlobalWindow::GetContentInternal(ErrorResult& aError)
+{
   // First check for a named frame named "content"
   nsCOMPtr<nsIDOMWindow> domWindow =
     GetChildWindow(NS_LITERAL_STRING("content"));
   if (domWindow) {
-    domWindow.forget(aContent);
-    return NS_OK;
+    return domWindow.forget();
   }
 
   // If we're contained in <iframe mozbrowser> or <iframe mozapp>, then
   // GetContent is the same as window.top.
   if (mDocShell && mDocShell->GetIsInBrowserOrApp()) {
-    return GetScriptableTop(aContent);
+    return GetTop(aError);
   }
 
   nsCOMPtr<nsIDocShellTreeItem> primaryContent;
   if (!nsContentUtils::IsCallerChrome()) {
     // If we're called by non-chrome code, make sure we don't return
     // the primary content window if the calling tab is hidden. In
     // such a case we return the same-type root in the hidden tab,
     // which is "good enough", for now.
@@ -3608,51 +3728,47 @@ nsGlobalWindow::GetContent(nsIDOMWindow*
       if (!visible) {
         mDocShell->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent));
       }
     }
   }
 
   if (!primaryContent) {
     nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
-    NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
+    if (!treeOwner) {
+      aError.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
 
     treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
   }
 
   domWindow = do_GetInterface(primaryContent);
-  domWindow.forget(aContent);
-
-  return NS_OK;
+  return domWindow.forget();
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
+{
+  ErrorResult rv;
+  *aContent = GetContentInternal(rv).get();
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScriptableContent(JSContext* aCx, JS::Value* aVal)
 {
-  nsCOMPtr<nsIDOMWindow> content;
-  nsresult rv = GetContent(getter_AddRefs(content));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (content || !nsContentUtils::IsCallerChrome() || !IsChromeWindow()) {
-    JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
-    if (content && global) {
-      nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-      JS::Rooted<JS::Value> rval(aCx);
-      nsresult rv = nsContentUtils::WrapNative(aCx, global, content, &rval,
-                                               getter_AddRefs(wrapper));
-      *aVal = rval;
-      return rv;
-    }
-    return NS_ERROR_FAILURE;
-  }
-
-  // Something tries to get .content on a ChromeWindow, try to fetch the CPOW.
-  nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
-  NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
-  return treeOwner->GetContentWindow(aCx, aVal);
+  ErrorResult rv;
+  JS::Rooted<JSObject*> content(aCx, GetContent(aCx, rv));
+  if (!rv.Failed()) {
+    *aVal = JS::ObjectValue(*content);
+  }
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt)
 {
   FORWARD_TO_OUTER(GetPrompter, (aPrompt), NS_ERROR_NOT_INITIALIZED);
 
   if (!mDocShell)
@@ -3660,139 +3776,161 @@ nsGlobalWindow::GetPrompter(nsIPrompt** 
 
   nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
   NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE);
 
   NS_ADDREF(*aPrompt = prompter);
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetMenubar(nsISupports** aMenubar)
-{
-  FORWARD_TO_INNER(GetMenubar, (aMenubar), NS_ERROR_NOT_INITIALIZED);
-
-  *aMenubar = nullptr;
+BarProp*
+nsGlobalWindow::GetMenubar(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetMenubar, (aError), aError, nullptr);
 
   if (!mMenubar) {
     mMenubar = new MenubarProp(this);
-    if (!mMenubar) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_ADDREF(*aMenubar = mMenubar);
-
-  return NS_OK;
+  }
+
+  return mMenubar;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetMenubar(nsISupports** aMenubar)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> menubar = GetMenubar(rv);
+  menubar.forget(aMenubar);
+
+  return rv.ErrorCode();
+}
+
+BarProp*
+nsGlobalWindow::GetToolbar(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetToolbar, (aError), aError, nullptr);
+
+  if (!mToolbar) {
+    mToolbar = new ToolbarProp(this);
+  }
+
+  return mToolbar;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetToolbar(nsISupports** aToolbar)
 {
-  FORWARD_TO_INNER(GetToolbar, (aToolbar), NS_ERROR_NOT_INITIALIZED);
-
-  *aToolbar = nullptr;
-
-  if (!mToolbar) {
-    mToolbar = new ToolbarProp(this);
-    if (!mToolbar) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_ADDREF(*aToolbar = mToolbar);
-
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> toolbar = GetToolbar(rv);
+  toolbar.forget(aToolbar);
+
+  return rv.ErrorCode();
+}
+
+BarProp*
+nsGlobalWindow::GetLocationbar(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetLocationbar, (aError), aError, nullptr);
+
+  if (!mLocationbar) {
+    mLocationbar = new LocationbarProp(this);
+  }
+  return mLocationbar;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetLocationbar(nsISupports** aLocationbar)
 {
-  FORWARD_TO_INNER(GetLocationbar, (aLocationbar), NS_ERROR_NOT_INITIALIZED);
-
-  *aLocationbar = nullptr;
-
-  if (!mLocationbar) {
-    mLocationbar = new LocationbarProp(this);
-    if (!mLocationbar) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_ADDREF(*aLocationbar = mLocationbar);
-
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> locationbar = GetLocationbar(rv);
+  locationbar.forget(aLocationbar);
+
+  return rv.ErrorCode();
+}
+
+BarProp*
+nsGlobalWindow::GetPersonalbar(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetPersonalbar, (aError), aError, nullptr);
+
+  if (!mPersonalbar) {
+    mPersonalbar = new PersonalbarProp(this);
+  }
+  return mPersonalbar;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPersonalbar(nsISupports** aPersonalbar)
 {
-  FORWARD_TO_INNER(GetPersonalbar, (aPersonalbar), NS_ERROR_NOT_INITIALIZED);
-
-  *aPersonalbar = nullptr;
-
-  if (!mPersonalbar) {
-    mPersonalbar = new PersonalbarProp(this);
-    if (!mPersonalbar) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_ADDREF(*aPersonalbar = mPersonalbar);
-
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> personalbar = GetPersonalbar(rv);
+  personalbar.forget(aPersonalbar);
+
+  return rv.ErrorCode();
+}
+
+BarProp*
+nsGlobalWindow::GetStatusbar(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetStatusbar, (aError), aError, nullptr);
+
+  if (!mStatusbar) {
+    mStatusbar = new StatusbarProp(this);
+  }
+  return mStatusbar;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetStatusbar(nsISupports** aStatusbar)
 {
-  FORWARD_TO_INNER(GetStatusbar, (aStatusbar), NS_ERROR_NOT_INITIALIZED);
-
-  *aStatusbar = nullptr;
-
-  if (!mStatusbar) {
-    mStatusbar = new StatusbarProp(this);
-    if (!mStatusbar) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_ADDREF(*aStatusbar = mStatusbar);
-
-  return NS_OK;
-}
-
-mozilla::dom::BarProp*
-nsGlobalWindow::GetScrollbars()
-{
-  FORWARD_TO_INNER(GetScrollbars, (), nullptr);
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> statusbar = GetStatusbar(rv);
+  statusbar.forget(aStatusbar);
+
+  return rv.ErrorCode();
+}
+
+BarProp*
+nsGlobalWindow::GetScrollbars(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetScrollbars, (aError), aError, nullptr);
+
   if (!mScrollbars) {
     mScrollbars = new ScrollbarsProp(this);
   }
 
   return mScrollbars;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScrollbars(nsISupports** aScrollbars)
 {
-  NS_IF_ADDREF(*aScrollbars = GetScrollbars());
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> scrollbars = GetScrollbars(rv);
+  scrollbars.forget(aScrollbars);
+
+  return rv.ErrorCode();
+}
+
+bool
+nsGlobalWindow::GetClosed(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetClosed, (aError), aError, false);
+
+  // If someone called close(), or if we don't have a docshell, we're closed.
+  return mIsClosed || !mDocShell;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetClosed(bool* aClosed)
 {
-  FORWARD_TO_OUTER(GetClosed, (aClosed), NS_ERROR_NOT_INITIALIZED);
-
-  // If someone called close(), or if we don't have a docshell, we're
-  // closed.
-  *aClosed = mIsClosed || !mDocShell;
-
-  return NS_OK;
+  ErrorResult rv;
+  *aClosed = GetClosed(rv);
+
+  return rv.ErrorCode();
 }
 
 nsDOMWindowList*
 nsGlobalWindow::GetWindowList()
 {
   MOZ_ASSERT(IsOuterWindow());
 
   if (!mFrames && mDocShell) {
@@ -3837,254 +3975,340 @@ nsGlobalWindow::GetSupportedNames(nsTArr
     for (uint32_t i = 0; i < length; ++i, ++name) {
       nsCOMPtr<nsIDocShellTreeItem> item =
         windows->GetDocShellTreeItemAt(i);
       item->GetName(*name);
     }
   }
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList **aApplicationCache)
-{
-  FORWARD_TO_INNER(GetApplicationCache, (aApplicationCache), NS_ERROR_UNEXPECTED);
-
-  NS_ENSURE_ARG_POINTER(aApplicationCache);
+nsIDOMOfflineResourceList*
+nsGlobalWindow::GetApplicationCache(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetApplicationCache, (aError), aError, nullptr);
 
   if (!mApplicationCache) {
     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
     if (!webNav) {
-      return NS_ERROR_FAILURE;
+      aError.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
 
     nsCOMPtr<nsIURI> uri;
-    nsresult rv = webNav->GetCurrentURI(getter_AddRefs(uri));
-    NS_ENSURE_SUCCESS(rv, rv);
+    aError = webNav->GetCurrentURI(getter_AddRefs(uri));
+    if (aError.Failed()) {
+      return nullptr;
+    }
 
     nsCOMPtr<nsIURI> manifestURI;
     nsContentUtils::GetOfflineAppManifest(mDoc, getter_AddRefs(manifestURI));
 
     nsRefPtr<nsDOMOfflineResourceList> applicationCache =
       new nsDOMOfflineResourceList(manifestURI, uri, this);
-    NS_ENSURE_TRUE(applicationCache, NS_ERROR_OUT_OF_MEMORY);
 
     applicationCache->Init();
 
     mApplicationCache = applicationCache;
   }
 
-  NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
-{
-  FORWARD_TO_INNER(GetCrypto, (aCrypto), NS_ERROR_NOT_INITIALIZED);
+  return mApplicationCache;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList **aApplicationCache)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMOfflineResourceList> applicationCache =
+    GetApplicationCache(rv);
+  applicationCache.forget(aApplicationCache);
+
+  return rv.ErrorCode();
+}
+
+nsIDOMCrypto*
+nsGlobalWindow::GetCrypto(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetCrypto, (aError), aError, nullptr);
 
   if (!mCrypto) {
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
     if (XRE_GetProcessType() != GeckoProcessType_Content) {
       nsresult rv;
       mCrypto = do_CreateInstance(NS_CRYPTO_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_FAILED(rv)) {
+        aError.Throw(rv);
+        return nullptr;
+      }
     } else
 #endif
     {
       mCrypto = new Crypto();
     }
 
     mCrypto->Init(this);
   }
-  NS_IF_ADDREF(*aCrypto = mCrypto);
-  return NS_OK;
+  return mCrypto;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMCrypto> crypto = GetCrypto(rv);
+  crypto.forget(aCrypto);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11)
 {
   *aPkcs11 = nullptr;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetControllers(nsIControllers** aResult)
-{
-  FORWARD_TO_OUTER(GetControllers, (aResult), NS_ERROR_NOT_INITIALIZED);
+nsIControllers*
+nsGlobalWindow::GetControllers(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetControllers, (aError), aError, nullptr);
 
   if (!mControllers) {
     nsresult rv;
     mControllers = do_CreateInstance(kXULControllersCID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      aError.Throw(rv);
+      return nullptr;
+    }
 
     // Add in the default controller
     nsCOMPtr<nsIController> controller = do_CreateInstance(
                                NS_WINDOWCONTROLLER_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      aError.Throw(rv);
+      return nullptr;
+    }
     
     mControllers->InsertControllerAt(0, controller);
     nsCOMPtr<nsIControllerContext> controllerContext = do_QueryInterface(controller);
-    if (!controllerContext) return NS_ERROR_FAILURE;
+    if (!controllerContext) {
+      aError.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
 
     controllerContext->SetCommandContext(static_cast<nsIDOMWindow*>(this));
   }
 
-  *aResult = mControllers;
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
-{
-  FORWARD_TO_OUTER(GetOpener, (aOpener), NS_ERROR_NOT_INITIALIZED);
-
-  *aOpener = nullptr;
+  return mControllers;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetControllers(nsIControllers** aResult)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
+  controllers.forget(aResult);
+
+  return rv.ErrorCode();
+}
+
+nsIDOMWindow*
+nsGlobalWindow::GetOpener(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetOpener, (aError), aError, nullptr);
 
   nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
   if (!opener) {
-    return NS_OK;
+    return nullptr;
   }
 
   // First, check if we were called from a privileged chrome script
   if (nsContentUtils::IsCallerChrome()) {
-    NS_ADDREF(*aOpener = opener);
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsPIDOMWindow> openerPwin(do_QueryInterface(opener));
-  if (!openerPwin) {
-    return NS_OK;
+    return opener;
   }
 
   // First, ensure that we're not handing back a chrome window.
-  nsGlobalWindow *win = static_cast<nsGlobalWindow *>(openerPwin.get());
+  nsGlobalWindow *win = static_cast<nsGlobalWindow *>(opener.get());
   if (win->IsChromeWindow()) {
-    return NS_OK;
+    return nullptr;
   }
 
   // We don't want to reveal the opener if the opener is a mail window,
   // because opener can be used to spoof the contents of a message (bug 105050).
   // So, we look in the opener's root docshell to see if it's a mail window.
-  nsCOMPtr<nsIDocShell> openerDocShell = openerPwin->GetDocShell();
+  nsCOMPtr<nsIDocShell> openerDocShell = opener->GetDocShell();
 
   if (openerDocShell) {
     nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
     openerDocShell->GetRootTreeItem(getter_AddRefs(openerRootItem));
     nsCOMPtr<nsIDocShell> openerRootDocShell(do_QueryInterface(openerRootItem));
     if (openerRootDocShell) {
       uint32_t appType;
       nsresult rv = openerRootDocShell->GetAppType(&appType);
       if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) {
-        *aOpener = opener;
+        return opener;
       }
     }
   }
 
-  NS_IF_ADDREF(*aOpener);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
+  return nullptr;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMWindow> opener = GetOpener(rv);
+  opener.forget(aOpener);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
 {
   // Check if we were called from a privileged chrome script.  If not, and if
   // aOpener is not null, just define aOpener on our inner window's JS object,
   // wapped into the current compartment so that for Xrays we define on the Xray
   // expando object, but don't set it on the outer window, so that it'll get
   // reset on navigation.  This is just like replaceable properties, but we're
   // not quite readonly.
   if (aOpener && !nsContentUtils::IsCallerChrome()) {
     // JS_WrapObject will outerize, so we don't care if aOpener is an inner.
     nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOpener);
-    NS_ENSURE_STATE(glob);
+    if (!glob) {
+      aError.Throw(NS_ERROR_UNEXPECTED);
+      return;
+    }
 
     AutoJSContext cx;
     JSAutoRequest ar(cx);
     // Note we explicitly do NOT enter any particular compartment here; we want
     // the caller compartment in cases when we have a caller, so that we define
     // expandos on Xrays as needed.
 
     JS::Rooted<JSObject*> otherObj(cx, glob->GetGlobalJSObject());
-    NS_ENSURE_STATE(otherObj);
+    if (!otherObj) {
+      aError.Throw(NS_ERROR_UNEXPECTED);
+      return;
+    }
 
     JS::Rooted<JSObject*> thisObj(cx, mJSObject);
-    NS_ENSURE_STATE(mJSObject);
+    if (!mJSObject) {
+      aError.Throw(NS_ERROR_UNEXPECTED);
+      return;
+    }
 
     if (!JS_WrapObject(cx, &otherObj) ||
         !JS_WrapObject(cx, &thisObj) ||
         !JS_DefineProperty(cx, thisObj, "opener", JS::ObjectValue(*otherObj),
                            JS_PropertyStub, JS_StrictPropertyStub,
                            JSPROP_ENUMERATE)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
+      aError.Throw(NS_ERROR_FAILURE);
+    }
+
+    return;
   }
 
   SetOpenerWindow(aOpener, false);
-
-  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
+{
+  ErrorResult rv;
+  SetOpener(aOpener, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::GetStatus(nsAString& aStatus, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetStatus, (aStatus, aError), aError, );
+
+  aStatus = mStatus;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetStatus(nsAString& aStatus)
 {
-  FORWARD_TO_OUTER(GetStatus, (aStatus), NS_ERROR_NOT_INITIALIZED);
-
-  aStatus = mStatus;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SetStatus(const nsAString& aStatus)
-{
-  FORWARD_TO_OUTER(SetStatus, (aStatus), NS_ERROR_NOT_INITIALIZED);
+  ErrorResult rv;
+  GetStatus(aStatus, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetStatus(const nsAString& aStatus, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetStatus, (aStatus, aError), aError, );
 
   mStatus = aStatus;
 
   /*
    * If caller is not chrome and dom.disable_window_status_change is true,
    * prevent propagating window.status to the UI by exiting early
    */
 
   if (!CanSetProperty("dom.disable_window_status_change")) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetWebBrowserChrome();
   if (browserChrome) {
     browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
                              PromiseFlatString(aStatus).get());
   }
-
-  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetStatus(const nsAString& aStatus)
+{
+  ErrorResult rv;
+  SetStatus(aStatus, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::GetName(nsAString& aName, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetName, (aName, aError), aError, );
+
+  if (mDocShell) {
+    mDocShell->GetName(aName);
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetName(nsAString& aName)
 {
-  FORWARD_TO_OUTER(GetName, (aName), NS_ERROR_NOT_INITIALIZED);
-
-  if (mDocShell)
-    mDocShell->GetName(aName);
-
-  return NS_OK;
+  ErrorResult rv;
+  GetName(aName, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetName(const nsAString& aName, mozilla::ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetName, (aName, aError), aError, );
+
+  if (mDocShell) {
+    aError = mDocShell->SetName(aName);
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetName(const nsAString& aName)
 {
-  FORWARD_TO_OUTER(SetName, (aName), NS_ERROR_NOT_INITIALIZED);
-
-  nsresult result = NS_OK;
-  if (mDocShell)
-    result = mDocShell->SetName(aName);
-  return result;
+  ErrorResult rv;
+  SetName(aName, rv);
+
+  return rv.ErrorCode();
 }
 
 // Helper functions used by many methods below.
 int32_t
 nsGlobalWindow::DevToCSSIntPixels(int32_t px)
 {
   if (!mDocShell)
     return px; // assume 1:1
@@ -4177,241 +4401,315 @@ nsGlobalWindow::GetInnerSize(CSSIntSize&
     }
 
     aSize = CSSIntRect::FromAppUnitsRounded(
       presContext->GetVisibleArea().Size());
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetInnerWidth(int32_t* aInnerWidth)
-{
-  FORWARD_TO_OUTER(GetInnerWidth, (aInnerWidth), NS_ERROR_NOT_INITIALIZED);
+int32_t
+nsGlobalWindow::GetInnerWidth(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetInnerWidth, (aError), aError, 0);
 
   CSSIntSize size;
-  nsresult rv = GetInnerSize(size);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aInnerWidth = size.width;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth)
-{
-  FORWARD_TO_OUTER(SetInnerWidth, (aInnerWidth), NS_ERROR_NOT_INITIALIZED);
-
-  NS_ENSURE_STATE(mDocShell);
+  aError = GetInnerSize(size);
+  return size.width;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetInnerWidth(int32_t* aInnerWidth)
+{
+  ErrorResult rv;
+  *aInnerWidth = GetInnerWidth(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetInnerWidth, (aInnerWidth, aError), aError, );
+
+  if (!mDocShell) {
+    aError.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent setting window.innerWidth by exiting early
    */
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   CheckSecurityWidthAndHeight(&aInnerWidth, nullptr);
 
-
   nsRefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (presShell && presShell->GetIsViewportOverridden())
   {
     nscoord height = 0;
-    nscoord width  = 0;
 
     nsRefPtr<nsPresContext> presContext;
     presContext = presShell->GetPresContext();
 
     nsRect shellArea = presContext->GetVisibleArea();
     height = shellArea.height;
-    width  = nsPresContext::CSSPixelsToAppUnits(aInnerWidth);
-    SetCSSViewportWidthAndHeight(width, height);
-    return NS_OK;
-  }
-  else
-  {
-    int32_t height = 0;
-    int32_t width  = 0;
-
-    nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
-    docShellAsWin->GetSize(&width, &height);
-    width  = CSSToDevIntPixels(aInnerWidth);
-    return SetDocShellWidthAndHeight(width, height);
-  }
+    SetCSSViewportWidthAndHeight(nsPresContext::CSSPixelsToAppUnits(aInnerWidth),
+                                 height);
+    return;
+  }
+
+  int32_t height = 0;
+  int32_t unused  = 0;
+
+  nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
+  docShellAsWin->GetSize(&unused, &height);
+  aError = SetDocShellWidthAndHeight(CSSToDevIntPixels(aInnerWidth), height);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth)
+{
+  ErrorResult rv;
+  SetInnerWidth(aInnerWidth, rv);
+
+  return rv.ErrorCode();
+}
+
+int32_t
+nsGlobalWindow::GetInnerHeight(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetInnerHeight, (aError), aError, 0);
+
+  CSSIntSize size;
+  aError = GetInnerSize(size);
+  return size.height;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetInnerHeight(int32_t* aInnerHeight)
 {
-  FORWARD_TO_OUTER(GetInnerHeight, (aInnerHeight), NS_ERROR_NOT_INITIALIZED);
-
-  CSSIntSize size;
-  nsresult rv = GetInnerSize(size);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aInnerHeight = size.height;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight)
-{
-  FORWARD_TO_OUTER(SetInnerHeight, (aInnerHeight), NS_ERROR_NOT_INITIALIZED);
-
-  NS_ENSURE_STATE(mDocShell);
+  ErrorResult rv;
+  *aInnerHeight = GetInnerHeight(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetInnerHeight, (aInnerHeight, aError), aError, );
+
+  if (!mDocShell) {
+    aError.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent setting window.innerHeight by exiting early
    */
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
-  }
-
-  CheckSecurityWidthAndHeight(nullptr, &aInnerHeight);
+    return;
+  }
 
   nsRefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (presShell && presShell->GetIsViewportOverridden())
   {
-    nscoord height = 0;
-    nscoord width  = 0;
-
     nsRefPtr<nsPresContext> presContext;
     presContext = presShell->GetPresContext();
 
     nsRect shellArea = presContext->GetVisibleArea();
-    width = shellArea.width;
-    height  = nsPresContext::CSSPixelsToAppUnits(aInnerHeight);
-    SetCSSViewportWidthAndHeight(width, height);
-    return NS_OK;
-  }
-  else
-  {
-    int32_t height = 0;
-    int32_t width  = 0;
-
-    nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
-    docShellAsWin->GetSize(&width, &height);
-    height  = CSSToDevIntPixels(aInnerHeight);
-    return SetDocShellWidthAndHeight(width, height);
-  }
-}
-
-nsresult
-nsGlobalWindow::GetOuterSize(nsIntSize* aSizeCSSPixels)
-{
+    nscoord height = aInnerHeight;
+    nscoord width = shellArea.width;
+    CheckSecurityWidthAndHeight(nullptr, &height);
+    SetCSSViewportWidthAndHeight(width,
+                                 nsPresContext::CSSPixelsToAppUnits(height));
+    return;
+  }
+
+  int32_t height = 0;
+  int32_t width  = 0;
+
+  nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
+  docShellAsWin->GetSize(&width, &height);
+  CheckSecurityWidthAndHeight(nullptr, &aInnerHeight);
+  aError = SetDocShellWidthAndHeight(width, CSSToDevIntPixels(aInnerHeight));
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight)
+{
+  ErrorResult rv;
+  SetInnerHeight(aInnerHeight, rv);
+
+  return rv.ErrorCode();
+}
+
+nsIntSize
+nsGlobalWindow::GetOuterSize(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetOuterSize, (aError), aError, nsIntSize(0, 0));
+
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return nsIntSize(0, 0);
+  }
 
   nsGlobalWindow* rootWindow =
     static_cast<nsGlobalWindow *>(GetPrivateRoot());
   if (rootWindow) {
     rootWindow->FlushPendingNotifications(Flush_Layout);
   }
 
   nsIntSize sizeDevPixels;
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetSize(&sizeDevPixels.width,
-                                            &sizeDevPixels.height),
-                    NS_ERROR_FAILURE);
-
-  *aSizeCSSPixels = DevToCSSIntPixels(sizeDevPixels);
-  return NS_OK;
+  aError = treeOwnerAsWin->GetSize(&sizeDevPixels.width, &sizeDevPixels.height);
+  if (aError.Failed()) {
+    return nsIntSize();
+  }
+
+  return DevToCSSIntPixels(sizeDevPixels);
+}
+
+int32_t
+nsGlobalWindow::GetOuterWidth(ErrorResult& aError)
+{
+  return GetOuterSize(aError).width;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetOuterWidth(int32_t* aOuterWidth)
 {
-  FORWARD_TO_OUTER(GetOuterWidth, (aOuterWidth), NS_ERROR_NOT_INITIALIZED);
-
-  nsIntSize sizeCSSPixels;
-  nsresult rv = GetOuterSize(&sizeCSSPixels);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aOuterWidth = sizeCSSPixels.width;
-  return NS_OK;
+  ErrorResult rv;
+  *aOuterWidth = GetOuterWidth(rv);
+
+  return rv.ErrorCode();
+}
+
+int32_t
+nsGlobalWindow::GetOuterHeight(ErrorResult& aError)
+{
+  return GetOuterSize(aError).height;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetOuterHeight(int32_t* aOuterHeight)
 {
-  FORWARD_TO_OUTER(GetOuterHeight, (aOuterHeight), NS_ERROR_NOT_INITIALIZED);
-
-  nsIntSize sizeCSSPixels;
-  nsresult rv = GetOuterSize(&sizeCSSPixels);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aOuterHeight = sizeCSSPixels.height;
-  return NS_OK;
-}
-
-nsresult
-nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth)
+  ErrorResult rv;
+  *aOuterHeight = GetOuterHeight(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
+                             ErrorResult& aError)
 {
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent setting window.outerWidth by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   CheckSecurityWidthAndHeight(aIsWidth ? &aLengthCSSPixels : nullptr,
                               aIsWidth ? nullptr : &aLengthCSSPixels);
 
   int32_t width, height;
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetSize(&width, &height), NS_ERROR_FAILURE);
+  aError = treeOwnerAsWin->GetSize(&width, &height);
+  if (aError.Failed()) {
+    return;
+  }
 
   int32_t lengthDevPixels = CSSToDevIntPixels(aLengthCSSPixels);
   if (aIsWidth) {
     width = lengthDevPixels;
   } else {
     height = lengthDevPixels;
   }
-  return treeOwnerAsWin->SetSize(width, height, true);    
+  aError = treeOwnerAsWin->SetSize(width, height, true);    
+}
+
+void
+nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetOuterWidth, (aOuterWidth, aError), aError, );
+
+  SetOuterSize(aOuterWidth, true, aError);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth)
 {
-  FORWARD_TO_OUTER(SetOuterWidth, (aOuterWidth), NS_ERROR_NOT_INITIALIZED);
-
-  return SetOuterSize(aOuterWidth, true);
+  ErrorResult rv;
+  SetOuterWidth(aOuterWidth, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetOuterHeight(int32_t aOuterHeight, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetOuterHeight, (aOuterHeight, aError), aError, );
+
+  SetOuterSize(aOuterHeight, false, aError);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetOuterHeight(int32_t aOuterHeight)
 {
-  FORWARD_TO_OUTER(SetOuterHeight, (aOuterHeight), NS_ERROR_NOT_INITIALIZED);
-
-  return SetOuterSize(aOuterHeight, false);
+  ErrorResult rv;
+  SetOuterHeight(aOuterHeight, rv);
+
+  return rv.ErrorCode();
+}
+
+nsIntPoint
+nsGlobalWindow::GetScreenXY(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetScreenXY, (aError), aError, nsIntPoint(0, 0));
+
+  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return nsIntPoint(0, 0);
+  }
+
+  int32_t x = 0, y = 0;
+  aError = treeOwnerAsWin->GetPosition(&x, &y);
+  return nsIntPoint(x, y);
+}
+
+int32_t
+nsGlobalWindow::GetScreenX(ErrorResult& aError)
+{
+  return DevToCSSIntPixels(GetScreenXY(aError).x);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScreenX(int32_t* aScreenX)
 {
-  FORWARD_TO_OUTER(GetScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
-
-  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
-
-  int32_t x, y;
-
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
-                    NS_ERROR_FAILURE);
-
-  *aScreenX = DevToCSSIntPixels(x);
-  return NS_OK;
+  ErrorResult rv;
+  *aScreenX = GetScreenX(rv);
+
+  return rv.ErrorCode();
 }
 
 nsRect
 nsGlobalWindow::GetInnerScreenRect()
 {
   if (!mDocShell) {
     return nsRect();
   }
@@ -4433,284 +4731,373 @@ nsGlobalWindow::GetInnerScreenRect()
   nsIFrame* rootFrame = presShell->GetRootFrame();
   if (!rootFrame) {
     return nsRect();
   }
 
   return rootFrame->GetScreenRectInAppUnits();
 }
 
+float
+nsGlobalWindow::GetMozInnerScreenX(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenX, (aError), aError, 0);
+
+  nsRect r = GetInnerScreenRect();
+  return nsPresContext::AppUnitsToFloatCSSPixels(r.x);
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetMozInnerScreenX(float* aScreenX)
 {
-  FORWARD_TO_OUTER(GetMozInnerScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
+  ErrorResult rv;
+  *aScreenX = GetMozInnerScreenX(rv);
+
+  return rv.ErrorCode();
+}
+
+float
+nsGlobalWindow::GetMozInnerScreenY(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenY, (aError), aError, 0);
 
   nsRect r = GetInnerScreenRect();
-  *aScreenX = nsPresContext::AppUnitsToFloatCSSPixels(r.x);
-  return NS_OK;
+  return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozInnerScreenY(float* aScreenY)
 {
-  FORWARD_TO_OUTER(GetMozInnerScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
-
-  nsRect r = GetInnerScreenRect();
-  *aScreenY = nsPresContext::AppUnitsToFloatCSSPixels(r.y);
-  return NS_OK;
+  ErrorResult rv;
+  *aScreenY = GetMozInnerScreenY(rv);
+
+  return rv.ErrorCode();
+}
+
+float
+nsGlobalWindow::GetDevicePixelRatio(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetDevicePixelRatio, (aError), aError, 0.0);
+
+  if (!mDocShell) {
+    return 1.0;
+  }
+
+  nsCOMPtr<nsPresContext> presContext;
+  mDocShell->GetPresContext(getter_AddRefs(presContext));
+  if (!presContext) {
+    return 1.0;
+  }
+
+  return float(nsPresContext::AppUnitsPerCSSPixel())/
+      presContext->AppUnitsPerDevPixel();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetDevicePixelRatio(float* aRatio)
 {
-  FORWARD_TO_OUTER(GetDevicePixelRatio, (aRatio), NS_ERROR_NOT_INITIALIZED);
-
-  *aRatio = 1.0;
-
-  if (!mDocShell)
-    return NS_OK;
-
-  nsCOMPtr<nsPresContext> presContext;
-  mDocShell->GetPresContext(getter_AddRefs(presContext));
-  if (!presContext)
-    return NS_OK;
-
-  *aRatio = float(nsPresContext::AppUnitsPerCSSPixel())/
-      presContext->AppUnitsPerDevPixel();
-  return NS_OK;
+  ErrorResult rv;
+  *aRatio = GetDevicePixelRatio(rv);
+
+  return rv.ErrorCode();
+}
+
+uint64_t
+nsGlobalWindow::GetMozPaintCount(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetMozPaintCount, (aError), aError, 0);
+
+  if (!mDocShell) {
+    return 0;
+  }
+
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
+  return presShell ? presShell->GetPaintCount() : 0;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozPaintCount(uint64_t* aResult)
 {
-  FORWARD_TO_OUTER(GetMozPaintCount, (aResult), NS_ERROR_NOT_INITIALIZED);
-
-  *aResult = 0;
-
-  if (!mDocShell)
-    return NS_OK;
-
-  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
-  if (!presShell)
-    return NS_OK;
-
-  *aResult = presShell->GetPaintCount();
-  return NS_OK;
+  ErrorResult rv;
+  *aResult = GetMozPaintCount(rv);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback,
                                          int32_t *aHandle)
 {
-  FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback, aHandle),
-                   NS_ERROR_NOT_INITIALIZED);
-
   if (!aCallback) {
     if (mDoc) {
       mDoc->WarnOnceAbout(nsIDocument::eMozBeforePaint);
     }
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
 
+  ErrorResult rv;
   nsIDocument::FrameRequestCallbackHolder holder(aCallback);
-  return RequestAnimationFrame(holder, aHandle);
-}
-
-nsresult
+  *aHandle = RequestAnimationFrame(holder, rv);
+
+  return rv.ErrorCode();
+}
+
+int32_t
+nsGlobalWindow::RequestAnimationFrame(FrameRequestCallback& aCallback,
+                                      ErrorResult& aError)
+{
+  nsIDocument::FrameRequestCallbackHolder holder(&aCallback);
+  return RequestAnimationFrame(holder, aError);
+}
+
+int32_t
+nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback,
+                                         ErrorResult& aError)
+{
+  nsIDocument::FrameRequestCallbackHolder holder(aCallback);
+  return RequestAnimationFrame(holder, aError);
+}
+
+int32_t
 nsGlobalWindow::RequestAnimationFrame(const nsIDocument::FrameRequestCallbackHolder& aCallback,
-                                      int32_t* aHandle)
-{
-  MOZ_ASSERT(IsInnerWindow());
+                                      ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(RequestAnimationFrame, (aCallback, aError), aError,
+                            0);
 
   if (!mDoc) {
-    *aHandle = 0;
-    return NS_OK;
-  }
-
-  if (mJSObject)
+    return 0;
+  }
+
+  if (mJSObject) {
     js::NotifyAnimationActivity(mJSObject);
-
-  return mDoc->ScheduleFrameRequestCallback(aCallback, aHandle);
+  }
+
+  int32_t handle;
+  aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
+  return handle;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::RequestAnimationFrame(const JS::Value& aCallback,
                                       JSContext* cx,
                                       int32_t* aHandle)
 {
-  FORWARD_TO_INNER(RequestAnimationFrame, (aCallback, cx, aHandle),
-                   NS_ERROR_NOT_INITIALIZED);
-
   if (!aCallback.isObject() || !JS_ObjectIsCallable(cx, &aCallback.toObject())) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsRefPtr<FrameRequestCallback> callback =
     new FrameRequestCallback(&aCallback.toObject());
 
-  nsIDocument::FrameRequestCallbackHolder holder(callback);
-  return RequestAnimationFrame(holder, aHandle);
+  ErrorResult rv;
+  *aHandle = RequestAnimationFrame(*callback, rv);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::MozCancelRequestAnimationFrame(int32_t aHandle)
 {
   return CancelAnimationFrame(aHandle);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::MozCancelAnimationFrame(int32_t aHandle)
 {
   return CancelAnimationFrame(aHandle);
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::CancelAnimationFrame(int32_t aHandle)
-{
-  FORWARD_TO_INNER(CancelAnimationFrame, (aHandle),
-                   NS_ERROR_NOT_INITIALIZED);
+void
+nsGlobalWindow::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(CancelAnimationFrame, (aHandle, aError), aError, );
 
   if (!mDoc) {
-    return NS_OK;
+    return;
   }
 
   mDoc->CancelFrameRequestCallback(aHandle);
-  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::CancelAnimationFrame(int32_t aHandle)
+{
+  ErrorResult rv;
+  CancelAnimationFrame(aHandle, rv);
+
+  return rv.ErrorCode();
+}
+
+int64_t
+nsGlobalWindow::GetMozAnimationStartTime(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetMozAnimationStartTime, (aError), aError, 0);
+
+  if (mDoc) {
+    nsIPresShell* presShell = mDoc->GetShell();
+    if (presShell) {
+      return presShell->GetPresContext()->RefreshDriver()->
+        MostRecentRefreshEpochTime() / PR_USEC_PER_MSEC;
+    }
+  }
+
+  // If all else fails, just be compatible with Date.now()
+  return JS_Now() / PR_USEC_PER_MSEC;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozAnimationStartTime(int64_t *aTime)
 {
-  FORWARD_TO_INNER(GetMozAnimationStartTime, (aTime), NS_ERROR_NOT_INITIALIZED);
-
-  if (mDoc) {
-    nsIPresShell* presShell = mDoc->GetShell();
-    if (presShell) {
-      *aTime = presShell->GetPresContext()->RefreshDriver()->
-        MostRecentRefreshEpochTime() / PR_USEC_PER_MSEC;
-      return NS_OK;
-    }
-  }
-
-  // If all else fails, just be compatible with Date.now()
-  *aTime = JS_Now() / PR_USEC_PER_MSEC;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
+  ErrorResult rv;
+  *aTime = GetMozAnimationStartTime(rv);
+
+  return rv.ErrorCode();
+}
+
+already_AddRefed<nsIDOMMediaQueryList>
 nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
-                           nsIDOMMediaQueryList** aResult)
+                           ErrorResult& aError)
 {
   // FIXME: This whole forward-to-outer and then get a pres
   // shell/context off the docshell dance is sort of silly; it'd make
   // more sense to forward to the inner, but it's what everyone else
   // (GetSelection, GetScrollXY, etc.) does around here.
-  FORWARD_TO_OUTER(MatchMedia, (aMediaQueryList, aResult),
-                   NS_ERROR_NOT_INITIALIZED);
-
-  *aResult = nullptr;
+  FORWARD_TO_OUTER_OR_THROW(MatchMedia, (aMediaQueryList, aError), aError,
+                            nullptr);
 
   // We need this now to ensure that we have a non-null |presContext|
   // when we ought to.
   // This is similar to EnsureSizeUpToDate, but only flushes frames.
   nsGlobalWindow *parent = static_cast<nsGlobalWindow*>(GetPrivateParent());
   if (parent) {
     parent->FlushPendingNotifications(Flush_Frames);
   }
 
-  if (!mDocShell)
-    return NS_OK;
+  if (!mDocShell) {
+    return nullptr;
+  }
 
   nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
 
-  if (!presContext)
-    return NS_OK;
-
-  presContext->MatchMedia(aMediaQueryList, aResult);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SetScreenX(int32_t aScreenX)
-{
-  FORWARD_TO_OUTER(SetScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
+  if (!presContext) {
+    return nullptr;
+  }
+
+  return presContext->MatchMedia(aMediaQueryList);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
+                           nsIDOMMediaQueryList** aResult)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMMediaQueryList> mediaQueryList =
+    MatchMedia(aMediaQueryList, rv);
+  mediaQueryList.forget(aResult);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetScreenX(int32_t aScreenX, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetScreenX, (aScreenX, aError), aError, );
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent setting window.screenX by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
-
-  CheckSecurityLeftAndTop(&aScreenX, nullptr);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   int32_t x, y;
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
-                    NS_ERROR_FAILURE);
-
+  aError = treeOwnerAsWin->GetPosition(&x, &y);
+  if (aError.Failed()) {
+    return;
+  }
+
+  CheckSecurityLeftAndTop(&aScreenX, nullptr);
   x = CSSToDevIntPixels(aScreenX);
 
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(x, y),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
+  aError = treeOwnerAsWin->SetPosition(x, y);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetScreenX(int32_t aScreenX)
+{
+  ErrorResult rv;
+  SetScreenX(aScreenX, rv);
+
+  return rv.ErrorCode();
+}
+
+int32_t
+nsGlobalWindow::GetScreenY(ErrorResult& aError)
+{
+  return DevToCSSIntPixels(GetScreenXY(aError).y);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScreenY(int32_t* aScreenY)
 {
-  FORWARD_TO_OUTER(GetScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
-
-  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
-
-  int32_t x, y;
-
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
-                    NS_ERROR_FAILURE);
-
-  *aScreenY = DevToCSSIntPixels(y);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SetScreenY(int32_t aScreenY)
-{
-  FORWARD_TO_OUTER(SetScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
+  ErrorResult rv;
+  *aScreenY = GetScreenY(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetScreenY(int32_t aScreenY, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SetScreenY, (aScreenY, aError), aError, );
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent setting window.screenY by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
-
-  CheckSecurityLeftAndTop(nullptr, &aScreenY);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   int32_t x, y;
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
-                    NS_ERROR_FAILURE);
-
+  aError = treeOwnerAsWin->GetPosition(&x, &y);
+  if (aError.Failed()) {
+    return;
+  }
+
+  CheckSecurityLeftAndTop(nullptr, &aScreenY);
   y = CSSToDevIntPixels(aScreenY);
 
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(x, y),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
+  aError = treeOwnerAsWin->SetPosition(x, y);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetScreenY(int32_t aScreenY)
+{
+  ErrorResult rv;
+  SetScreenY(aScreenY, rv);
+
+  return rv.ErrorCode();
 }
 
 // NOTE: Arguments to this function should have values scaled to
 // CSS pixels, not device pixels.
 void
 nsGlobalWindow::CheckSecurityWidthAndHeight(int32_t* aWidth, int32_t* aHeight)
 {
 #ifdef MOZ_XUL
@@ -4852,121 +5239,149 @@ nsGlobalWindow::GetPageXOffset(int32_t* 
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPageYOffset(int32_t* aPageYOffset)
 {
   return GetScrollY(aPageYOffset);
 }
 
-nsresult
-nsGlobalWindow::GetScrollMaxXY(int32_t* aScrollMaxX, int32_t* aScrollMaxY)
-{
-  FORWARD_TO_OUTER(GetScrollMaxXY, (aScrollMaxX, aScrollMaxY),
-                   NS_ERROR_NOT_INITIALIZED);
+void
+nsGlobalWindow::GetScrollMaxXY(int32_t* aScrollMaxX, int32_t* aScrollMaxY,
+                               ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetScrollMaxXY, (aScrollMaxX, aScrollMaxY, aError),
+                            aError, );
 
   FlushPendingNotifications(Flush_Layout);
   nsIScrollableFrame *sf = GetScrollFrame();
-  if (!sf)
-    return NS_OK;
+  if (!sf) {
+    return;
+  }
 
   nsRect scrollRange = sf->GetScrollRange();
 
-  if (aScrollMaxX)
+  if (aScrollMaxX) {
     *aScrollMaxX = std::max(0,
       (int32_t)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange.XMost())));
-  if (aScrollMaxY)
+  }
+  if (aScrollMaxY) {
     *aScrollMaxY = std::max(0,
       (int32_t)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange.YMost())));
-
-  return NS_OK;
+  }
+}
+
+int32_t
+nsGlobalWindow::GetScrollMaxX(ErrorResult& aError)
+{
+  int32_t scrollMaxX = 0;
+  GetScrollMaxXY(&scrollMaxX, nullptr, aError);
+  return scrollMaxX;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScrollMaxX(int32_t* aScrollMaxX)
 {
   NS_ENSURE_ARG_POINTER(aScrollMaxX);
-  *aScrollMaxX = 0;
-  return GetScrollMaxXY(aScrollMaxX, nullptr);
+  ErrorResult rv;
+  *aScrollMaxX = GetScrollMaxX(rv);
+
+  return rv.ErrorCode();
+}
+
+int32_t
+nsGlobalWindow::GetScrollMaxY(ErrorResult& aError)
+{
+  int32_t scrollMaxY = 0;
+  GetScrollMaxXY(nullptr, &scrollMaxY, aError);
+  return scrollMaxY;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScrollMaxY(int32_t* aScrollMaxY)
 {
   NS_ENSURE_ARG_POINTER(aScrollMaxY);
-  *aScrollMaxY = 0;
-  return GetScrollMaxXY(nullptr, aScrollMaxY);
-}
-
-nsresult
-nsGlobalWindow::GetScrollXY(int32_t* aScrollX, int32_t* aScrollY,
-                            bool aDoFlush)
-{
-  FORWARD_TO_OUTER(GetScrollXY, (aScrollX, aScrollY, aDoFlush),
-                   NS_ERROR_NOT_INITIALIZED);
+  ErrorResult rv;
+  *aScrollMaxY = GetScrollMaxY(rv);
+
+  return rv.ErrorCode();
+}
+
+CSSIntPoint
+nsGlobalWindow::GetScrollXY(bool aDoFlush, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetScrollXY, (aDoFlush, aError), aError,
+                            CSSIntPoint(0, 0));
 
   if (aDoFlush) {
     FlushPendingNotifications(Flush_Layout);
   } else {
     EnsureSizeUpToDate();
   }
 
   nsIScrollableFrame *sf = GetScrollFrame();
-  if (!sf)
-    return NS_OK;
+  if (!sf) {
+    return CSSIntPoint(0, 0);
+  }
 
   nsPoint scrollPos = sf->GetScrollPosition();
   if (scrollPos != nsPoint(0,0) && !aDoFlush) {
     // Oh, well.  This is the expensive case -- the window is scrolled and we
     // didn't actually flush yet.  Repeat, but with a flush, since the content
     // may get shorter and hence our scroll position may decrease.
-    return GetScrollXY(aScrollX, aScrollY, true);
-  }
-
-  CSSIntPoint scrollPosCSSPixels = sf->GetScrollPositionCSSPixels();
-  if (aScrollX) {
-    *aScrollX = scrollPosCSSPixels.x;
-  }
-  if (aScrollY) {
-    *aScrollY = scrollPosCSSPixels.y;
-  }
-  return NS_OK;
+    return GetScrollXY(true, aError);
+  }
+
+  return sf->GetScrollPositionCSSPixels();
+}
+
+int32_t
+nsGlobalWindow::GetScrollX(ErrorResult& aError)
+{
+  return GetScrollXY(false, aError).x;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScrollX(int32_t* aScrollX)
 {
   NS_ENSURE_ARG_POINTER(aScrollX);
-  *aScrollX = 0;
-  return GetScrollXY(aScrollX, nullptr, false);
+  ErrorResult rv;
+  *aScrollX = GetScrollXY(false, rv).x;
+  return rv.ErrorCode();
+}
+
+int32_t
+nsGlobalWindow::GetScrollY(ErrorResult& aError)
+{
+  return GetScrollXY(false, aError).y;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScrollY(int32_t* aScrollY)
 {
   NS_ENSURE_ARG_POINTER(aScrollY);
-  *aScrollY = 0;
-  return GetScrollXY(nullptr, aScrollY, false);
+  ErrorResult rv;
+  *aScrollY = GetScrollXY(false, rv).y;
+  return rv.ErrorCode();
 }
 
 uint32_t
-nsGlobalWindow::GetLength()
-{
-  FORWARD_TO_OUTER(GetLength, (), 0);
+nsGlobalWindow::Length()
+{
+  FORWARD_TO_OUTER(Length, (), 0);
 
   nsDOMWindowList* windows = GetWindowList();
-  NS_ENSURE_TRUE(windows, 0);
-
-  return windows->GetLength();
+
+  return windows ? windows->GetLength() : 0;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetLength(uint32_t* aLength)
 {
-  *aLength = GetLength();
+  *aLength = Length();
   return NS_OK;
 }
 
 already_AddRefed<nsIDOMWindow>
 nsGlobalWindow::GetChildWindow(const nsAString& aName)
 {
   nsCOMPtr<nsIDocShellTreeNode> dsn(do_QueryInterface(GetDocShell()));
   NS_ENSURE_TRUE(dsn, nullptr);
@@ -5104,16 +5519,22 @@ nsGlobalWindow::GetNearestWidget()
   NS_ENSURE_TRUE(docShell, nullptr);
   nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, nullptr);
   nsIFrame* rootFrame = presShell->GetRootFrame();
   NS_ENSURE_TRUE(rootFrame, nullptr);
   return rootFrame->GetView()->GetNearestWidget(nullptr);
 }
 
+void
+nsGlobalWindow::SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError)
+{
+  aError = SetFullScreenInternal(aFullScreen, true);
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::SetFullScreen(bool aFullScreen)
 {
   return SetFullScreenInternal(aFullScreen, true);
 }
 
 nsresult
 nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust)
@@ -5198,36 +5619,47 @@ nsGlobalWindow::SetFullScreenInternal(bo
   } else if (mWakeLock && !mFullScreen) {
     mWakeLock->Unlock();
     mWakeLock = NULL;
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetFullScreen(bool* aFullScreen)
-{
-  FORWARD_TO_OUTER(GetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
+bool
+nsGlobalWindow::GetFullScreen(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetFullScreen, (aError), aError, false);
 
   // Get the fullscreen value of the root window, to always have the value
   // accurate, even when called from content.
   if (mDocShell) {
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
     mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
     if (rootItem != mDocShell) {
       nsCOMPtr<nsIDOMWindow> window = do_GetInterface(rootItem);
-      if (window)
-        return window->GetFullScreen(aFullScreen);
+      if (window) {
+        bool fullScreen = false;
+        aError = window->GetFullScreen(&fullScreen);
+        return fullScreen;
+      }
     }
   }
 
   // We are the root window, or something went wrong. Return our internal value.
-  *aFullScreen = mFullScreen;
-  return NS_OK;
+  return mFullScreen;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetFullScreen(bool* aFullScreen)
+{
+  ErrorResult rv;
+  *aFullScreen = GetFullScreen(rv);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Dump(const nsAString& aStr)
 {
   if (!nsContentUtils::DOMWindowDumpEnabled()) {
     return NS_OK;
   }
@@ -5436,23 +5868,24 @@ nsGlobalWindow::CanMoveResizeWindows()
     if (ds) {
       gDragServiceDisabled = true;
       ds->Suppress();
     }
   }
   return true;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::Alert(const nsAString& aString)
-{
-  FORWARD_TO_OUTER(Alert, (aString), NS_ERROR_NOT_INITIALIZED);
+void
+nsGlobalWindow::Alert(const nsAString& aMessage, mozilla::ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Alert, (aMessage, aError), aError, );
 
   if (!AreDialogsEnabled()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return;
   }
 
   // Reset popup state while opening a modal dialog, and firing events
   // about the dialog, to prevent the current state from being active
   // the whole time a modal dialog is open.
   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
   // Before bringing up the window, unsuppress painting and flush
@@ -5460,133 +5893,160 @@ nsGlobalWindow::Alert(const nsAString& a
   EnsureReflowFlushAndPaint();
 
   nsAutoString title;
   MakeScriptDialogTitle(title);
 
   // Remove non-terminating null characters from the 
   // string. See bug #310037. 
   nsAutoString final;
-  nsContentUtils::StripNullChars(aString, final);
+  nsContentUtils::StripNullChars(aMessage, final);
 
   // Check if we're being called at a point where we can't use tab-modal
   // prompts, because something doesn't want reentrancy.
   bool allowTabModal = GetIsTabModalPromptAllowed();
 
   nsresult rv;
   nsCOMPtr<nsIPromptFactory> promptFac =
     do_GetService("@mozilla.org/prompter;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aError.Throw(rv);
+    return;
+  }
 
   nsCOMPtr<nsIPrompt> prompt;
-  rv = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
-                            reinterpret_cast<void**>(&prompt));
-  NS_ENSURE_SUCCESS(rv, rv);
+  aError = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
+                                reinterpret_cast<void**>(&prompt));
+  if (aError.Failed()) {
+    return;
+  }
 
   nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
   if (promptBag)
     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal);
 
   nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ? 
                              GetCurrentInnerWindowInternal()->mDoc :
                              nullptr);
   if (ShouldPromptToBlockDialogs()) {
     bool disallowDialog = false;
     nsXPIDLString label;
     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
                                        "ScriptDialogLabel", label);
 
-    rv = prompt->AlertCheck(title.get(), final.get(), label.get(),
-                            &disallowDialog);
+    aError = prompt->AlertCheck(title.get(), final.get(), label.get(),
+                                &disallowDialog);
     if (disallowDialog)
       DisableDialogs();
   } else {
-    rv = prompt->Alert(title.get(), final.get());
-  }
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn)
-{
-  FORWARD_TO_OUTER(Confirm, (aString, aReturn), NS_ERROR_NOT_INITIALIZED);
+    aError = prompt->Alert(title.get(), final.get());
+  }
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Alert(const nsAString& aString)
+{
+  ErrorResult rv;
+  Alert(aString, rv);
+
+  return rv.ErrorCode();
+}
+
+bool
+nsGlobalWindow::Confirm(const nsAString& aMessage, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Confirm, (aMessage, aError), aError, false);
 
   if (!AreDialogsEnabled()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return false;
   }
 
   // Reset popup state while opening a modal dialog, and firing events
   // about the dialog, to prevent the current state from being active
   // the whole time a modal dialog is open.
   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
-  *aReturn = false;
-
   // Before bringing up the window, unsuppress painting and flush
   // pending reflows.
   EnsureReflowFlushAndPaint();
 
   nsAutoString title;
   MakeScriptDialogTitle(title);
 
   // Remove non-terminating null characters from the 
   // string. See bug #310037. 
   nsAutoString final;
-  nsContentUtils::StripNullChars(aString, final);
+  nsContentUtils::StripNullChars(aMessage, final);
 
   // Check if we're being called at a point where we can't use tab-modal
   // prompts, because something doesn't want reentrancy.
   bool allowTabModal = GetIsTabModalPromptAllowed();
 
   nsresult rv;
   nsCOMPtr<nsIPromptFactory> promptFac =
     do_GetService("@mozilla.org/prompter;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aError.Throw(rv);
+    return false;
+  }
 
   nsCOMPtr<nsIPrompt> prompt;
-  rv = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
-                            reinterpret_cast<void**>(&prompt));
-  NS_ENSURE_SUCCESS(rv, rv);
+  aError = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
+                                reinterpret_cast<void**>(&prompt));
+  if (aError.Failed()) {
+    return false;
+  }
 
   nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
   if (promptBag)
     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal);
 
+  bool result = false;
   nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ? 
                              GetCurrentInnerWindowInternal()->mDoc :
                              nullptr);
   if (ShouldPromptToBlockDialogs()) {
     bool disallowDialog = false;
     nsXPIDLString label;
     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
                                        "ScriptDialogLabel", label);
 
-    rv = prompt->ConfirmCheck(title.get(), final.get(), label.get(),
-                              &disallowDialog, aReturn);
+    aError = prompt->ConfirmCheck(title.get(), final.get(), label.get(),
+                                  &disallowDialog, &result);
     if (disallowDialog)
       DisableDialogs();
   } else {
-    rv = prompt->Confirm(title.get(), final.get(), aReturn);
-  }
-
-  return rv;
-}
-
-NS_IMETHODIMP
+    aError = prompt->Confirm(title.get(), final.get(), &result);
+  }
+
+  return result;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn)
+{
+  ErrorResult rv;
+  *aReturn = Confirm(aString, rv);
+
+  return rv.ErrorCode();
+}
+
+void
 nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
-                       nsAString& aReturn)
-{
-  FORWARD_TO_OUTER(Prompt, (aMessage, aInitial, aReturn),
-                   NS_ERROR_NOT_INITIALIZED);
+                       nsAString& aReturn, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Prompt, (aMessage, aInitial, aReturn, aError),
+                            aError, );
 
   SetDOMStringToNull(aReturn);
 
   if (!AreDialogsEnabled()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return;
   }
 
   // Reset popup state while opening a modal dialog, and firing events
   // about the dialog, to prevent the current state from being active
   // the whole time a modal dialog is open.
   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
   // Before bringing up the window, unsuppress painting and flush
@@ -5604,22 +6064,27 @@ nsGlobalWindow::Prompt(const nsAString& 
 
   // Check if we're being called at a point where we can't use tab-modal
   // prompts, because something doesn't want reentrancy.
   bool allowTabModal = GetIsTabModalPromptAllowed();
 
   nsresult rv;
   nsCOMPtr<nsIPromptFactory> promptFac =
     do_GetService("@mozilla.org/prompter;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aError.Throw(rv);
+    return;
+  }
 
   nsCOMPtr<nsIPrompt> prompt;
-  rv = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
-                            reinterpret_cast<void**>(&prompt));
-  NS_ENSURE_SUCCESS(rv, rv);
+  aError = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
+                                reinterpret_cast<void**>(&prompt));
+  if (aError.Failed()) {
+    return;
+  }
 
   nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
   if (promptBag)
     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal);
 
   // Pass in the default value, if any.
   PRUnichar *inoutValue = ToNewUnicode(fixedInitial);
   bool disallowDialog = false;
@@ -5629,53 +6094,64 @@ nsGlobalWindow::Prompt(const nsAString& 
     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
                                        "ScriptDialogLabel", label);
   }
 
   nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ? 
                              GetCurrentInnerWindowInternal()->mDoc :
                              nullptr);
   bool ok;
-  rv = prompt->Prompt(title.get(), fixedMessage.get(),
-                      &inoutValue, label.get(), &disallowDialog, &ok);
+  aError = prompt->Prompt(title.get(), fixedMessage.get(),
+                          &inoutValue, label.get(), &disallowDialog, &ok);
 
   if (disallowDialog) {
     DisableDialogs();
   }
 
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (aError.Failed()) {
+    return;
+  }
 
   nsAdoptingString outValue(inoutValue);
 
   if (ok && outValue) {
     aReturn.Assign(outValue);
   }
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::Focus()
-{
-  FORWARD_TO_OUTER(Focus, (), NS_ERROR_NOT_INITIALIZED);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
+                       nsAString& aReturn)
+{
+  ErrorResult rv;
+  Prompt(aMessage, aInitial, aReturn, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Focus(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Focus, (aError), aError, );
 
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-  if (!fm)
-    return NS_OK;
+  if (!fm) {
+    return;
+  }
 
   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
 
   bool isVisible = false;
   if (baseWin) {
     baseWin->GetVisibility(&isVisible);
   }
 
   if (!isVisible) {
     // A hidden tab is being focused, ignore this call.
-    return NS_OK;
+    return;
   }
 
   nsIDOMWindow *caller = nsContentUtils::GetWindowFromCaller();
   nsCOMPtr<nsIDOMWindow> opener;
   GetOpener(getter_AddRefs(opener));
 
   // Enforce dom.disable_window_flip (for non-chrome), but still allow the
   // window which opened us to raise us at times when popups are allowed
@@ -5692,27 +6168,28 @@ nsGlobalWindow::Focus()
   nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
   bool isActive = (rootWin == activeWindow);
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
   if (treeOwnerAsWin && (canFocus || isActive)) {
     bool isEnabled = true;
     if (NS_SUCCEEDED(treeOwnerAsWin->GetEnabled(&isEnabled)) && !isEnabled) {
       NS_WARNING( "Should not try to set the focus on a disabled window" );
-      return NS_OK;
+      return;
     }
 
     // XXXndeakin not sure what this is for or if it should go somewhere else
     nsCOMPtr<nsIEmbeddingSiteWindow> embeddingWin(do_GetInterface(treeOwnerAsWin));
     if (embeddingWin)
       embeddingWin->SetFocus();
   }
 
-  if (!mDocShell)
-    return NS_OK;
+  if (!mDocShell) {
+    return;
+  }
 
   nsCOMPtr<nsIPresShell> presShell;
   // Don't look for a presshell if we're a root chrome window that's got
   // about:blank loaded.  We don't want to focus our widget in that case.
   // XXXbz should we really be checking for IsInitialDocument() instead?
   bool lookForPresShell = true;
   int32_t itemType = nsIDocShellTreeItem::typeContent;
   mDocShell->GetItemType(&itemType);
@@ -5731,49 +6208,59 @@ nsGlobalWindow::Focus()
 
   nsCOMPtr<nsIDocShellTreeItem> parentDsti;
   mDocShell->GetParent(getter_AddRefs(parentDsti));
 
   // set the parent's current focus to the frame containing this window.
   nsCOMPtr<nsPIDOMWindow> parent = do_GetInterface(parentDsti);
   if (parent) {
     nsCOMPtr<nsIDocument> parentdoc = parent->GetDoc();
-    if (!parentdoc)
-      return NS_OK;
+    if (!parentdoc) {
+      return;
+    }
 
     nsIContent* frame = parentdoc->FindContentForSubDocument(mDoc);
     nsCOMPtr<nsIDOMElement> frameElement = do_QueryInterface(frame);
     if (frameElement) {
       uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
       if (canFocus)
         flags |= nsIFocusManager::FLAG_RAISE;
-      return fm->SetFocus(frameElement, flags);
-    }
-  }
-  else if (TabChild *child = TabChild::GetFrom(this)) {
+      aError = fm->SetFocus(frameElement, flags);
+    }
+    return;
+  }
+  if (TabChild *child = TabChild::GetFrom(this)) {
     child->SendRequestFocus(canFocus);
-  }
-  else if (canFocus) {
+    return;
+  }
+  if (canFocus) {
     // if there is no parent, this must be a toplevel window, so raise the
     // window if canFocus is true
-    return fm->SetActiveWindow(this);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::Blur()
-{
-  FORWARD_TO_OUTER(Blur, (), NS_ERROR_NOT_INITIALIZED);
+    aError = fm->SetActiveWindow(this);
+  }
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Focus()
+{
+  ErrorResult rv;
+  Focus(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Blur(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Blur, (aError), aError, );
 
   // If dom.disable_window_flip == true, then content should not be allowed
   // to call this function (this would allow popunders, bug 369306)
   if (!CanSetProperty("dom.disable_window_flip")) {
-    return NS_OK;
+    return;
   }
 
   // If embedding apps don't implement nsIEmbeddingSiteWindow, we
   // shouldn't throw exceptions to web content.
 
   nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
   nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow(do_GetInterface(treeOwner));
   if (siteWindow) {
@@ -5785,49 +6272,81 @@ nsGlobalWindow::Blur()
     if (fm && mDoc) {
       nsCOMPtr<nsIDOMElement> element;
       fm->GetFocusedElementForWindow(this, false, nullptr, getter_AddRefs(element));
       nsCOMPtr<nsIContent> content = do_QueryInterface(element);
       if (content == mDoc->GetRootElement())
         fm->ClearFocus(this);
     }
   }
-
-  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Blur()
+{
+  ErrorResult rv;
+  Blur(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Back(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Back, (aError), aError, );
+
+  nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
+  if (!webNav) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  aError = webNav->GoBack();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Back()
 {
-  FORWARD_TO_OUTER(Back, (), NS_ERROR_NOT_INITIALIZED);
+  ErrorResult rv;
+  Back(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Forward(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Forward, (aError), aError, );
 
   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
-  NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
-
-  return webNav->GoBack();
+  if (!webNav) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  aError = webNav->GoForward();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Forward()
 {
-  FORWARD_TO_OUTER(Forward, (), NS_ERROR_NOT_INITIALIZED);
-
-  nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
-  NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
-
-  return webNav->GoForward();
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::Home()
-{
-  FORWARD_TO_OUTER(Home, (), NS_ERROR_NOT_INITIALIZED);
-
-  if (!mDocShell)
-    return NS_OK;
+  ErrorResult rv;
+  Forward(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Home(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Home, (aError), aError, );
+
+  if (!mDocShell) {
+    return;
+  }
 
   nsAdoptingString homeURL =
     Preferences::GetLocalizedString(PREF_BROWSER_STARTUP_HOMEPAGE);
 
   if (homeURL.IsEmpty()) {
     // if all else fails, use this
 #ifdef DEBUG_seth
     printf("all else failed.  using %s as the home page\n", DEFAULT_HOME_PAGE);
@@ -5849,55 +6368,77 @@ nsGlobalWindow::Home()
     int32_t firstPipe = homeURL.FindChar('|');
 
     if (firstPipe > 0) {
       homeURL.Truncate(firstPipe);
     }
   }
 #endif
 
-  nsresult rv;
   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
-  NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
-  rv = webNav->LoadURI(homeURL.get(),
-                       nsIWebNavigation::LOAD_FLAGS_NONE,
-                       nullptr,
-                       nullptr,
-                       nullptr);
-  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
-  return NS_OK;
+  if (!webNav) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  aError = webNav->LoadURI(homeURL.get(),
+                           nsIWebNavigation::LOAD_FLAGS_NONE,
+                           nullptr,
+                           nullptr,
+                           nullptr);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Home()
+{
+  ErrorResult rv;
+  Home(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Stop(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Stop, (aError), aError, );
+
+  nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
+  if (webNav) {
+    aError = webNav->Stop(nsIWebNavigation::STOP_ALL);
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Stop()
 {
-  FORWARD_TO_OUTER(Stop, (), NS_ERROR_NOT_INITIALIZED);
-
-  nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
-  if (!webNav)
-    return NS_OK;
-
-  return webNav->Stop(nsIWebNavigation::STOP_ALL);
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::Print()
+  ErrorResult rv;
+  Stop(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Print(ErrorResult& aError)
 {
 #ifdef NS_PRINTING
-  FORWARD_TO_OUTER(Print, (), NS_ERROR_NOT_INITIALIZED);
-
-  if (Preferences::GetBool("dom.disable_window_print", false))
-    return NS_ERROR_NOT_AVAILABLE;
+  FORWARD_TO_OUTER_OR_THROW(Print, (aError), aError, );
+
+  if (Preferences::GetBool("dom.disable_window_print", false)) {
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return;
+  }
 
   if (!AreDialogsEnabled()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return;
   }
 
   if (ShouldPromptToBlockDialogs() && !ConfirmDialogIfNeeded()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return;
   }
 
   nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
   if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
                                 getter_AddRefs(webBrowserPrint)))) {
     nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ? 
                                GetCurrentInnerWindowInternal()->mDoc :
                                nullptr);
@@ -5944,233 +6485,297 @@ nsGlobalWindow::Print()
                                    nsIPrintSettings::kInitSavePrinterName);
       }
     } else {
       webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));
       webBrowserPrint->Print(printSettings, nullptr);
     }
   }
 #endif //NS_PRINTING
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos)
-{
-  FORWARD_TO_OUTER(MoveTo, (aXPos, aYPos), NS_ERROR_NOT_INITIALIZED);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Print()
+{
+  ErrorResult rv;
+  Print(rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(MoveTo, (aXPos, aYPos, aError), aError, );
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent window.moveTo() by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
-
-  CheckSecurityLeftAndTop(&aXPos, &aYPos);
-
-  // mild abuse of a "size" object so we don't need more helper functions
-  nsIntSize devPos(CSSToDevIntPixels(nsIntSize(aXPos, aYPos)));
-
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(devPos.width, devPos.height),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif)
-{
-  FORWARD_TO_OUTER(MoveBy, (aXDif, aYDif), NS_ERROR_NOT_INITIALIZED);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  // Mild abuse of a "size" object so we don't need more helper functions.
+  nsIntSize cssPos(aXPos, aYPos);
+  CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height);
+
+  nsIntSize devPos = CSSToDevIntPixels(cssPos);
+
+  aError = treeOwnerAsWin->SetPosition(devPos.width, devPos.height);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos)
+{
+  ErrorResult rv;
+  MoveTo(aXPos, aYPos, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(MoveBy, (aXDif, aYDif, aError), aError, );
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent window.moveBy() by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   // To do this correctly we have to convert what we get from GetPosition
   // into CSS pixels, add the arguments, do the security check, and
   // then convert back to device pixels for the call to SetPosition.
 
   int32_t x, y;
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y), NS_ERROR_FAILURE);
+  aError = treeOwnerAsWin->GetPosition(&x, &y);
+  if (aError.Failed()) {
+    return;
+  }
 
   // mild abuse of a "size" object so we don't need more helper functions
   nsIntSize cssPos(DevToCSSIntPixels(nsIntSize(x, y)));
 
   cssPos.width += aXDif;
   cssPos.height += aYDif;
   
   CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height);
 
   nsIntSize newDevPos(CSSToDevIntPixels(cssPos));
 
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(newDevPos.width,
-                                                newDevPos.height),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight)
-{
-  FORWARD_TO_OUTER(ResizeTo, (aWidth, aHeight), NS_ERROR_NOT_INITIALIZED);
+  aError = treeOwnerAsWin->SetPosition(newDevPos.width, newDevPos.height);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif)
+{
+  ErrorResult rv;
+  MoveBy(aXDif, aYDif, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(ResizeTo, (aWidth, aHeight, aError), aError, );
 
   /*
    * If caller is a browser-element then dispatch a resize event to
    * the embedder.
    */
   if (mDocShell && mDocShell->GetIsBrowserOrApp()) {
     nsIntSize size(aWidth, aHeight);
     if (!DispatchResizeEvent(size)) {
       // The embedder chose to prevent the default action for this
       // event, so let's not resize this window after all...
-      return NS_OK;
+      return;
     }
   }
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent window.resizeTo() by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
   
-  CheckSecurityWidthAndHeight(&aWidth, &aHeight);
-
-  nsIntSize devSz(CSSToDevIntPixels(nsIntSize(aWidth, aHeight)));
-
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->SetSize(devSz.width, devSz.height, true),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif)
-{
-  FORWARD_TO_OUTER(ResizeBy, (aWidthDif, aHeightDif), NS_ERROR_NOT_INITIALIZED);
+  nsIntSize cssSize(aWidth, aHeight);
+  CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height);
+
+  nsIntSize devSz(CSSToDevIntPixels(cssSize));
+
+  aError = treeOwnerAsWin->SetSize(devSz.width, devSz.height, true);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight)
+{
+  ErrorResult rv;
+  ResizeTo(aWidth, aHeight, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
+                         ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(ResizeBy, (aWidthDif, aHeightDif, aError), aError, );
 
   /*
    * If caller is a browser-element then dispatch a resize event to
    * parent.
    */
   if (mDocShell && mDocShell->GetIsBrowserOrApp()) {
     CSSIntSize size;
-    nsresult rv = GetInnerSize(size);
-    NS_ENSURE_SUCCESS(rv, NS_OK);
+    if (NS_FAILED(GetInnerSize(size))) {
+      return;
+    }
 
     size.width += aWidthDif;
     size.height += aHeightDif;
 
     if (!DispatchResizeEvent(nsIntSize(size.width, size.height))) {
       // The embedder chose to prevent the default action for this
       // event, so let's not resize this window after all...
-      return NS_OK;
+      return;
     }
   }
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent window.resizeBy() by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
-  NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
+  if (!treeOwnerAsWin) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   int32_t width, height;
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->GetSize(&width, &height), NS_ERROR_FAILURE);
+  aError = treeOwnerAsWin->GetSize(&width, &height);
+  if (aError.Failed()) {
+    return;
+  }
 
   // To do this correctly we have to convert what we got from GetSize
   // into CSS pixels, add the arguments, do the security check, and
   // then convert back to device pixels for the call to SetSize.
 
   nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
 
   cssSize.width += aWidthDif;
   cssSize.height += aHeightDif;
 
   CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height);
 
   nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
 
-  NS_ENSURE_SUCCESS(treeOwnerAsWin->SetSize(newDevSize.width,
-                                            newDevSize.height,
-                                            true),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::SizeToContent()
-{
-  FORWARD_TO_OUTER(SizeToContent, (), NS_ERROR_NOT_INITIALIZED);
+  aError = treeOwnerAsWin->SetSize(newDevSize.width, newDevSize.height, true);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif)
+{
+  ErrorResult rv;
+  ResizeBy(aWidthDif, aHeightDif, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SizeToContent(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(SizeToContent, (aError), aError, );
 
   if (!mDocShell) {
-    return NS_OK;
+    return;
   }
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent window.sizeToContent() by exiting early
    */
 
   if (!CanMoveResizeWindows() || IsFrame()) {
-    return NS_OK;
+    return;
   }
 
   // The content viewer does a check to make sure that it's a content
   // viewer for a toplevel docshell.
   nsCOMPtr<nsIContentViewer> cv;
   mDocShell->GetContentViewer(getter_AddRefs(cv));
   nsCOMPtr<nsIMarkupDocumentViewer> markupViewer(do_QueryInterface(cv));
-  NS_ENSURE_TRUE(markupViewer, NS_ERROR_FAILURE);
+  if (!markupViewer) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   int32_t width, height;
-  NS_ENSURE_SUCCESS(markupViewer->GetContentSize(&width, &height),
-                    NS_ERROR_FAILURE);
+  aError = markupViewer->GetContentSize(&width, &height);
+  if (aError.Failed()) {
+    return;
+  }
 
   // Make sure the new size is following the CheckSecurityWidthAndHeight
   // rules.
   nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
-  NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
+  if (!treeOwner) {
+    aError.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
   CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height);
 
   nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
 
-  NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(mDocShell,
-                                           newDevSize.width, newDevSize.height),
-                    NS_ERROR_FAILURE);
-
-  return NS_OK;
+  aError = treeOwner->SizeShellTo(mDocShell, newDevSize.width,
+                                  newDevSize.height);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SizeToContent()
+{
+  ErrorResult rv;
+  SizeToContent(rv);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget **aWindowRoot)
 {
   nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
   return CallQueryInterface(root, aWindowRoot);
 }
@@ -6272,34 +6877,48 @@ nsGlobalWindow::ScrollByPages(int32_t nu
     // Perhaps Web content does too.
     sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
                  nsIScrollableFrame::INSTANT);
   }
 
   return NS_OK;
 }
 
+void
+nsGlobalWindow::ClearTimeout(int32_t aHandle, ErrorResult& aError)
+{
+  if (aHandle > 0) {
+    ClearTimeoutOrInterval(aHandle, aError);
+  }
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::ClearTimeout(int32_t aHandle)
 {
-  if (aHandle <= 0) {
-    return NS_OK;
-  }
-
-  return ClearTimeoutOrInterval(aHandle);
+  ErrorResult rv;
+  ClearTimeout(aHandle, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::ClearInterval(int32_t aHandle, ErrorResult& aError)
+{
+  if (aHandle > 0) {
+    ClearTimeoutOrInterval(aHandle, aError);
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::ClearInterval(int32_t aHandle)
 {
-  if (aHandle <= 0) {
-    return NS_OK;
-  }
-
-  return ClearTimeoutOrInterval(aHandle);
+  ErrorResult rv;
+  ClearTimeoutOrInterval(aHandle, rv);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetTimeout(int32_t *_retval)
 {
   return SetTimeoutOrInterval(false, _retval);
 }
 
@@ -6524,16 +7143,25 @@ nsGlobalWindow::FireAbuseEvents(bool aBl
   if (aBlocked) {
     FirePopupBlockedEvent(topDoc, this, popupURI, aPopupWindowName,
                           aPopupWindowFeatures);
   }
   if (aWindow)
     FirePopupWindowEvent(topDoc);
 }
 
+already_AddRefed<nsIDOMWindow>
+nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
+                     const nsAString& aOptions, ErrorResult& aError)
+{
+  nsCOMPtr<nsIDOMWindow> window;
+  aError = OpenJS(aUrl, aName, aOptions, getter_AddRefs(window));
+  return window.forget();
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
                      const nsAString& aOptions, nsIDOMWindow **_retval)
 {
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       true,           // aCalledNoScript
@@ -6595,16 +7223,44 @@ nsGlobalWindow::OpenNoNavigate(const nsA
                       false,          // aNavigate
                       nullptr, nullptr,  // No args
                       GetPrincipal(),    // aCalleePrincipal
                       nullptr,           // aJSCallerContext
                       _retval);
 
 }
 
+already_AddRefed<nsIDOMWindow>
+nsGlobalWindow::OpenDialog(JSContext* aCx, const nsAString& aUrl,
+                           const nsAString& aName, const nsAString& aOptions,
+                           const Sequence<JS::Value>& aExtraArgument,
+                           ErrorResult& aError)
+{
+  nsCOMPtr<nsIJSArgArray> argvArray;
+  aError = NS_CreateJSArgv(aCx, aExtraArgument.Length(),
+                           const_cast<JS::Value*>(aExtraArgument.Elements()),
+                           getter_AddRefs(argvArray));
+  if (aError.Failed()) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDOMWindow> dialog;
+  aError = OpenInternal(aUrl, aName, aOptions,
+                        true,             // aDialog
+                        false,            // aContentModal
+                        false,            // aCalledNoScript
+                        false,            // aDoJSFixups
+                        true,                // aNavigate
+                        argvArray, nullptr,  // Arguments
+                        GetPrincipal(),      // aCalleePrincipal
+                        aCx,                 // aJSCallerContext
+                        getter_AddRefs(dialog));
+  return dialog.forget();
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
                            const nsAString& aOptions, nsIDOMWindow** _retval)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
@@ -6642,27 +7298,34 @@ nsGlobalWindow::OpenDialog(const nsAStri
                       false,            // aDoJSFixups
                       true,                // aNavigate
                       argvArray, nullptr,  // Arguments
                       GetPrincipal(),      // aCalleePrincipal
                       cx,                  // aJSCallerContext
                       _retval);
 }
 
+already_AddRefed<nsIDOMWindow>
+nsGlobalWindow::GetFrames(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetFrames, (aError), aError, nullptr);
+
+  nsRefPtr<nsGlobalWindow> frames(this);
+  FlushPendingNotifications(Flush_ContentAndNotify);
+  return frames.forget();
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetFrames(nsIDOMWindow** aFrames)
 {
-  FORWARD_TO_OUTER(GetFrames, (aFrames), NS_ERROR_NOT_INITIALIZED);
-
-  *aFrames = this;
-  NS_ADDREF(*aFrames);
-
-  FlushPendingNotifications(Flush_ContentAndNotify);
-
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMWindow> frames = GetFrames(rv);
+  frames.forget(aFrames);
+
+  return rv.ErrorCode();
 }
 
 JSObject* nsGlobalWindow::CallerGlobal()
 {
   JSContext *cx = nsContentUtils::GetCurrentJSContext();
   if (!cx) {
     NS_ERROR("Please don't call this method from C++!");
 
@@ -7024,24 +7687,25 @@ PostMessageEvent::Run()
   nsEventDispatcher::Dispatch(static_cast<nsPIDOMWindow*>(mTargetWindow),
                               presContext,
                               internalEvent,
                               message,
                               &status);
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::PostMessageMoz(const JS::Value& aMessage,
-                               const nsAString& aOrigin,
-                               const JS::Value& aTransfer,
-                               JSContext* aCx)
-{
-  FORWARD_TO_OUTER(PostMessageMoz, (aMessage, aOrigin, aTransfer, aCx),
-                   NS_ERROR_NOT_INITIALIZED);
+void
+nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                               const nsAString& aTargetOrigin,
+                               JS::Handle<JS::Value> aTransfer,
+                               ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(PostMessageMoz,
+                            (aCx, aMessage, aTargetOrigin, aTransfer, aError),
+                            aError, );
 
   //
   // Window.postMessage is an intentional subversion of the same-origin policy.
   // As such, this code must be particularly careful in the information it
   // exposes to calling code.
   //
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
   //
@@ -7064,52 +7728,59 @@ nsGlobalWindow::PostMessageMoz(const JS:
   else {
     // In case the global is not a window, it can be a sandbox, and the sandbox's
     // principal can be used for the security check.
     JSObject *global = CallerGlobal();
     NS_ASSERTION(global, "Why is there no global object?");
     JSCompartment *compartment = js::GetObjectCompartment(global);
     callerPrin = xpc::GetCompartmentPrincipal(compartment);
   }
-  if (!callerPrin)
-    return NS_OK;
+  if (!callerPrin) {
+    return;
+  }
 
   nsCOMPtr<nsIURI> callerOuterURI;
-  if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI))))
-    return NS_OK;
+  if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI)))) {
+    return;
+  }
 
   nsAutoString origin;
   if (callerOuterURI) {
     // if the principal has a URI, use that to generate the origin
     nsContentUtils::GetUTFOrigin(callerPrin, origin);
   }
   else if (callerInnerWin) {
     // otherwise use the URI of the document to generate origin
     nsCOMPtr<nsIDocument> doc = callerInnerWin->GetExtantDoc();
-    if (!doc)
-      return NS_OK;
+    if (!doc) {
+      return;
+    }
     callerOuterURI = doc->GetDocumentURI();
     // if the principal has a URI, use that to generate the origin
     nsContentUtils::GetUTFOrigin(callerOuterURI, origin);
   }
   else {
     // in case of a sandbox with a system principal origin can be empty
-    if (!nsContentUtils::IsSystemPrincipal(callerPrin))
-      return NS_OK;
+    if (!nsContentUtils::IsSystemPrincipal(callerPrin)) {
+      return;
+    }
   }
 
   // Convert the provided origin string into a URI for comparison purposes.
   // "*" indicates no specific origin is required.
   nsCOMPtr<nsIURI> providedOrigin;
-  if (!aOrigin.EqualsASCII("*")) {
-    if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin), aOrigin)))
-      return NS_ERROR_DOM_SYNTAX_ERR;
+  if (!aTargetOrigin.EqualsASCII("*")) {
+    if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin), aTargetOrigin))) {
+      aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      return;
+    }
     if (NS_FAILED(providedOrigin->SetUserPass(EmptyCString())) ||
-        NS_FAILED(providedOrigin->SetPath(EmptyCString())))
-      return NS_OK;
+        NS_FAILED(providedOrigin->SetPath(EmptyCString()))) {
+      return;
+    }
   }
 
   // Create and asynchronously dispatch a runnable which will handle actual DOM
   // event creation and dispatch.
   nsRefPtr<PostMessageEvent> event =
     new PostMessageEvent(nsContentUtils::IsCallerChrome() || !callerInnerWin
                          ? nullptr
                          : callerInnerWin->GetOuterWindowInternal(),
@@ -7121,27 +7792,63 @@ nsGlobalWindow::PostMessageMoz(const JS:
   // We *must* clone the data here, or the JS::Value could be modified
   // by script
   JSAutoStructuredCloneBuffer buffer;
   StructuredCloneInfo scInfo;
   scInfo.event = event;
   scInfo.window = this;
 
   nsIPrincipal* principal = GetPrincipal();
-  if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
-    return NS_ERROR_DOM_DATA_CLONE_ERR;
-
   JS::Rooted<JS::Value> message(aCx, aMessage);
   JS::Rooted<JS::Value> transfer(aCx, aTransfer);
-  if (!buffer.write(aCx, message, transfer, &kPostMessageCallbacks, &scInfo))
-    return NS_ERROR_DOM_DATA_CLONE_ERR;
+  if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)) ||
+      !buffer.write(aCx, message, transfer, &kPostMessageCallbacks,
+                    &scInfo)) {
+    aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
+    return;
+  }
 
   event->SetJSData(buffer);
 
-  return NS_DispatchToCurrentThread(event);
+  aError = NS_DispatchToCurrentThread(event);
+}
+
+void
+nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                               const nsAString& aTargetOrigin,
+                               const Optional<Sequence<JS::Value > >& aTransfer,
+                               ErrorResult& aError)
+{
+  JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
+  if (aTransfer.WasPassed()) {
+    const Sequence<JS::Value >& values = aTransfer.Value();
+    transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx,
+                                                            values.Length(),
+                                                            const_cast<JS::Value*>(values.Elements())));
+    if (transferArray.isNull()) {
+      aError.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return;
+    }
+  }
+
+  PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, aError);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::PostMessageMoz(const JS::Value& aMessage,
+                               const nsAString& aOrigin,
+                               const JS::Value& aTransfer,
+                               JSContext* aCx)
+{
+  JS::Rooted<JS::Value> message(aCx, aMessage);
+  JS::Rooted<JS::Value> transfer(aCx, aTransfer);
+  ErrorResult rv;
+  PostMessageMoz(aCx, message, aOrigin, transfer, rv);
+
+  return rv.ErrorCode();
 }
 
 class nsCloseEvent : public nsRunnable {
 
   nsRefPtr<nsGlobalWindow> mWindow;
   bool mIndirect;
 
   nsCloseEvent(nsGlobalWindow *aWindow, bool aIndirect)
@@ -7194,42 +7901,41 @@ nsGlobalWindow::CanClose()
     rv = cv->RequestWindowClose(&canClose);
     if (NS_SUCCEEDED(rv) && !canClose)
       return false;
   }
 
   return true;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::Close()
-{
-  FORWARD_TO_OUTER(Close, (), NS_ERROR_NOT_INITIALIZED);
+void
+nsGlobalWindow::Close(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(Close, (aError), aError, );
 
   if (!mDocShell || IsInModalState() ||
       (IsFrame() && !mDocShell->GetIsBrowserOrApp())) {
     // window.close() is called on a frame in a frameset, on a window
     // that's already closed, or on a window for which there's
     // currently a modal dialog open. Ignore such calls.
-
-    return NS_OK;
+    return;
   }
 
   if (mHavePendingClose) {
     // We're going to be closed anyway; do nothing since we don't want
     // to double-close
-    return NS_OK;
+    return;
   }
 
   if (mBlockScriptedClosingFlag)
   {
     // A script's popup has been blocked and we don't want
     // the window to be closed directly after this event,
     // so the user can see that there was a blocked popup.
-    return NS_OK;
+    return;
   }
 
   // Don't allow scripts from content to close non-app windows that were not
   // opened by script.
   if (!mDocShell->GetIsApp() &&
       !mHadOriginalOpener && !nsContentUtils::IsCallerChrome()) {
     bool allowClose = mAllowScriptsToClose ||
       Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
@@ -7237,42 +7943,52 @@ nsGlobalWindow::Close()
       // We're blocking the close operation
       // report localized error msg in JS console
       nsContentUtils::ReportToConsole(
           nsIScriptError::warningFlag,
           NS_LITERAL_CSTRING("DOM Window"), mDoc,  // Better name for the category?
           nsContentUtils::eDOM_PROPERTIES,
           "WindowCloseBlockedWarning");
 
-      return NS_OK;
-    }
-  }
-
-  if (!mInClose && !mIsClosed && !CanClose())
-    return NS_OK;
+      return;
+    }
+  }
+
+  if (!mInClose && !mIsClosed && !CanClose()) {
+    return;
+  }
 
   // Fire a DOM event notifying listeners that this window is about to
   // be closed. The tab UI code may choose to cancel the default
   // action for this event, if so, we won't actually close the window
   // (since the tab UI code will close the tab in stead). Sure, this
   // could be abused by content code, but do we care? I don't think
   // so...
 
   bool wasInClose = mInClose;
   mInClose = true;
 
   if (!DispatchCustomEvent("DOMWindowClose")) {
     // Someone chose to prevent the default action for this event, if
     // so, let's not close this window after all...
 
     mInClose = wasInClose;
-    return NS_OK;
-  }
-
-  return FinalClose();
+    return;
+  }
+
+  aError = FinalClose();
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Close()
+{
+  ErrorResult rv;
+  Close(rv);
+
+  return rv.ErrorCode();
 }
 
 nsresult
 nsGlobalWindow::ForceClose()
 {
   if (IsFrame() || !mDocShell) {
     // This may be a frame in a frameset, or a window that's already closed.
     // Ignore such calls.
@@ -7677,54 +8393,73 @@ nsGlobalWindow::CacheXBLPrototypeHandler
  * In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
  * window contained by an <iframe mozbrowser> or <iframe mozapp> has no frame
  * element (effectively treating a mozbrowser the same as a content/chrome
  * boundary).
  */
 NS_IMETHODIMP
 nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
 {
-  FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
-  *aFrameElement = NULL;
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMElement> frameElement = do_QueryInterface(GetFrameElement(rv));
+  if (rv.Failed()) {
+    return rv.ErrorCode();
+  }
+
+  frameElement.forget(aFrameElement);
+
+  return NS_OK;
+}
+
+Element*
+nsGlobalWindow::GetFrameElement(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (aError), aError, nullptr);
 
   if (!mDocShell || mDocShell->GetIsBrowserOrApp()) {
-    return NS_OK;
-  }
-
-  return GetFrameElement(aFrameElement);
+    return nullptr;
+  }
+
+  return GetRealFrameElement(aError);
+}
+
+Element*
+nsGlobalWindow::GetRealFrameElement(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetRealFrameElement, (aError), aError, nullptr);
+
+  if (!mDocShell) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDocShell> parent;
+  mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
+
+  if (!parent || parent == mDocShell) {
+    // We're at a chrome boundary, don't expose the chrome iframe
+    // element to content code.
+    return nullptr;
+  }
+
+  return mFrameElement;
 }
 
 /**
  * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
  * around GetRealFrameElement.
  */
 NS_IMETHODIMP
 nsGlobalWindow::GetRealFrameElement(nsIDOMElement** aFrameElement)
 {
-  FORWARD_TO_OUTER(GetRealFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
-
-  *aFrameElement = NULL;
-
-  if (!mDocShell) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIDocShell> parent;
-  mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
-
-  if (!parent || parent == mDocShell) {
-    // We're at a chrome boundary, don't expose the chrome iframe
-    // element to content code.
-    return NS_OK;
-  }
-
-  if (mFrameElement) {
-    CallQueryInterface(mFrameElement, aFrameElement);
-  }
-  return NS_OK;
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMElement> frameElement =
+    do_QueryInterface(GetRealFrameElement(rv));
+  frameElement.forget(aFrameElement);
+
+  return rv.ErrorCode();
 }
 
 // Helper for converting window.showModalDialog() options (list of ';'
 // separated name (:|=) value pairs) to a format that's parsable by
 // our normal window opening code.
 
 void
 ConvertDialogOptions(const nsAString& aOptions, nsAString& aResult)
@@ -7840,82 +8575,133 @@ ConvertDialogOptions(const nsAString& aO
     if (iter == end) {
       break;
     }
 
     iter++;
   }
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs_,
-                                const nsAString& aOptions, uint8_t aArgc,
-                                nsIVariant **aRetVal)
-{
-  FORWARD_TO_OUTER(ShowModalDialog, (aURI, aArgs_, aOptions, aArgc, aRetVal),
-                   NS_ERROR_NOT_INITIALIZED);
-
-  *aRetVal = nullptr;
-
-  if (Preferences::GetBool("dom.disable_window_showModalDialog", false))
-    return NS_ERROR_NOT_AVAILABLE;
-
-  // Per-spec the |arguments| parameter is supposed to pass through unmodified.
-  // However, XPConnect default-initializes variants to null, rather than
-  // undefined. Fix this up here.
-  nsCOMPtr<nsIVariant> aArgs = aArgs_;
-  if (aArgc < 1) {
-    aArgs = CreateVoidVariant();
-  }
+already_AddRefed<nsIVariant>
+nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
+                                const nsAString& aOptions, ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(ShowModalDialog,
+                            (aUrl, aArgument, aOptions, aError), aError,
+                            nullptr);
+
+  if (Preferences::GetBool("dom.disable_window_showModalDialog", false)) {
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
+  }
+
   nsRefPtr<DialogValueHolder> argHolder =
-    new DialogValueHolder(nsContentUtils::GetSubjectPrincipal(), aArgs);
+    new DialogValueHolder(nsContentUtils::GetSubjectPrincipal(), aArgument);
 
   // Before bringing up the window/dialog, unsuppress painting and flush
   // pending reflows.
   EnsureReflowFlushAndPaint();
 
   if (!AreDialogsEnabled()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
   }
 
   if (ShouldPromptToBlockDialogs() && !ConfirmDialogIfNeeded()) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
   }
 
   nsCOMPtr<nsIDOMWindow> dlgWin;
   nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
 
   ConvertDialogOptions(aOptions, options);
 
   options.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
 
   EnterModalState();
   uint32_t oldMicroTaskLevel = nsContentUtils::MicroTaskLevel();
   nsContentUtils::SetMicroTaskLevel(0);
-  nsresult rv = OpenInternal(aURI, EmptyString(), options,
-                             false,          // aDialog
-                             true,           // aContentModal
-                             true,           // aCalledNoScript
-                             true,           // aDoJSFixups
-                             true,           // aNavigate
-                             nullptr, argHolder, // args
-                             GetPrincipal(),     // aCalleePrincipal
-                             nullptr,            // aJSCallerContext
-                             getter_AddRefs(dlgWin));
+  aError = OpenInternal(aUrl, EmptyString(), options,
+                        false,          // aDialog
+                        true,           // aContentModal
+                        true,           // aCalledNoScript
+                        true,           // aDoJSFixups
+                        true,           // aNavigate
+                        nullptr, argHolder, // args
+                        GetPrincipal(),     // aCalleePrincipal
+                        nullptr,            // aJSCallerContext
+                        getter_AddRefs(dlgWin));
   nsContentUtils::SetMicroTaskLevel(oldMicroTaskLevel);
   LeaveModalState();
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (aError.Failed()) {
+    return nullptr;
+  }
 
   nsCOMPtr<nsIDOMModalContentWindow> dialog = do_QueryInterface(dlgWin);
-  if (dialog) {
-    rv = dialog->GetReturnValue(aRetVal);
-    MOZ_ASSERT(NS_SUCCEEDED(rv));
-  }
-
-  return NS_OK;
+  if (!dialog) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIVariant> retVal;
+  aError = dialog->GetReturnValue(getter_AddRefs(retVal));
+  MOZ_ASSERT(!aError.Failed());
+
+  return retVal.forget();
+}
+
+JS::Value
+nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
+                                const Optional<JS::Handle<JS::Value> >& aArgument,
+                                const nsAString& aOptions,
+                                ErrorResult& aError)
+{
+  nsCOMPtr<nsIVariant> args;
+  if (aArgument.WasPassed()) {
+    aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
+                                                      aArgument.Value().get(),
+                                                      getter_AddRefs(args));
+  } else {
+    args = CreateVoidVariant();
+  }
+
+  nsCOMPtr<nsIVariant> retVal = ShowModalDialog(aUrl, args, aOptions, aError);
+  if (aError.Failed()) {
+    return JS::UndefinedValue();
+  }
+
+  JS::Value result;
+  if (retVal) {
+    aError = nsContentUtils::XPConnect()->VariantToJS(aCx,
+                                                      FastGetGlobalJSObject(),
+                                                      retVal, &result);
+  } else {
+    result = JS::NullValue();
+  }
+  return result;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs_,
+                                const nsAString& aOptions, uint8_t aArgc,
+                                nsIVariant **aRetVal)
+{
+  // Per-spec the |arguments| parameter is supposed to pass through unmodified.
+  // However, XPConnect default-initializes variants to null, rather than
+  // undefined. Fix this up here.
+  nsCOMPtr<nsIVariant> aArgs = aArgs_;
+  if (aArgc < 1) {
+    aArgs = CreateVoidVariant();
+  }
+
+  ErrorResult rv;
+  nsCOMPtr<nsIVariant> retVal = ShowModalDialog(aURI, aArgs, aOptions, rv);
+  retVal.forget(aRetVal);
+
+  return rv.ErrorCode();
 }
 
 class CommandDispatcher : public nsRunnable
 {
 public:
   CommandDispatcher(nsIDOMXULCommandDispatcher* aDispatcher,
                     const nsAString& aAction)
   : mDispatcher(aDispatcher), mAction(aAction) {}
@@ -7947,61 +8733,70 @@ nsGlobalWindow::UpdateCommands(const nsA
       nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher,
                                                             anAction));
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetSelection(nsISelection** aSelection)
-{
-  FORWARD_TO_OUTER(GetSelection, (aSelection), NS_ERROR_NOT_INITIALIZED);
-
-  NS_ENSURE_ARG_POINTER(aSelection);
-  *aSelection = nullptr;
-
-  if (!mDocShell)
-    return NS_OK;
+nsISelection*
+nsGlobalWindow::GetSelection(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetSelection, (aError), aError, nullptr);
+
+  if (!mDocShell) {
+    return nullptr;
+  }
 
   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
-
-  if (!presShell)
-    return NS_OK;
+  if (!presShell) {
+    return nullptr;
+  }
     
-  *aSelection = presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
-  
-  NS_IF_ADDREF(*aSelection);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::Find(const nsAString& aStr, bool aCaseSensitive,
+  return presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetSelection(nsISelection** aSelection)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsISelection> selection = GetSelection(rv);
+  selection.forget(aSelection);
+
+  return rv.ErrorCode();
+}
+
+bool
+nsGlobalWindow::Find(const nsAString& aString, bool aCaseSensitive,
                      bool aBackwards, bool aWrapAround, bool aWholeWord,
                      bool aSearchInFrames, bool aShowDialog,
-                     bool *aDidFind)
-{
-  if (Preferences::GetBool("dom.disable_window_find", false))
-    return NS_ERROR_NOT_AVAILABLE;
-
-  FORWARD_TO_OUTER(Find, (aStr, aCaseSensitive, aBackwards, aWrapAround,
-                          aWholeWord, aSearchInFrames, aShowDialog, aDidFind),
-                   NS_ERROR_NOT_INITIALIZED);
-
-  nsresult rv = NS_OK;
-  *aDidFind = false;
+                     ErrorResult& aError)
+{
+  if (Preferences::GetBool("dom.disable_window_find", false)) {
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return false;
+  }
+
+  FORWARD_TO_OUTER_OR_THROW(Find,
+                            (aString, aCaseSensitive, aBackwards, aWrapAround,
+                             aWholeWord, aSearchInFrames, aShowDialog, aError),
+                            aError, false);
 
   nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell));
-  NS_ENSURE_TRUE(finder, NS_ERROR_FAILURE);
+  if (!finder) {
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return false;
+  }
 
   // Set the options of the search
-  rv = finder->SetSearchString(PromiseFlatString(aStr).get());
-  NS_ENSURE_SUCCESS(rv, rv);
+  aError = finder->SetSearchString(PromiseFlatString(aString).get());
+  if (aError.Failed()) {
+    return false;
+  }
   finder->SetMatchCase(aCaseSensitive);
   finder->SetFindBackwards(aBackwards);
   finder->SetWrapFind(aWrapAround);
   finder->SetEntireWord(aWholeWord);
   finder->SetSearchFrames(aSearchInFrames);
 
   // the nsIWebBrowserFind is initialized to use this window
   // as the search root, but uses focus to set the current search
@@ -8009,61 +8804,94 @@ nsGlobalWindow::Find(const nsAString& aS
   // should be the current search frame.
   nsCOMPtr<nsIWebBrowserFindInFrames> framesFinder(do_QueryInterface(finder));
   if (framesFinder) {
     framesFinder->SetRootSearchFrame(this);   // paranoia
     framesFinder->SetCurrentSearchFrame(this);
   }
   
   // The Find API does not accept empty strings. Launch the Find Dialog.
-  if (aStr.IsEmpty() || aShowDialog) {
+  if (aString.IsEmpty() || aShowDialog) {
     // See if the find dialog is already up using nsIWindowMediator
     nsCOMPtr<nsIWindowMediator> windowMediator =
       do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
 
     nsCOMPtr<nsIDOMWindow> findDialog;
 
     if (windowMediator) {
       windowMediator->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
                                           getter_AddRefs(findDialog));
     }
 
     if (findDialog) {
       // The Find dialog is already open, bring it to the top.
-      rv = findDialog->Focus();
-    } else { // Open a Find dialog
-      if (finder) {
-        nsCOMPtr<nsIDOMWindow> dialog;
-        rv = OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
-                        NS_LITERAL_STRING("_blank"),
-                        NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
-                        finder, getter_AddRefs(dialog));
-      }
-    }
-  } else {
-    // Launch the search with the passed in search string
-    rv = finder->FindNext(aDidFind);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  return rv;
+      aError = findDialog->Focus();
+    } else if (finder) {
+      // Open a Find dialog
+      nsCOMPtr<nsIDOMWindow> dialog;
+      aError = OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
+                          NS_LITERAL_STRING("_blank"),
+                          NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
+                          finder, getter_AddRefs(dialog));
+    }
+
+    return false;
+  }
+
+  // Launch the search with the passed in search string
+  bool didFind = false;
+  aError = finder->FindNext(&didFind);
+  return didFind;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::Find(const nsAString& aStr, bool aCaseSensitive,
+                     bool aBackwards, bool aWrapAround, bool aWholeWord,
+                     bool aSearchInFrames, bool aShowDialog,
+                     bool *aDidFind)
+{
+  ErrorResult rv;
+  *aDidFind = Find(aStr, aCaseSensitive, aBackwards, aWrapAround, aWholeWord,
+                   aSearchInFrames, aShowDialog, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Atob(const nsAString& aAsciiBase64String,
+                     nsAString& aBinaryData, ErrorResult& aError)
+{
+  aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Atob(const nsAString& aAsciiBase64String,
                      nsAString& aBinaryData)
 {
-  return nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
+  ErrorResult rv;
+  Atob(aAsciiBase64String, aBinaryData, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::Btoa(const nsAString& aBinaryData,
+                     nsAString& aAsciiBase64String, ErrorResult& aError)
+{
+  aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Btoa(const nsAString& aBinaryData,
                      nsAString& aAsciiBase64String)
 {
-  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
+  ErrorResult rv;
+  Btoa(aBinaryData, aAsciiBase64String, rv);
+
+  return rv.ErrorCode();
 }
 
 //*****************************************************************************
 // nsGlobalWindow::nsIDOMEventTarget
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindow::RemoveEventListener(const nsAString& aType,
@@ -8286,34 +9114,36 @@ nsGlobalWindow::GetPrivateRoot()
       }
     }
   }
 
   return static_cast<nsGlobalWindow*>(top.get());
 }
 
 
-NS_IMETHODIMP
-nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation)
-{
-  FORWARD_TO_INNER(GetLocation, (aLocation), NS_ERROR_NOT_INITIALIZED);
-
-  *aLocation = nullptr;
+nsIDOMLocation*
+nsGlobalWindow::GetLocation(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetLocation, (aError), aError, nullptr);
 
   nsIDocShell *docShell = GetDocShell();
   if (!mLocation && docShell) {
     mLocation = new nsLocation(docShell);
-    if (!mLocation) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_IF_ADDREF(*aLocation = mLocation);
-
-  return NS_OK;
+  }
+  return mLocation;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMLocation> location = GetLocation(rv);
+  location.forget(aLocation);
+
+  return rv.ErrorCode();
 }
 
 void
 nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
 {
   // Set / unset mIsActive on the top level window, which is used for the
   // :-moz-window-inactive pseudoclass, and its sheet (if any).
   nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
@@ -8883,105 +9713,125 @@ nsGlobalWindow::UpdateCanvasFocus(bool a
           nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
           if (canvasFrame) {
               canvasFrame->SetHasFocus(false);
           }
       }
   }
 }
 
+already_AddRefed<nsICSSDeclaration>
+nsGlobalWindow::GetComputedStyle(Element& aElt, const nsAString& aPseudoElt,
+                                 ErrorResult& aError)
+{
+  return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetComputedStyle(nsIDOMElement* aElt,
                                  const nsAString& aPseudoElt,
                                  nsIDOMCSSStyleDeclaration** aReturn)
 {
   return GetComputedStyleHelper(aElt, aPseudoElt, false, aReturn);
 }
 
+already_AddRefed<nsICSSDeclaration>
+nsGlobalWindow::GetDefaultComputedStyle(Element& aElt,
+                                        const nsAString& aPseudoElt,
+                                        ErrorResult& aError)
+{
+  return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetDefaultComputedStyle(nsIDOMElement* aElt,
                                         const nsAString& aPseudoElt,
                                         nsIDOMCSSStyleDeclaration** aReturn)
 {
   return GetComputedStyleHelper(aElt, aPseudoElt, true, aReturn);
 }
 
 nsresult
 nsGlobalWindow::GetComputedStyleHelper(nsIDOMElement* aElt,
                                        const nsAString& aPseudoElt,
                                        bool aDefaultStylesOnly,
                                        nsIDOMCSSStyleDeclaration** aReturn)
 {
-  FORWARD_TO_OUTER(GetComputedStyleHelper, (aElt, aPseudoElt,
-                                            aDefaultStylesOnly, aReturn),
-                   NS_ERROR_NOT_INITIALIZED);
-
   NS_ENSURE_ARG_POINTER(aReturn);
   *aReturn = nullptr;
 
-  if (!aElt) {
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
+  if (!element) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMCSSStyleDeclaration> declaration =
+    GetComputedStyleHelper(*element, aPseudoElt, aDefaultStylesOnly, rv);
+  declaration.forget(aReturn);
+
+  return rv.ErrorCode();
+}
+
+already_AddRefed<nsICSSDeclaration>
+nsGlobalWindow::GetComputedStyleHelper(Element& aElt,
+                                       const nsAString& aPseudoElt,
+                                       bool aDefaultStylesOnly,
+                                       ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelper,
+                            (aElt, aPseudoElt, aDefaultStylesOnly, aError),
+                            aError, nullptr);
+
   if (!mDocShell) {
-    return NS_OK;
+    return nullptr;
   }
 
   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (!presShell) {
     // Try flushing frames on our parent in case there's a pending
     // style change that will create the presshell.
     nsGlobalWindow *parent =
       static_cast<nsGlobalWindow *>(GetPrivateParent());
     if (!parent) {
-      return NS_OK;
+      return nullptr;
     }
 
     parent->FlushPendingNotifications(Flush_Frames);
 
     // Might have killed mDocShell
     if (!mDocShell) {
-      return NS_OK;
+      return nullptr;
     }
 
     presShell = mDocShell->GetPresShell();
     if (!presShell) {
-      return NS_OK;
-    }
-  }
-
-  nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
-  NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
+      return nullptr;
+    }
+  }
+
   nsRefPtr<nsComputedDOMStyle> compStyle =
-    NS_NewComputedDOMStyle(element, aPseudoElt, presShell,
+    NS_NewComputedDOMStyle(&aElt, aPseudoElt, presShell,
                            aDefaultStylesOnly ? nsComputedDOMStyle::eDefaultOnly :
                                                 nsComputedDOMStyle::eAll);
 
-  *aReturn = compStyle.forget().get();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
-{
-  FORWARD_TO_INNER(GetSessionStorage, (aSessionStorage), NS_ERROR_UNEXPECTED);
+  return compStyle.forget();
+}
+
+nsIDOMStorage*
+nsGlobalWindow::GetSessionStorage(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetSessionStorage, (aError), aError, nullptr);
 
   nsIPrincipal *principal = GetPrincipal();
   nsIDocShell* docShell = GetDocShell();
 
-  if (!principal || !docShell) {
-    *aSessionStorage = nullptr;
-    return NS_OK;
-  }
-
-  if (!Preferences::GetBool(kStorageEnabled)) {
-    *aSessionStorage = nullptr;
-    return NS_OK;
+  if (!principal || !docShell || !Preferences::GetBool(kStorageEnabled)) {
+    return nullptr;
   }
 
   if (mSessionStorage) {
 #ifdef PR_LOGGING
     if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
       PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage.get());
     }
 #endif
@@ -8993,132 +9843,155 @@ nsGlobalWindow::GetSessionStorage(nsIDOM
                    "that could not be accessed!");
       if (!canAccess) {
         mSessionStorage = nullptr;
       }
     }
   }
 
   if (!mSessionStorage) {
-    *aSessionStorage = nullptr;
-
     nsString documentURI;
     if (mDoc) {
       mDoc->GetDocumentURI(documentURI);
     }
 
     // If the document has the sandboxed origin flag set
     // don't allow access to sessionStorage.
     if (!mDoc) {
-      return NS_ERROR_FAILURE;
+      aError.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
 
     if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
-      return NS_ERROR_DOM_SECURITY_ERR;
+      aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return nullptr;
     }
 
     nsresult rv;
 
     nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(docShell, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      aError.Throw(rv);
+      return nullptr;
+    }
 
     nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
 
-    rv = storageManager->CreateStorage(principal,
-                                       documentURI,
-                                       loadContext && loadContext->UsePrivateBrowsing(),
-                                       getter_AddRefs(mSessionStorage));
-    NS_ENSURE_SUCCESS(rv, rv);
+    aError = storageManager->CreateStorage(principal,
+                                           documentURI,
+                                           loadContext && loadContext->UsePrivateBrowsing(),
+                                           getter_AddRefs(mSessionStorage));
+    if (aError.Failed()) {
+      return nullptr;
+    }
 
 #ifdef PR_LOGGING
     if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
       PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage.get());
     }
 #endif
 
     if (!mSessionStorage) {
-      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+      aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+      return nullptr;
     }
   }
 
 #ifdef PR_LOGGING
   if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
     PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage.get());
   }
 #endif
 
-  NS_ADDREF(*aSessionStorage = mSessionStorage);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
-{
-  FORWARD_TO_INNER(GetLocalStorage, (aLocalStorage), NS_ERROR_UNEXPECTED);
-
-  NS_ENSURE_ARG(aLocalStorage);
+  return mSessionStorage;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMStorage> storage = GetSessionStorage(rv);
+  storage.forget(aSessionStorage);
+
+  return rv.ErrorCode();
+}
+
+nsIDOMStorage*
+nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(GetLocalStorage, (aError), aError, nullptr);
 
   if (!Preferences::GetBool(kStorageEnabled)) {
-    *aLocalStorage = nullptr;
-    return NS_OK;
+    return nullptr;
   }
 
   if (!mLocalStorage) {
-    *aLocalStorage = nullptr;
-
-    nsresult rv;
-
     if (!DOMStorage::CanUseStorage()) {
-      return NS_ERROR_DOM_SECURITY_ERR;
+      aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return nullptr;
     }
 
     nsIPrincipal *principal = GetPrincipal();
     if (!principal) {
-      return NS_OK;
-    }
-
+      return nullptr;
+    }
+
+    nsresult rv;
     nsCOMPtr<nsIDOMStorageManager> storageManager =
       do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      aError.Throw(rv);
+      return nullptr;
+    }
 
     // If the document has the sandboxed origin flag set
     // don't allow access to localStorage.
     if (mDoc && (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
-      return NS_ERROR_DOM_SECURITY_ERR;
+      aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return nullptr;
     }
 
     nsString documentURI;
     if (mDoc) {
       mDoc->GetDocumentURI(documentURI);
     }
 
     nsIDocShell* docShell = GetDocShell();
     nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
 
-    rv = storageManager->CreateStorage(principal,
-                                       documentURI,
-                                       loadContext && loadContext->UsePrivateBrowsing(),
-                                       getter_AddRefs(mLocalStorage));
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  NS_ADDREF(*aLocalStorage = mLocalStorage);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGlobalWindow::GetIndexedDB(nsISupports** _retval)
+    aError = storageManager->CreateStorage(principal,
+                                           documentURI,
+                                           loadContext && loadContext->UsePrivateBrowsing(),
+                                           getter_AddRefs(mLocalStorage));
+  }
+
+  return mLocalStorage;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
+{
+  NS_ENSURE_ARG(aLocalStorage);
+
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMStorage> storage = GetLocalStorage(rv);
+  storage.forget(aLocalStorage);
+
+  return rv.ErrorCode();
+}
+
+indexedDB::IDBFactory*
+nsGlobalWindow::GetIndexedDB(ErrorResult& aError)
 {
   if (!mIndexedDB) {
-    nsresult rv;
-
     // If the document has the sandboxed origin flag set
     // don't allow access to indexedDB.
     if (mDoc && (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
-      return NS_ERROR_DOM_SECURITY_ERR;
+      aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return nullptr;
     }
 
     if (!IsChromeWindow()) {
       // Whitelist about:home, since it doesn't have a base domain it would not
       // pass the thirdPartyUtil check, though it should be able to use
       // indexedDB.
       bool skipThirdPartyCheck = false;
       nsIPrincipal *principal = GetPrincipal();
@@ -9131,39 +10004,48 @@ nsGlobalWindow::GetIndexedDB(nsISupports
           skipThirdPartyCheck = NS_SUCCEEDED(uri->GetPath(path)) &&
                                 path.EqualsLiteral("home");
         }
       }
 
       if (!skipThirdPartyCheck) {
         nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
           do_GetService(THIRDPARTYUTIL_CONTRACTID);
-        NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+        if (!thirdPartyUtil) {
+          aError.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+          return nullptr;
+        }
 
         bool isThirdParty;
-        rv = thirdPartyUtil->IsThirdPartyWindow(this, nullptr, &isThirdParty);
-        NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-        if (isThirdParty) {
-          NS_WARNING("IndexedDB is not permitted in a third-party window.");
-          *_retval = nullptr;
-          return NS_OK;
+        aError = thirdPartyUtil->IsThirdPartyWindow(this, nullptr,
+                                                    &isThirdParty);
+        if (aError.Failed() || isThirdParty) {
+          NS_WARN_IF_FALSE(aError.Failed(),
+                           "IndexedDB is not permitted in a third-party window.");
+          return nullptr;
         }
       }
     }
 
     // This may be null if being created from a file.
-    rv = indexedDB::IDBFactory::Create(this, nullptr,
-                                       getter_AddRefs(mIndexedDB));
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  nsCOMPtr<nsISupports> request(mIndexedDB);
+    aError = indexedDB::IDBFactory::Create(this, nullptr,
+                                           getter_AddRefs(mIndexedDB));
+  }
+
+  return mIndexedDB;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetIndexedDB(nsISupports** _retval)
+{
+  ErrorResult rv;
+  nsCOMPtr<nsISupports> request(GetIndexedDB(rv));
   request.forget(_retval);
-  return NS_OK;
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozIndexedDB(nsISupports** _retval)
 {
   return GetIndexedDB(_retval);
 }
 
@@ -10293,16 +11175,108 @@ nsGlobalWindow::OpenInternal(const nsASt
 }
 
 //*****************************************************************************
 // nsGlobalWindow: Timeout Functions
 //*****************************************************************************
 
 uint32_t sNestingLevel;
 
+nsGlobalWindow*
+nsGlobalWindow::InnerForSetTimeoutOrInterval(ErrorResult& aError)
+{
+  // This needs to forward to the inner window, but since the current
+  // inner may not be the inner in the calling scope, we need to treat
+  // this specially here as we don't want timeouts registered in a
+  // dying inner window to get registered and run on the current inner
+  // window. To get this right, we need to forward this call to the
+  // inner window that's calling window.setTimeout().
+
+  if (!IsOuterWindow()) {
+    return this;
+  }
+
+  nsGlobalWindow* callerInner = CallerInnerWindow();
+  if (!callerInner) {
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
+  }
+
+  // If the caller and the callee share the same outer window,
+  // forward to the caller inner. Else, we forward to the current
+  // inner (e.g. someone is calling setTimeout() on a reference to
+  // some other window).
+
+  if (callerInner->GetOuterWindow() == this &&
+      callerInner->IsInnerWindow()) {
+    return callerInner;
+  }
+
+  nsGlobalWindow* currentInner = GetCurrentInnerWindowInternal();
+  if (!currentInner) {
+    NS_WARNING("No inner window available!");
+    aError.Throw(NS_ERROR_NOT_INITIALIZED);
+    return nullptr;
+  }
+
+  return currentInner;
+}
+
+int32_t
+nsGlobalWindow::SetTimeout(JSContext* aCx, Function& aFunction,
+                           int32_t aTimeout,
+                           const Sequence<JS::Value>& aArguments,
+                           ErrorResult& aError)
+{
+  return SetTimeoutOrInterval(aFunction, aTimeout, aArguments, false, aError);
+}
+
+int32_t
+nsGlobalWindow::SetTimeout(JSContext* aCx, const nsAString& aHandler,
+                           int32_t aTimeout, ErrorResult& aError)
+{
+  return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
+}
+
+static bool
+IsInterval(const Optional<int32_t>& aTimeout, int32_t& aResultTimeout)
+{
+  if (aTimeout.WasPassed()) {
+    aResultTimeout = aTimeout.Value();
+    return true;
+  }
+
+  // If no interval was specified, treat this like a timeout, to avoid setting
+  // an interval of 0 milliseconds.
+  aResultTimeout = 0;
+  return false;
+}
+
+int32_t
+nsGlobalWindow::SetInterval(JSContext* aCx, Function& aFunction,
+                            const Optional<int32_t>& aTimeout,
+                            const Sequence<JS::Value>& aArguments,
+                            ErrorResult& aError)
+{
+  int32_t timeout;
+  bool isInterval = IsInterval(aTimeout, timeout);
+  return SetTimeoutOrInterval(aFunction, timeout, aArguments, isInterval,
+                              aError);
+}
+
+int32_t
+nsGlobalWindow::SetInterval(JSContext* aCx, const nsAString& aHandler,
+                            const Optional<int32_t>& aTimeout,
+                            ErrorResult& aError)
+{
+  int32_t timeout;
+  bool isInterval = IsInterval(aTimeout, timeout);
+  return SetTimeoutOrInterval(aCx, aHandler, timeout, isInterval, aError);
+}
+
 nsresult
 nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
                                      int32_t interval,
                                      bool aIsInterval, int32_t *aReturn)
 {
   FORWARD_TO_INNER(SetTimeoutOrInterval, (aHandler, interval, aIsInterval, aReturn),
                    NS_ERROR_NOT_INITIALIZED);
 
@@ -10468,22 +11442,76 @@ nsGlobalWindow::SetTimeoutOrInterval(boo
 
   int32_t interval = 0;
   bool isInterval = aIsInterval;
   nsCOMPtr<nsIScriptTimeoutHandler> handler;
   nsresult rv = NS_CreateJSTimeoutHandler(this,
                                           &isInterval,
                                           &interval,
                                           getter_AddRefs(handler));
-  if (NS_FAILED(rv))
-    return (rv == NS_ERROR_DOM_TYPE_ERR) ? NS_OK : rv;
+  if (!handler) {
+    *aReturn = 0;
+    return rv;
+  }
 
   return SetTimeoutOrInterval(handler, interval, isInterval, aReturn);
 }
 
+int32_t
+nsGlobalWindow::SetTimeoutOrInterval(Function& aFunction, int32_t aTimeout,
+                                     const Sequence<JS::Value>& aArguments,
+                                     bool aIsInterval, ErrorResult& aError)
+{
+  nsGlobalWindow* inner = InnerForSetTimeoutOrInterval(aError);
+  if (aError.Failed()) {
+    return 0;
+  }
+
+  if (inner != this) {
+    return inner->SetTimeoutOrInterval(aFunction, aTimeout, aArguments,
+                                       aIsInterval, aError);
+  }
+
+  nsCOMPtr<nsIScriptTimeoutHandler> handler =
+    NS_CreateJSTimeoutHandler(this, aFunction, aArguments, aError);
+  if (!handler) {
+    return 0;
+  }
+
+  int32_t result;
+  aError = SetTimeoutOrInterval(handler, aTimeout, aIsInterval, &result);
+  return result;
+}
+
+int32_t
+nsGlobalWindow::SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
+                                     int32_t aTimeout, bool aIsInterval,
+                                     ErrorResult& aError)
+{
+  nsGlobalWindow* inner = InnerForSetTimeoutOrInterval(aError);
+  if (aError.Failed()) {
+    return 0;
+  }
+
+  if (inner != this) {
+    return inner->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval,
+                                       aError);
+  }
+
+  nsCOMPtr<nsIScriptTimeoutHandler> handler =
+    NS_CreateJSTimeoutHandler(aCx, this, aHandler, aError);
+  if (!handler) {
+    return 0;
+  }
+
+  int32_t result;
+  aError = SetTimeoutOrInterval(handler, aTimeout, aIsInterval, &result);
+  return result;
+}
+
 bool
 nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
                                   nsIScriptContext* aScx)
 {
   // Hold on to the timeout in case mExpr or mFunObj releases its
   // doc.
   nsRefPtr<nsTimeout> timeout = aTimeout;
   nsTimeout* last_running_timeout = mRunningTimeout;
@@ -10807,20 +11835,21 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
   // Take the dummy timeout off the head of the list
   dummy_timeout->remove();
   dummy_timeout->Release();
   MOZ_ASSERT(dummy_timeout->HasRefCntOne(), "dummy_timeout may leak");
 
   mTimeoutInsertionPoint = last_insertion_point;
 }
 
-nsresult
-nsGlobalWindow::ClearTimeoutOrInterval(int32_t aTimerID)
-{
-  FORWARD_TO_INNER(ClearTimeoutOrInterval, (aTimerID), NS_ERROR_NOT_INITIALIZED);
+void
+nsGlobalWindow::ClearTimeoutOrInterval(int32_t aTimerID, ErrorResult& aError)
+{
+  FORWARD_TO_INNER_OR_THROW(ClearTimeoutOrInterval, (aTimerID, aError),
+                            aError, );
 
   uint32_t public_id = (uint32_t)aTimerID;
   nsTimeout *timeout;
 
   for (timeout = mTimeouts.getFirst(); timeout; timeout = timeout->getNext()) {
     if (timeout->mPublicId == public_id) {
       if (timeout->mRunning) {
         /* We're running from inside the timeout. Mark this
@@ -10837,18 +11866,16 @@ nsGlobalWindow::ClearTimeoutOrInterval(i
           timeout->mTimer = nullptr;
           timeout->Release();
         }
         timeout->Release();
       }
       break;
     }
   }
-
-  return NS_OK;
 }
 
 nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
 {
   FORWARD_TO_INNER(ResetTimersForNonBackgroundWindow, (),
                    NS_ERROR_NOT_INITIALIZED);
 
   if (IsFrozen() || mTimeoutsSuspendDepth) {
@@ -11531,52 +12558,69 @@ nsGlobalWindow::EnableTimeChangeNotifica
 }
 
 void
 nsGlobalWindow::DisableTimeChangeNotifications()
 {
   nsSystemTimeChangeObserver::RemoveWindowListener(this);
 }
 
-static size_t
-SizeOfEventTargetObjectsEntryExcludingThisFun(
+static PLDHashOperator
+CollectSizeAndListenerCount(
   nsPtrHashKey<nsDOMEventTargetHelper> *aEntry,
-  MallocSizeOf aMallocSizeOf,
   void *arg)
 {
-  nsISupports *supports = aEntry->GetKey();
-  nsCOMPtr<nsISizeOfEventTarget> iface = do_QueryInterface(supports);
-  return iface ? iface->SizeOfEventTargetIncludingThis(aMallocSizeOf) : 0;
+  nsWindowSizes* windowSizes = static_cast<nsWindowSizes*>(arg);
+
+  nsDOMEventTargetHelper* et = aEntry->GetKey();
+
+  if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
+    windowSizes->mDOMEventTargetsSize +=
+      iSizeOf->SizeOfEventTargetIncludingThis(windowSizes->mMallocSizeOf);
+  }
+
+  if (nsEventListenerManager* elm = et->GetExistingListenerManager()) {
+    windowSizes->mDOMEventListenersCount += elm->ListenerCount();
+  }
+
+  return PL_DHASH_NEXT;
 }
 
 void
 nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
-  aWindowSizes->mDOMOther += aWindowSizes->mMallocSizeOf(this);
+  aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
 
   if (IsInnerWindow()) {
     nsEventListenerManager* elm = GetExistingListenerManager();
     if (elm) {
-      aWindowSizes->mDOMOther +=
+      aWindowSizes->mDOMOtherSize +=
         elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
+      aWindowSizes->mDOMEventListenersCount +=
+        elm->ListenerCount();
     }
     if (mDoc) {
       mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
     }
   }
 
   if (mNavigator) {
-    aWindowSizes->mDOMOther +=
+    aWindowSizes->mDOMOtherSize +=
       mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
   }
 
-  aWindowSizes->mDOMEventTargets +=
-    mEventTargetObjects.SizeOfExcludingThis(
-      SizeOfEventTargetObjectsEntryExcludingThisFun,
-      aWindowSizes->mMallocSizeOf);
+  // The things pointed to by the entries will be measured below, so we
+  // use nullptr for the callback here.
+  aWindowSizes->mDOMEventTargetsSize +=
+    mEventTargetObjects.SizeOfExcludingThis(nullptr,
+                                            aWindowSizes->mMallocSizeOf);
+  aWindowSizes->mDOMEventTargetsCount +=
+    const_cast<nsTHashtable<nsPtrHashKey<nsDOMEventTargetHelper> >*>
+      (&mEventTargetObjects)->EnumerateEntries(CollectSizeAndListenerCount,
+                                               aWindowSizes);
 }
 
 
 #ifdef MOZ_GAMEPAD
 void
 nsGlobalWindow::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
 {
   FORWARD_TO_INNER_VOID(AddGamepad, (aIndex, aGamepad));
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -41,17 +41,16 @@
 #include "nsFrameMessageManager.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIInlineEventHandlers.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
 #include "nsIDocument.h"
 #include "nsIDOMTouchEvent.h"
-
 #include "mozilla/dom/EventTarget.h"
 #include "Units.h"
 #include "nsComponentManagerUtils.h"
 
 #ifdef MOZ_B2G
 #include "nsIDOMWindowB2G.h"
 #endif // MOZ_B2G
 
@@ -74,16 +73,17 @@
 #define MAX_IDLE_FUZZ_TIME_MS 90000
 
 // Min idle notification time in seconds.
 #define MIN_IDLE_NOTIFICATION_TIME_S 1
 
 class nsIArray;
 class nsIBaseWindow;
 class nsIContent;
+class nsICSSDeclaration;
 class nsIDocShellTreeOwner;
 class nsIDOMCrypto;
 class nsIDOMOfflineResourceList;
 class nsIDOMMozWakeLock;
 class nsIScrollableFrame;
 class nsIControllers;
 class nsIScriptContext;
 class nsIScriptTimeoutHandler;
@@ -101,31 +101,43 @@ class nsIIdleService;
 struct nsIntSize;
 struct nsRect;
 
 class nsWindowSizes;
 
 namespace mozilla {
 namespace dom {
 class BarProp;
+class Function;
 class Gamepad;
 class Navigator;
 class SpeechSynthesis;
 namespace indexedDB {
 class IDBFactory;
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
 
 extern nsresult
 NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
                           bool *aIsInterval,
                           int32_t *aInterval,
                           nsIScriptTimeoutHandler **aRet);
 
+extern already_AddRefed<nsIScriptTimeoutHandler>
+NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
+                          mozilla::dom::Function& aFunction,
+                          const mozilla::dom::Sequence<JS::Value>& aArguments,
+                          mozilla::ErrorResult& aError);
+
+extern already_AddRefed<nsIScriptTimeoutHandler>
+NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
+                          const nsAString& aExpression,
+                          mozilla::ErrorResult& aError);
+
 /*
  * Timeout struct that holds information about each script
  * timeout.  Holds a strong reference to an nsIScriptTimeoutHandler, which
  * abstracts the language specific cruft.
  */
 struct nsTimeout : mozilla::LinkedListElement<nsTimeout>
 {
   nsTimeout();
@@ -301,17 +313,16 @@ class nsGlobalWindow : public mozilla::d
 #endif // MOZ_B2G
 #ifdef MOZ_WEBSPEECH
                      , public nsISpeechSynthesisGetter
 #endif // MOZ_WEBSPEECH
 {
 public:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
-  typedef mozilla::dom::Navigator Navigator;
   typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
 
   // public methods
   nsPIDOMWindow* GetPrivateParent();
   // callback for close event
   void ReallyCloseWindow();
 
   // nsISupports
@@ -451,34 +462,28 @@ public:
   virtual NS_HIDDEN_(nsresult) SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust);
 
   virtual NS_HIDDEN_(void) SetHasGamepadEventListener(bool aHasGamepad = true);
 
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // WebIDL interface.
-  uint32_t GetLength();
   already_AddRefed<nsIDOMWindow> IndexedGetter(uint32_t aIndex, bool& aFound);
 
   void GetSupportedNames(nsTArray<nsString>& aNames);
 
   // Object Management
   nsGlobalWindow(nsGlobalWindow *aOuterWindow);
 
   static nsGlobalWindow *FromSupports(nsISupports *supports)
   {
     // Make sure this matches the casts we do in QueryInterface().
     return (nsGlobalWindow *)(mozilla::dom::EventTarget *)supports;
   }
-  static nsISupports *ToSupports(nsGlobalWindow *win)
-  {
-    // Make sure this matches the casts we do in QueryInterface().
-    return (nsISupports *)(mozilla::dom::EventTarget *)win;
-  }
   static nsGlobalWindow *FromWrapper(nsIXPConnectWrappedNative *wrapper)
   {
     return FromSupports(wrapper->Native());
   }
 
   /**
    * Wrap nsIDOMWindow::GetTop so we can overload the inline GetTop()
    * implementation below.  (nsIDOMWindow::GetTop simply calls
@@ -497,20 +502,17 @@ public:
       return static_cast<nsGlobalWindow *>(top.get());
     return nullptr;
   }
 
   inline nsGlobalWindow* GetScriptableTop()
   {
     nsCOMPtr<nsIDOMWindow> top;
     GetScriptableTop(getter_AddRefs(top));
-    if (top) {
-      return static_cast<nsGlobalWindow *>(top.get());
-    }
-    return nullptr;
+    return static_cast<nsGlobalWindow *>(top.get());
   }
 
   already_AddRefed<nsIDOMWindow> GetChildWindow(const nsAString& aName);
 
   // These return true if we've reached the state in this top level window
   // where we ask the user if further dialogs should be blocked.
   //
   // DialogsAreBeingAbused must be called on the scriptable top inner window.
@@ -756,21 +758,187 @@ public:
 #define TOUCH_EVENT EVENT