merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 17 Mar 2016 11:00:17 +0100
changeset 289131 fefe2bc3e54fa101dc12e2858546ab5df2ee6d20
parent 289020 fd250005129607b930f96c843c6b36710abbf692 (current diff)
parent 289130 4b3b0c66d13269c9adb00dd2cc11bcecbee6c46e (diff)
child 289132 f4095779c96f0a10f6fc659d013458506e95cfa9
child 289140 35c021424684c717b5ad2206a4209872688f794e
child 289209 dfc0c1ef423373073f1d98801329414bed340bff
push id30096
push usercbook@mozilla.com
push dateThu, 17 Mar 2016 10:00:34 +0000
treeherdermozilla-central@fefe2bc3e54f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone48.0a1
first release with
nightly linux32
fefe2bc3e54f / 48.0a1 / 20160317030235 / files
nightly linux64
fefe2bc3e54f / 48.0a1 / 20160317030235 / files
nightly mac
fefe2bc3e54f / 48.0a1 / 20160317030235 / files
nightly win32
fefe2bc3e54f / 48.0a1 / 20160317030235 / files
nightly win64
fefe2bc3e54f / 48.0a1 / 20160317030235 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
browser/components/extensions/test/browser/browser.ini
dom/base/nsDocument.cpp
dom/media/webaudio/test/chrome.ini
dom/workers/Location.cpp
dom/workers/Location.h
layout/style/test/chrome/additional_sheets_helper.html
layout/style/test/chrome/test_addSheet.html
layout/style/test/chrome/test_additional_sheets.html
old-configure.in
testing/firefox-ui/harness/firefox_ui_harness/decorators.py
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -38,17 +38,17 @@ LOCAL_INCLUDES += [
     '/accessible/ipc',
     '/accessible/xpcom',
     '/accessible/xul',
     '/other-licenses/atk-1.0',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     CFLAGS += CONFIG['TK_CFLAGS']
     CXXFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['MOZ_ENABLE_DBUS']:
     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -68,32 +68,30 @@ LOCAL_INCLUDES += [
     '/ipc/chromium/src',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
     '/layout/xul',
     '/layout/xul/tree/',
 ]
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     LOCAL_INCLUDES += [
         '/accessible/atk',
     ]
+    CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
         '/accessible/windows/ia2',
         '/accessible/windows/msaa',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     LOCAL_INCLUDES += [
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['MOZ_ENABLE_GTK']:
-    CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
-
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/accessible/generic/moz.build
+++ b/accessible/generic/moz.build
@@ -31,17 +31,17 @@ LOCAL_INCLUDES += [
     '/accessible/ipc',
     '/accessible/xpcom',
     '/accessible/xul',
     '/dom/base',
     '/layout/generic',
     '/layout/xul',
 ]
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     LOCAL_INCLUDES += [
         '/accessible/atk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
         '/accessible/windows/ia2',
         '/accessible/windows/msaa',
     ]
--- a/accessible/html/moz.build
+++ b/accessible/html/moz.build
@@ -19,17 +19,17 @@ LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/xpcom',
     '/layout/generic',
     '/layout/tables',
     '/layout/xul',
 ]
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     LOCAL_INCLUDES += [
         '/accessible/atk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
         '/accessible/windows/ia2',
         '/accessible/windows/msaa',
     ]
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/moz.build
@@ -22,17 +22,17 @@ if CONFIG['ACCESSIBILITY']:
     ]
 
     LOCAL_INCLUDES += [
         '../base',
         '../generic',
         '../xpcom',
     ]
 
-    if CONFIG['MOZ_ENABLE_GTK']:
+    if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         LOCAL_INCLUDES += [
             '/accessible/atk',
         ]
     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
         LOCAL_INCLUDES += [
             '/accessible/windows/ia2',
             '/accessible/windows/msaa',
         ]
--- a/accessible/moz.build
+++ b/accessible/moz.build
@@ -1,17 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in toolkit:
     DIRS += ['atk']
 elif toolkit == 'windows':
     DIRS += ['windows']
 elif toolkit == 'cocoa':
     DIRS += ['mac']
 else:
     DIRS += ['other']
 
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -28,17 +28,17 @@ EXPORTS += [
     '!xpcAccEvents.h',
 ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
 ]
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     LOCAL_INCLUDES += [
         '/accessible/atk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
         '/accessible/windows/msaa',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
--- a/accessible/xul/moz.build
+++ b/accessible/xul/moz.build
@@ -24,17 +24,17 @@ LOCAL_INCLUDES += [
     '/accessible/generic',
     '/accessible/html',
     '/accessible/xpcom',
     '/layout/generic',
     '/layout/xul',
     '/layout/xul/tree',
 ]
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     LOCAL_INCLUDES += [
         '/accessible/atk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
         '/accessible/windows/ia2',
         '/accessible/windows/msaa',
     ]
--- a/b2g/branding/branding-common.mozbuild
+++ b/b2g/branding/branding-common.mozbuild
@@ -12,13 +12,12 @@ def B2GBranding():
         ]
     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
         BRANDING_FILES += [
             'app.icns',
             'background.png',
             'disk.icns',
             'dsstore',
         ]
-
-    if CONFIG['MOZ_WIDGET_GTK']:
+    elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         BRANDING_FILES += [
             'default.png',
         ]
new file mode 100644
--- /dev/null
+++ b/b2g/common.configure
@@ -0,0 +1,21 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Truetype fonts for B2G
+# ==============================================================
+option(env='MOZTTDIR', nargs=1, help='Path to truetype fonts for B2G')
+
+@depends('MOZTTDIR')
+def mozttdir(value):
+    if value:
+        path = value[0]
+        if not os.path.isdir(path):
+            error('MOZTTDIR "%s" is not a valid directory' % path)
+        set_config('MOZTTDIR', path)
+        set_define('PACKAGE_MOZTT', '1')
+
+
+include('../toolkit/moz.configure')
--- a/b2g/dev/moz.configure
+++ b/b2g/dev/moz.configure
@@ -1,7 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-include('../../toolkit/moz.configure')
+include('../common/moz.configure')
--- a/b2g/graphene/moz.configure
+++ b/b2g/graphene/moz.configure
@@ -1,7 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-include('../../toolkit/moz.configure')
+include('../common.configure')
--- a/b2g/installer/Makefile.in
+++ b/b2g/installer/Makefile.in
@@ -102,19 +102,19 @@ DEFINES += -DMOZ_ICU_VERSION=$(MOZ_ICU_V
 ifdef MOZ_SYSTEM_ICU
 DEFINES += -DMOZ_SYSTEM_ICU
 endif
 ifdef MOZ_SHARED_ICU
 DEFINES += -DMOZ_SHARED_ICU
 endif
 DEFINES += -DMOZ_ICU_DBG_SUFFIX=$(MOZ_ICU_DBG_SUFFIX)
 
-ifdef MOZ_WIDGET_GTK
+ifneq (,$(filter gtk%,$(MOZ_WIDGET_TOOLKIT)))
 DEFINES += -DMOZ_GTK=1
-ifdef MOZ_ENABLE_GTK3
+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
 DEFINES += -DMOZ_GTK3=1
 endif
 endif
 
 ifdef MOZ_CHROME_MULTILOCALE
 locale-manifest.in: $(GLOBAL_DEPS) FORCE
 	printf '\n[multilocale]\n' > $@
 	for LOCALE in $(MOZ_CHROME_MULTILOCALE) ;\
--- a/b2g/moz.configure
+++ b/b2g/moz.configure
@@ -1,7 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-include('../toolkit/moz.configure')
+option('--with-gonk', nargs=1, help='Path to the gonk base directory')
+
+@depends('--with-gonk')
+def gonkdir(value):
+    return value[0] if value else ''
+
+
+include('common.configure')
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -41,17 +41,17 @@ ifdef COMPILE_ENVIRONMENT
 libs:: 
 	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 endif
 
 GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js)
 
 endif
 
-ifdef MOZ_WIDGET_GTK
+ifneq (,$(filter gtk%,$(MOZ_WIDGET_TOOLKIT)))
 libs::
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(FINAL_TARGET)/icons
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png  $(FINAL_TARGET)/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png  $(FINAL_TARGET)/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png  $(FINAL_TARGET)/chrome/icons/default
 endif
 
 # channel-prefs.js is handled separate from other prefs due to bug 756325
--- a/browser/branding/branding-common.mozbuild
+++ b/browser/branding/branding-common.mozbuild
@@ -31,15 +31,15 @@ def FirefoxBranding():
     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
         BRANDING_FILES += [
             'background.png',
             'disk.icns',
             'document.icns',
             'dsstore',
             'firefox.icns',
         ]
-    elif CONFIG['MOZ_WIDGET_GTK']:
+    elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         BRANDING_FILES += [
             'default16.png',
             'default32.png',
             'default48.png',
             'mozicon128.png',
         ]
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/NewTabMessages.jsm
@@ -0,0 +1,95 @@
+/*global
+  NewTabWebChannel,
+  NewTabPrefsProvider,
+  Preferences,
+  XPCOMUtils
+*/
+
+/* exported NewTabMessages */
+
+"use strict";
+
+const {utils: Cu} = Components;
+Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
+                                  "resource:///modules/NewTabPrefsProvider.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
+                                  "resource:///modules/NewTabWebChannel.jsm");
+
+this.EXPORTED_SYMBOLS = ["NewTabMessages"];
+
+const PREF_ENABLED = "browser.newtabpage.remote";
+
+// Action names are from the content's perspective. in from chrome == out from content
+// Maybe replace the ACTION objects by a bi-directional Map a bit later?
+const ACTIONS = {
+  prefs: {
+    inPrefs: "REQUEST_PREFS",
+    outPrefs: "RECEIVE_PREFS",
+    action_types: new Set(["REQUEST_PREFS", "RECEIVE_PREFS"]),
+  }
+};
+
+let NewTabMessages = {
+
+  _prefs: {},
+
+  /** NEWTAB EVENT HANDLERS **/
+
+  /*
+   * Return to the originator all newtabpage prefs. A point-to-point request.
+   */
+  handlePrefRequest(actionName, {target}) {
+    if (ACTIONS.prefs.action_types.has(actionName)) {
+      let results = NewTabPrefsProvider.prefs.newtabPagePrefs;
+      NewTabWebChannel.send(ACTIONS.prefs.outPrefs, results, target);
+    }
+  },
+
+  /*
+   * Broadcast preference changes to all open newtab pages
+   */
+  handlePrefChange(actionName, value) {
+    let prefChange = {};
+    prefChange[actionName] = value;
+    NewTabWebChannel.broadcast(ACTIONS.prefs.outPrefs, prefChange);
+  },
+
+  _handleEnabledChange(prefName, value) {
+    if (prefName === PREF_ENABLED) {
+      if (this._prefs.enabled && !value) {
+        this.uninit();
+      } else if (!this._prefs.enabled && value) {
+        this.init();
+      }
+    }
+  },
+
+  init() {
+    this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
+
+    if (this._prefs.enabled) {
+      NewTabWebChannel.on(ACTIONS.prefs.inPrefs, this.handlePrefRequest.bind(this));
+      NewTabPrefsProvider.prefs.on(PREF_ENABLED, this._handleEnabledChange.bind(this));
+
+      for (let pref of NewTabPrefsProvider.newtabPagePrefSet) {
+        NewTabPrefsProvider.prefs.on(pref, this.handlePrefChange.bind(this));
+      }
+    }
+  },
+
+  uninit() {
+    this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
+
+    if (this._prefs.enabled) {
+      NewTabPrefsProvider.prefs.off(PREF_ENABLED, this._handleEnabledChange);
+
+      NewTabWebChannel.off(ACTIONS.prefs.inPrefs, this.handlePrefRequest);
+      for (let pref of NewTabPrefsProvider.newtabPagePrefSet) {
+        NewTabPrefsProvider.prefs.off(pref, this.handlePrefChange);
+      }
+    }
+  }
+};
--- a/browser/components/newtab/NewTabPrefsProvider.jsm
+++ b/browser/components/newtab/NewTabPrefsProvider.jsm
@@ -16,21 +16,34 @@ XPCOMUtils.defineLazyGetter(this, "Event
 });
 
 // Supported prefs and data type
 const gPrefsMap = new Map([
   ["browser.newtabpage.remote", "bool"],
   ["browser.newtabpage.remote.mode", "str"],
   ["browser.newtabpage.enabled", "bool"],
   ["browser.newtabpage.enhanced", "bool"],
+  ["browser.newtabpage.introShown", "bool"],
+  ["browser.newtabpage.updateIntroShown", "bool"],
   ["browser.newtabpage.pinned", "str"],
+  ["browser.newtabpage.blocked", "str"],
   ["intl.locale.matchOS", "bool"],
   ["general.useragent.locale", "localized"],
 ]);
 
+// prefs that are important for the newtab page
+const gNewtabPagePrefs = new Set([
+  "browser.newtabpage.enabled",
+  "browser.newtabpage.enhanced",
+  "browser.newtabpage.pinned",
+  "browser.newtabpage.blocked",
+  "browser.newtabpage.introShown",
+  "browser.newtabpage.updateIntroShown"
+]);
+
 let PrefsProvider = function PrefsProvider() {
   EventEmitter.decorate(this);
 };
 
 PrefsProvider.prototype = {
 
   observe(subject, topic, data) { // jshint ignore:line
     if (topic === "nsPref:changed") {
@@ -54,16 +67,27 @@ PrefsProvider.prototype = {
             break;
         }
       }
     } else {
       Cu.reportError(new Error("NewTabPrefsProvider observing unknown topic"));
     }
   },
 
+  /*
+   * Return the preferences that are important to the newtab page
+   */
+  get newtabPagePrefs() {
+    let results = {};
+    for (let pref of gNewtabPagePrefs) {
+      results[pref] = Preferences.get(pref, null);
+    }
+    return results;
+  },
+
   get prefsMap() {
     return gPrefsMap;
   },
 
   init() {
     for (let pref of gPrefsMap.keys()) {
       Services.prefs.addObserver(pref, this, false);
     }
@@ -78,9 +102,10 @@ PrefsProvider.prototype = {
 
 /**
  * Singleton that serves as the default new tab pref provider for the grid.
  */
 const gPrefs = new PrefsProvider();
 
 let NewTabPrefsProvider = {
   prefs: gPrefs,
+  newtabPagePrefSet: gNewtabPagePrefs,
 };
--- a/browser/components/newtab/NewTabRemoteResources.jsm
+++ b/browser/components/newtab/NewTabRemoteResources.jsm
@@ -1,13 +1,15 @@
-/* exported MODE_CHANNEL_MAP */
+/* exported NewTabRemoteResources */
 
 "use strict";
 
-this.EXPORTED_SYMBOLS = ["MODE_CHANNEL_MAP"];
+this.EXPORTED_SYMBOLS = ["NewTabRemoteResources"];
 
-const MODE_CHANNEL_MAP = {
-  "production": {origin: "https://content.cdn.mozilla.net"},
-  "staging": {origin: "https://content-cdn.stage.mozaws.net"},
-  "test": {origin: "https://example.com"},
-  "test2": {origin: "http://mochi.test:8888"},
-  "dev": {origin: "http://localhost:8888"}
+const NewTabRemoteResources = {
+  MODE_CHANNEL_MAP: {
+    production: {origin: "https://content.cdn.mozilla.net"},
+    staging: {origin: "https://content-cdn.stage.mozaws.net"},
+    test: {origin: "https://example.com"},
+    test2: {origin: "http://mochi.test:8888"},
+    dev: {origin: "http://localhost:8888"}
+  }
 };
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/NewTabWebChannel.jsm
@@ -0,0 +1,295 @@
+/* global
+   NewTabPrefsProvider,
+   Services,
+   EventEmitter,
+   Preferences,
+   XPCOMUtils,
+   WebChannel,
+   NewTabRemoteResources
+*/
+/* exported NewTabWebChannel */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["NewTabWebChannel"];
+
+const {utils: Cu} = Components;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Preferences.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
+                                  "resource:///modules/NewTabPrefsProvider.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabRemoteResources",
+                                  "resource:///modules/NewTabRemoteResources.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
+                                  "resource://gre/modules/WebChannel.jsm");
+XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
+  const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
+  return EventEmitter;
+});
+
+const CHAN_ID = "newtab";
+const PREF_ENABLED = "browser.newtabpage.remote";
+const PREF_MODE = "browser.newtabpage.remote.mode";
+
+/**
+ * NewTabWebChannel is the conduit for all communication with unprivileged newtab instances.
+ *
+ * It allows for the ability to broadcast to all newtab browsers.
+ * If the browser.newtab.remote pref is false, the object will be in an uninitialized state.
+ *
+ * Mode choices:
+ * 'production': pages from our production CDN
+ * 'staging': pages from our staging CDN
+ * 'test': intended for tests
+ * 'test2': intended for tests
+ * 'dev': intended for development
+ *
+ *  An unknown mode will result in 'production' mode, which is the default
+ *
+ *  Incoming messages are expected to be JSON-serialized and in the format:
+ *
+ *  {
+ *    type: "REQUEST_SCREENSHOT",
+ *    data: {
+ *      url: "https://example.com"
+ *    }
+ *  }
+ *
+ *  Or:
+ *
+ *  {
+ *    type: "REQUEST_SCREENSHOT",
+ *  }
+ *
+ *  Outgoing messages are expected to be objects serializable by structured cloning, in a similar format:
+ *  {
+ *    type: "RECEIVE_SCREENSHOT",
+ *    data: {
+ *      "url": "https://example.com",
+ *      "image": "dataURi:....."
+ *    }
+ *  }
+ */
+let NewTabWebChannelImpl = function NewTabWebChannelImpl() {
+  EventEmitter.decorate(this);
+  this._handlePrefChange = this._handlePrefChange.bind(this);
+  this._incomingMessage = this._incomingMessage.bind(this);
+};
+
+NewTabWebChannelImpl.prototype = {
+  _prefs: {},
+  _channel: null,
+
+  // a WeakMap containing browsers as keys and a weak ref to their principal
+  // as value
+  _principals: null,
+
+  // a Set containing weak refs to browsers
+  _browsers: null,
+
+  /*
+   * Returns current channel's ID
+   */
+  get chanId() {
+    return CHAN_ID;
+  },
+
+  /*
+   * Returns the number of browsers currently tracking
+   */
+  get numBrowsers() {
+    return this._getBrowserRefs().length;
+  },
+
+  /*
+   * Returns current channel's origin
+   */
+  get origin() {
+    if (!(this._prefs.mode in NewTabRemoteResources.MODE_CHANNEL_MAP)) {
+      this._prefs.mode = "production";
+    }
+    return NewTabRemoteResources.MODE_CHANNEL_MAP[this._prefs.mode].origin;
+  },
+
+  /*
+   * Unloads all browsers and principals
+   */
+  _unloadAll() {
+    if (this._principals != null) {
+      this._principals = new WeakMap();
+    }
+    this._browsers = new Set();
+    this.emit("targetUnloadAll");
+  },
+
+  /*
+   * Checks if a browser is known
+   *
+   * This will cause an iteration through all known browsers.
+   * That's ok, we don't expect a lot of browsers
+   */
+  _isBrowserKnown(browser) {
+    for (let bRef of this._getBrowserRefs()) {
+      let b = bRef.get();
+      if (b && b.permanentKey === browser.permanentKey) {
+        return true;
+      }
+    }
+
+    return false;
+  },
+
+  /*
+   * Obtains all known browser refs
+   */
+  _getBrowserRefs() {
+    let refs = [];
+    for (let bRef of this._browsers) {
+      /*
+       * even though we hold a weak ref to browser, it seems that browser
+       * objects aren't gc'd immediately after a tab closes. They stick around
+       * in memory, but thankfully they don't have a documentURI in that case
+       */
+      let browser = bRef.get();
+      if (browser && browser.documentURI) {
+        refs.push(bRef);
+      } else {
+        // need to clean up principals because the browser object is not gc'ed
+        // immediately
+        this._principals.delete(browser);
+        this._browsers.delete(bRef);
+        this.emit("targetUnload");
+      }
+    }
+    return refs;
+  },
+
+  /*
+   * Receives a message from content.
+   *
+   * Keeps track of browsers for broadcast, relays messages to listeners.
+   */
+  _incomingMessage(id, message, target) {
+    if (this.chanId !== id) {
+      Cu.reportError(new Error("NewTabWebChannel unexpected message destination"));
+    }
+
+    /*
+     * need to differentiate by browser, because event targets are created each
+     * time a message is sent.
+     */
+    if (!this._isBrowserKnown(target.browser)) {
+      this._browsers.add(Cu.getWeakReference(target.browser));
+      this._principals.set(target.browser, Cu.getWeakReference(target.principal));
+      this.emit("targetAdd");
+    }
+
+    try {
+      let msg = JSON.parse(message);
+      this.emit(msg.type, {data: msg.data, target: target});
+    } catch (err) {
+      Cu.reportError(err);
+    }
+  },
+
+  /*
+   * Sends a message to all known browsers
+   */
+  broadcast(actionType, message) {
+    for (let bRef of this._getBrowserRefs()) {
+      let browser = bRef.get();
+      try {
+        let principal = this._principals.get(browser).get();
+        if (principal && browser && browser.documentURI) {
+          this._channel.send({type: actionType, data: message}, {browser, principal});
+        }
+      } catch (e) {
+        Cu.reportError(new Error("NewTabWebChannel WeakRef is dead"));
+        this._principals.delete(browser);
+      }
+    }
+  },
+
+  /*
+   * Sends a message to a specific target
+   */
+  send(actionType, message, target) {
+    try {
+      this._channel.send({type: actionType, data: message}, target);
+    } catch (e) {
+      // Web Channel might be dead
+      Cu.reportError(e);
+    }
+  },
+
+  /*
+   * Pref change observer callback
+   */
+  _handlePrefChange(prefName, newState, forceState) { // eslint-disable-line no-unused-vars
+    switch (prefName) {
+      case PREF_ENABLED:
+        if (!this._prefs.enabled && newState) {
+          // changing state from disabled to enabled
+          this.setupState();
+        } else if (this._prefs.enabled && !newState) {
+          // changing state from enabled to disabled
+          this.tearDownState();
+        }
+        break;
+      case PREF_MODE:
+        if (this._prefs.mode !== newState) {
+          // changing modes
+          this.tearDownState();
+          this.setupState();
+        }
+        break;
+    }
+  },
+
+  /*
+   * Sets up the internal state
+   */
+  setupState() {
+    this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
+
+    let mode = Preferences.get(PREF_MODE, "production");
+    if (!(mode in NewTabRemoteResources.MODE_CHANNEL_MAP)) {
+      mode = "production";
+    }
+    this._prefs.mode = mode;
+    this._principals = new WeakMap();
+    this._browsers = new Set();
+
+    if (this._prefs.enabled) {
+      this._channel = new WebChannel(this.chanId, Services.io.newURI(this.origin, null, null));
+      this._channel.listen(this._incomingMessage);
+    }
+  },
+
+  tearDownState() {
+    if (this._channel) {
+      this._channel.stopListening();
+    }
+    this._prefs = {};
+    this._unloadAll();
+    this._channel = null;
+    this._principals = null;
+    this._browsers = null;
+  },
+
+  init() {
+    this.setupState();
+    NewTabPrefsProvider.prefs.on(PREF_ENABLED, this._handlePrefChange);
+    NewTabPrefsProvider.prefs.on(PREF_MODE, this._handlePrefChange);
+  },
+
+  uninit() {
+    this.tearDownState();
+    NewTabPrefsProvider.prefs.off(PREF_ENABLED, this._handlePrefChange);
+    NewTabPrefsProvider.prefs.off(PREF_MODE, this._handlePrefChange);
+  }
+};
+
+let NewTabWebChannel = new NewTabWebChannelImpl();
--- a/browser/components/newtab/aboutNewTabService.js
+++ b/browser/components/newtab/aboutNewTabService.js
@@ -1,31 +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/.
 */
 
 /* globals XPCOMUtils, NewTabPrefsProvider, Services,
-  Locale, UpdateUtils, MODE_CHANNEL_MAP
+  Locale, UpdateUtils, NewTabRemoteResources
 */
 "use strict";
 
 const {utils: Cu, interfaces: Ci} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
                                   "resource://gre/modules/UpdateUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
                                   "resource:///modules/NewTabPrefsProvider.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Locale",
                                   "resource://gre/modules/Locale.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "MODE_CHANNEL_MAP",
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabRemoteResources",
                                   "resource:///modules/NewTabRemoteResources.jsm");
 
 const LOCAL_NEWTAB_URL = "chrome://browser/content/newtab/newTab.xhtml";
 
 const REMOTE_NEWTAB_PATH = "/v%VERSION%/%CHANNEL%/%LOCALE%/index.html";
 
 const ABOUT_URL = "about:newtab";
 
@@ -163,20 +163,20 @@ AboutNewTabService.prototype = {
    */
   generateRemoteURL() {
     let releaseName = this.releaseFromUpdateChannel(UpdateUtils.UpdateChannel);
     let path = REMOTE_NEWTAB_PATH
       .replace("%VERSION%", REMOTE_NEWTAB_VERSION)
       .replace("%LOCALE%", Locale.getLocale())
       .replace("%CHANNEL%", releaseName);
     let mode = Services.prefs.getCharPref(PREF_REMOTE_MODE, "production");
-    if (!(mode in MODE_CHANNEL_MAP)) {
+    if (!(mode in NewTabRemoteResources.MODE_CHANNEL_MAP)) {
       mode = "production";
     }
-    return MODE_CHANNEL_MAP[mode].origin + path;
+    return NewTabRemoteResources.MODE_CHANNEL_MAP[mode].origin + path;
   },
 
   /*
    * Returns the default URL.
    *
    * This URL only depends on the browser.newtabpage.remote pref. Overriding
    * the newtab page has no effect on the result of this function.
    *
--- a/browser/components/newtab/moz.build
+++ b/browser/components/newtab/moz.build
@@ -6,19 +6,21 @@
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 
 XPCSHELL_TESTS_MANIFESTS += [
     'tests/xpcshell/xpcshell.ini',
 ]
 
 EXTRA_JS_MODULES += [
+    'NewTabMessages.jsm',
     'NewTabPrefsProvider.jsm',
     'NewTabRemoteResources.jsm',
     'NewTabURL.jsm',
+    'NewTabWebChannel.jsm',
     'PlacesProvider.jsm'
 ]
 
 XPIDL_SOURCES += [
     'nsIAboutNewTabService.idl',
 ]
 
 XPIDL_MODULE = 'browser-newtab'
--- a/browser/components/newtab/tests/browser/browser.ini
+++ b/browser/components/newtab/tests/browser/browser.ini
@@ -1,6 +1,10 @@
 [DEFAULT]
 support-files =
   dummy_page.html
+  newtabwebchannel_basic.html
+  newtabmessages_prefs.html
 
 [browser_remotenewtab_pageloads.js]
 [browser_newtab_overrides.js]
+[browser_newtabmessages.js]
+[browser_newtabwebchannel.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/browser/browser_newtabmessages.js
@@ -0,0 +1,57 @@
+/* globals Cu, XPCOMUtils, Preferences, is, registerCleanupFunction, NewTabWebChannel */
+
+"use strict";
+
+Cu.import("resource://gre/modules/Preferences.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
+                                  "resource:///modules/NewTabWebChannel.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabMessages",
+                                  "resource:///modules/NewTabMessages.jsm");
+
+function setup() {
+  Preferences.set("browser.newtabpage.enhanced", true);
+  Preferences.set("browser.newtabpage.remote.mode", "test");
+  Preferences.set("browser.newtabpage.remote", true);
+  NewTabMessages.init();
+}
+
+function cleanup() {
+  NewTabMessages.uninit();
+  NewTabWebChannel.tearDownState();
+  Preferences.set("browser.newtabpage.remote", false);
+  Preferences.set("browser.newtabpage.remote.mode", "production");
+}
+registerCleanupFunction(cleanup);
+
+/*
+ * Sanity tests for pref messages
+ */
+add_task(function* prefMessages_request() {
+  setup();
+  let testURL = "https://example.com/browser/browser/components/newtab/tests/browser/newtabmessages_prefs.html";
+
+  let tabOptions = {
+    gBrowser,
+    url: testURL
+  };
+
+  let prefResponseAck = new Promise(resolve => {
+    NewTabWebChannel.once("responseAck", () => {
+      ok(true, "a request response has been received");
+      resolve();
+    });
+  });
+
+  yield BrowserTestUtils.withNewTab(tabOptions, function*() {
+    yield prefResponseAck;
+    let prefChangeAck = new Promise(resolve => {
+      NewTabWebChannel.once("responseAck", () => {
+        ok(true, "a change response has been received");
+        resolve();
+      });
+    });
+    Preferences.set("browser.newtabpage.enhanced", false);
+    yield prefChangeAck;
+  });
+  cleanup();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/browser/browser_newtabwebchannel.js
@@ -0,0 +1,232 @@
+/* globals XPCOMUtils, Cu, Preferences, NewTabWebChannel, is, registerCleanupFunction */
+
+"use strict";
+
+Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
+                                  "resource:///modules/NewTabWebChannel.jsm");
+
+const TEST_URL = "https://example.com/browser/browser/components/newtab/tests/browser/newtabwebchannel_basic.html";
+const TEST_URL_2 = "http://mochi.test:8888/browser/browser/components/newtab/tests/browser/newtabwebchannel_basic.html";
+
+function cleanup() {
+  NewTabWebChannel.tearDownState();
+  Preferences.set("browser.newtabpage.remote", false);
+  Preferences.set("browser.newtabpage.remote.mode", "production");
+}
+registerCleanupFunction(cleanup);
+
+/*
+ * Tests flow of messages from newtab to chrome and chrome to newtab
+ */
+add_task(function* open_webchannel_basic() {
+  Preferences.set("browser.newtabpage.remote.mode", "test");
+  Preferences.set("browser.newtabpage.remote", true);
+
+  let tabOptions = {
+    gBrowser,
+    url: TEST_URL
+  };
+
+  let messagePromise = new Promise(resolve => {
+    NewTabWebChannel.once("foo", function(name, msg) {
+      is(name, "foo", "Correct message type sent: foo");
+      is(msg.data, "bar", "Correct data sent: bar");
+      resolve(msg.target);
+    });
+  });
+
+  let replyPromise = new Promise(resolve => {
+    NewTabWebChannel.once("reply", function(name, msg) {
+      is(name, "reply", "Correct message type sent: reply");
+      is(msg.data, "quuz", "Correct data sent: quuz");
+      resolve(msg.target);
+    });
+  });
+
+  let unloadPromise = new Promise(resolve => {
+    NewTabWebChannel.once("targetUnload", function(name) {
+      is(name, "targetUnload", "Correct message type sent: targetUnload");
+      resolve();
+    });
+  });
+
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  yield BrowserTestUtils.withNewTab(tabOptions, function*(browser) {
+    let target = yield messagePromise;
+    is(NewTabWebChannel.numBrowsers, 1, "One target expected");
+    is(target.browser, browser, "Same browser");
+    NewTabWebChannel.send("respond", null, target);
+    yield replyPromise;
+  });
+
+  Cu.forceGC();
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  yield unloadPromise;
+  cleanup();
+});
+
+/*
+ * Tests message broadcast reaches all open newtab pages
+ */
+add_task(function* webchannel_broadcast() {
+  Preferences.set("browser.newtabpage.remote.mode", "test");
+  Preferences.set("browser.newtabpage.remote", true);
+
+  let countingMessagePromise = new Promise(resolve => {
+    let count = 0;
+    NewTabWebChannel.on("foo", function test_message(name, msg) {
+      count += 1;
+      if (count === 2) {
+        NewTabWebChannel.off("foo", test_message);
+        resolve(msg.target);
+      }
+    }.bind(this));
+  });
+
+  let countingReplyPromise = new Promise(resolve => {
+    let count = 0;
+    NewTabWebChannel.on("reply", function test_message(name, msg) {
+      count += 1;
+      if (count === 2) {
+        NewTabWebChannel.off("reply", test_message);
+        resolve(msg.target);
+      }
+    }.bind(this));
+  });
+
+  let countingUnloadPromise = new Promise(resolve => {
+    let count = 0;
+    NewTabWebChannel.on("targetUnload", function test_message() {
+      count += 1;
+      if (count === 2) {
+        NewTabWebChannel.off("targetUnload", test_message);
+        resolve();
+      }
+    });
+  });
+
+  let tabs = [];
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  tabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL));
+  tabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL));
+
+  yield countingMessagePromise;
+  is(NewTabWebChannel.numBrowsers, 2, "Two targets expected");
+
+  NewTabWebChannel.broadcast("respond", null);
+  yield countingReplyPromise;
+
+  for (let tab of tabs) {
+    yield BrowserTestUtils.removeTab(tab);
+  }
+  Cu.forceGC();
+
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  yield countingUnloadPromise;
+  cleanup();
+});
+
+/*
+ * Tests switching modes
+ */
+add_task(function* webchannel_switch() {
+  Preferences.set("browser.newtabpage.remote.mode", "test");
+  Preferences.set("browser.newtabpage.remote", true);
+
+  function newMessagePromise() {
+    return new Promise(resolve => {
+      NewTabWebChannel.once("foo", function(name, msg) {
+        resolve(msg.target);
+      }.bind(this));
+    });
+  }
+
+  let replyCount = 0;
+  let replyPromise = new Promise(resolve => {
+    NewTabWebChannel.on("reply", function() {
+      replyCount += 1;
+      resolve();
+    }.bind(this));
+  });
+
+  let unloadPromise = new Promise(resolve => {
+    NewTabWebChannel.once("targetUnload", function() {
+      resolve();
+    });
+  });
+
+  let unloadAllPromise = new Promise(resolve => {
+    NewTabWebChannel.once("targetUnloadAll", function() {
+      resolve();
+    });
+  });
+
+  let tabs = [];
+  let messagePromise;
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+
+  messagePromise = newMessagePromise();
+  tabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL));
+  yield messagePromise;
+  is(NewTabWebChannel.numBrowsers, 1, "Correct number of targets");
+
+  messagePromise = newMessagePromise();
+  Preferences.set("browser.newtabpage.remote.mode", "test2");
+  tabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL_2));
+  yield unloadAllPromise;
+  yield messagePromise;
+  is(NewTabWebChannel.numBrowsers, 1, "Correct number of targets");
+
+  NewTabWebChannel.broadcast("respond", null);
+  yield replyPromise;
+  is(replyCount, 1, "only current channel is listened to for replies");
+
+  for (let tab of tabs) {
+    yield BrowserTestUtils.removeTab(tab);
+  }
+
+  Cu.forceGC();
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  yield unloadPromise;
+  cleanup();
+});
+
+add_task(function* open_webchannel_reload() {
+  Preferences.set("browser.newtabpage.remote.mode", "test");
+  Preferences.set("browser.newtabpage.remote", true);
+
+  let tabOptions = {
+    gBrowser,
+    url: TEST_URL
+  };
+
+  let messagePromise = new Promise(resolve => {
+    NewTabWebChannel.once("foo", function(name, msg) {
+      is(name, "foo", "Correct message type sent: foo");
+      is(msg.data, "bar", "Correct data sent: bar");
+      resolve(msg.target);
+    });
+  });
+  let unloadPromise = new Promise(resolve => {
+    NewTabWebChannel.once("targetUnload", function() {
+      resolve();
+    });
+  });
+
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  yield BrowserTestUtils.withNewTab(tabOptions, function*(browser) {
+    let target = yield messagePromise;
+    is(NewTabWebChannel.numBrowsers, 1, "One target expected");
+    is(target.browser, browser, "Same browser");
+
+    browser.contentWindow.location.reload();
+  });
+
+  Cu.forceGC();
+  is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
+  yield unloadPromise;
+  cleanup();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/browser/newtabmessages_prefs.html
@@ -0,0 +1,32 @@
+<html>
+    <head>
+        <meta charset="utf8">
+        <title>Newtab WebChannel test</title>
+    </head>
+    <body>
+        <script>
+            window.addEventListener("WebChannelMessageToContent", function(e) {
+                if (e.detail.message && e.detail.message.type === "RECEIVE_PREFS") {
+                    let reply = new window.CustomEvent("WebChannelMessageToChrome", {
+                        detail: {
+                            id: "newtab",
+                            message: JSON.stringify({type: "responseAck"}),
+                        }
+                    });
+                    window.dispatchEvent(reply);
+                }
+            }, true);
+
+            document.onreadystatechange = function () {
+                let msg = new window.CustomEvent("WebChannelMessageToChrome", {
+                    detail: {
+                        id: "newtab",
+                        message: JSON.stringify({type: "REQUEST_PREFS"}),
+                    }
+                });
+                window.dispatchEvent(msg);
+            };
+
+        </script>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/browser/newtabwebchannel_basic.html
@@ -0,0 +1,32 @@
+<html>
+    <head>
+        <meta charset="utf8">
+        <title>Newtab WebChannel test</title>
+    </head>
+    <body>
+        <script>
+            document.onreadystatechange = function () {
+                let msg = new window.CustomEvent("WebChannelMessageToChrome", {
+                    detail: {
+                        id: "newtab",
+                        message: JSON.stringify({type: "foo", data: "bar"}),
+                    }
+                });
+                window.dispatchEvent(msg);
+            };
+
+            window.addEventListener("WebChannelMessageToContent", function(e) {
+                if (e.detail.message && e.detail.message.type === "respond") {
+                    let reply = new window.CustomEvent("WebChannelMessageToChrome", {
+                        detail: {
+                            id: "newtab",
+                            message: JSON.stringify({type: "reply", data: "quuz"}),
+                        }
+                    });
+                    window.dispatchEvent(reply);
+                }
+            }, true);
+            
+        </script>
+    </body>
+</html>
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -23,16 +23,22 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource:///modules/DirectoryLinksProvider.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
                                   "resource://gre/modules/NewTabUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
                                   "resource:///modules/NewTabPrefsProvider.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
+                                  "resource:///modules/NewTabWebChannel.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabMessages",
+                                  "resource:///modules/NewTabMessages.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "UITour",
                                   "resource:///modules/UITour.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentClick",
                                   "resource:///modules/ContentClick.jsm");
@@ -744,16 +750,18 @@ BrowserGlue.prototype = {
     AboutHome.init();
 
     DirectoryLinksProvider.init();
     NewTabUtils.init();
     NewTabUtils.links.addProvider(DirectoryLinksProvider);
     AboutNewTab.init();
 
     NewTabPrefsProvider.prefs.init();
+    NewTabWebChannel.init();
+    NewTabMessages.init();
 
     SessionStore.init();
     BrowserUITelemetry.init();
     ContentSearch.init();
     FormValidationHandler.init();
 
     ContentClick.init();
     RemotePrompt.init();
@@ -1049,16 +1057,19 @@ BrowserGlue.prototype = {
                          .getService(Ci.nsIAppStartup);
       appStartup.trackStartupCrashEnd();
     } catch (e) {
       Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
     }
 
     SelfSupportBackend.uninit();
     NewTabPrefsProvider.prefs.uninit();
+    NewTabWebChannel.uninit();
+    NewTabMessages.uninit();
+
     AboutNewTab.uninit();
     webrtcUI.uninit();
     FormValidationHandler.uninit();
     if (AppConstants.NIGHTLY_BUILD) {
       AddonWatcher.uninit();
     }
   },
 
--- a/browser/components/shell/moz.build
+++ b/browser/components/shell/moz.build
@@ -16,32 +16,32 @@ XPIDL_SOURCES += [
 if CONFIG['OS_ARCH'] == 'WINNT':
     XPIDL_SOURCES += [
         'nsIWindowsShellService.idl',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     XPIDL_SOURCES += [
         'nsIMacShellService.idl',
     ]
-elif CONFIG['MOZ_WIDGET_GTK']:
+elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     XPIDL_SOURCES += [
         'nsIGNOMEShellService.idl',
     ]
 
 XPIDL_MODULE = 'shellservice'
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'nsWindowsShellService.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     SOURCES += [
         'nsMacShellService.cpp',
     ]
-elif CONFIG['MOZ_WIDGET_GTK']:
+elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     SOURCES += [
         'nsGNOMEShellService.cpp',
     ]
 
 if SOURCES:
     FINAL_LIBRARY = 'browsercomps'
 
 EXTRA_COMPONENTS += [
--- a/browser/extensions/e10srollout/bootstrap.js
+++ b/browser/extensions/e10srollout/bootstrap.js
@@ -1,16 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/UpdateUtils.jsm");
 
  // The amount of people to be part of e10s, in %
 const TEST_THRESHOLD = {
   "beta"    : 50,
   "release" : 0,
 };
 
@@ -50,22 +51,25 @@ function defineCohort() {
   let updateChannel = UpdateUtils.getUpdateChannel(false);
   if (!(updateChannel in TEST_THRESHOLD)) {
     setCohort("unsupportedChannel");
     return;
   }
 
   let userOptedOut = optedOut();
   let userOptedIn = optedIn();
+  let disqualified = (Services.appinfo.multiprocessBlockPolicy != 0);
   let testGroup = (getUserSample() < TEST_THRESHOLD[updateChannel]);
 
   if (userOptedOut) {
     setCohort("optedOut");
   } else if (userOptedIn) {
     setCohort("optedIn");
+  } else if (disqualified) {
+    setCohort("disqualified");
   } else if (testGroup) {
     setCohort("test");
     Preferences.set(PREF_TOGGLE_E10S, true);
   } else {
     setCohort("control");
     Preferences.reset(PREF_TOGGLE_E10S);
   }
 }
@@ -84,16 +88,19 @@ function getUserSample() {
 
   let val = Math.floor(Math.random() * 100);
   Preferences.set(PREF_COHORT_SAMPLE, val);
   return val;
 }
 
 function setCohort(cohortName) {
   Preferences.set(PREF_COHORT_NAME, cohortName);
+  try {
+    Services.appinfo.annotateCrashReport("E10SCohort", cohortName);
+  } catch (e) {}
 }
 
 function optedIn() {
   return Preferences.get(PREF_E10S_OPTED_IN, false) ||
          Preferences.get(PREF_E10S_FORCE_ENABLED, false);
 }
 
 function optedOut() {
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -19,19 +19,19 @@ DEFINES += -DMOZ_MULET
 endif
 
 DEFINES += -DMOZ_APP_NAME=$(MOZ_APP_NAME) -DPREF_DIR=$(PREF_DIR)
 
 ifdef MOZ_DEBUG
 DEFINES += -DMOZ_DEBUG=1
 endif
 
-ifdef MOZ_WIDGET_GTK
+ifneq (,$(filter gtk%,$(MOZ_WIDGET_TOOLKIT)))
 DEFINES += -DMOZ_GTK=1
-ifdef MOZ_ENABLE_GTK3
+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
 DEFINES += -DMOZ_GTK3=1
 endif
 endif
 
 ifdef MOZ_SYSTEM_NSPR
 DEFINES += -DMOZ_SYSTEM_NSPR=1
 endif
 
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -361,21 +361,16 @@
     list-style-image: url(chrome://global/skin/icons/question-32.png);
   }
 
   #login-fill-notification-icon,
   #password-notification-icon {
     list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16@2x.png);
   }
 
-  .webapps-notification-icon,
-  #webapps-notification-icon {
-    list-style-image: url(chrome://global/skin/icons/webapps-16@2x.png);
-  }
-
   #plugins-notification-icon {
     list-style-image: url(chrome://browser/skin/notification-pluginNormal@2x.png);
   }
 
   #plugins-notification-icon.plugin-hidden {
     list-style-image: url(chrome://browser/skin/notification-pluginAlert@2x.png);
   }
 
--- a/build/docs/index.rst
+++ b/build/docs/index.rst
@@ -19,16 +19,17 @@ Important Concepts
    environment-variables
    build-targets
    python
    test_manifests
    mozinfo
    preprocessor
    jar-manifests
    defining-binaries
+   toolchains
 
 integrated development environment (IDE)
 ========================================
 .. toctree::
    :maxdepth: 1
 
    androideclipse
    cppeclipse
new file mode 100644
--- /dev/null
+++ b/build/docs/toolchains.rst
@@ -0,0 +1,53 @@
+.. _build_toolchains:
+
+===========================
+Creating Toolchain Archives
+===========================
+
+There are various scripts in the repository for producing archives
+of the build tools (e.g. compilers and linkers) required to build.
+
+Clang
+=====
+
+See the ``build/build-clang`` directory. Read ``build/build-clang/README``
+for more.
+
+Windows
+=======
+
+The ``build/windows_toolchain.py`` script is used to build and manage
+Windows toolchain archives containing Visual Studio executables, SDKs,
+etc.
+
+The way Firefox build automation works is an archive containing the
+toolchain is produced and uploaded to an internal Mozilla server. The
+build automation will download, verify, and extract this archive before
+building. The archive is self-contained so machines don't need to install
+Visual Studio, SDKs, or various other dependencies. Unfortunately,
+Microsoft's terms don't allow Mozilla to distribute this archive
+publicly. However, the same tool can be used to create your own copy.
+
+Configuring Your System
+-----------------------
+
+It is **highly** recommended to perform this process on a fresh installation
+of Windows 7 or 10 (such as in a VM). Installing all updates through
+Windows Update is not only acceptable - it is encouraged. Although it
+shouldn't matter.
+
+Next, install Visual Studio 2015 Community. The download link can be
+found at https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx.
+Be sure to follow these install instructions:
+
+1. Choose a ``Custom`` installation and click ``Next``
+2. Select ``Programming Languages`` -> ``Visual C++`` (make sure all sub items are
+   selected)
+3. Under ``Windows and Web Development`` uncheck everything except
+   ``Universal Windows App Development Tools`` and the items under it
+   (should be ``Tools (1.2)...`` and the ``Windows 10 SDK``).
+
+Once Visual Studio 2015 Community has been installed, from a checkout
+of mozilla-central, run the following to produce a ZIP archive::
+
+   $ ./mach python build/windows_toolchain.py create-zip vs2015.zip
--- a/build/moz.configure/checks.configure
+++ b/build/moz.configure/checks.configure
@@ -64,14 +64,14 @@ def check_prog(var, progs, allow_missing
             if result:
                 return result
         return not_found
 
     @depends(check)
     @advanced
     def postcheck(value):
         set_config(var, ':' if value is not_found else value)
-        if not value and not allow_missing:
+        if value is not_found and not allow_missing:
             from mozbuild.shellutil import quote
             error('Cannot find %s (tried: %s)'
                   % (var.lower(), ', '.join(quote(p) for p in progs)))
 
     return check
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -250,23 +250,29 @@ def wanted_mozconfig_variables(help):
          'AUTOCONF',
          'AWK',
          'DISABLE_EXPORT_JS',
          'DISABLE_SHARED_JS',
          'DOXYGEN',
          'DSYMUTIL',
          'EXTERNAL_SOURCE_DIR',
          'GENISOIMAGE',
+         'L10NBASEDIR',
          'MOZILLABUILD',
          'MOZ_ARTIFACT_BUILDS',
          'MOZ_BUILD_APP',
+         'MOZ_FMP4',
+         'MOZ_INSTRUMENT_EVENT_LOOP',
+         'MOZTTDIR',
          'PERL',
          'RPMBUILD',
          'TAR',
          'UNZIP',
+         'USE_FC_FREETYPE',
+         'WITHOUT_X',
          'XARGS',
          'ZIP',
      ])
 
 
 @depends(mozconfig, wanted_mozconfig_variables)
 def mozconfig_options(mozconfig, wanted_mozconfig_variables):
     if mozconfig['path']:
@@ -355,17 +361,21 @@ def split_triplet(triplet):
     elif os.startswith('kfreebsd') and os.endswith('-gnu'):
         canonical_os = 'GNU'
         canonical_kernel = 'kFreeBSD'
     elif os.startswith('gnu'):
         canonical_os = canonical_kernel = 'GNU'
     elif os.startswith('mingw'):
         canonical_os = canonical_kernel = 'WINNT'
     elif os.startswith('darwin'):
-        canonical_os = canonical_kernel = 'Darwin'
+        canonical_kernel = 'Darwin'
+        canonical_os = 'OSX'
+    elif os.startswith('ios'):
+        canonical_kernel = 'Darwin'
+        canonical_os = 'iOS'
     elif os.startswith('dragonfly'):
         canonical_os = canonical_kernel = 'DragonFly'
     elif os.startswith('freebsd'):
         canonical_os = canonical_kernel = 'FreeBSD'
     elif os.startswith('netbsd'):
         canonical_os = canonical_kernel = 'NetBSD'
     elif os.startswith('openbsd'):
         canonical_os = canonical_kernel = 'OpenBSD'
@@ -429,27 +439,34 @@ def target(value, host):
         return host
     return split_triplet(value[0])
 
 
 @depends(host, target)
 def host_and_target_for_old_configure(host, target):
     # Autoconf needs these set
     add_old_configure_arg('--host=%s' % host.alias)
-    add_old_configure_arg('--target=%s' % target.alias)
+
+    target_alias = target.alias
+    # old-configure does plenty of tests against $target and $target_os
+    # and expects darwin for iOS, so make it happy.
+    if target.os == 'iOS':
+        target_alias = target_alias.replace('-ios', '-darwin')
+    add_old_configure_arg('--target=%s' % target_alias)
 
 
 # These variables are for compatibility with the current moz.builds and
 # old-configure. Eventually, we'll want to canonicalize better.
 @depends(target)
 def target_variables(target):
     if target.kernel == 'kFreeBSD':
         os_target = 'GNU/kFreeBSD'
         os_arch = 'GNU_kFreeBSD'
-    elif target.kernel == 'Linux' and target.os == 'GNU':
+    elif target.kernel == 'Darwin' or (target.kernel == 'Linux' and
+                                       target.os == 'GNU'):
         os_target = target.kernel
         os_arch = target.kernel
     else:
         os_target = target.os
         os_arch = target.kernel
     add_old_configure_assignment('OS_TARGET', os_target)
     set_config('OS_TARGET', os_target)
     add_old_configure_assignment('OS_ARCH', os_arch)
@@ -537,9 +554,25 @@ def js_option(*args, **kwargs):
     opt = option(*args, **kwargs)
 
     @depends(opt.option, build_project)
     def js_option(value, build_project):
         if build_project != 'js':
             add_old_configure_arg(value.format(opt.option))
 
 
+# This is overridden in b2g/moz.configure with an option. No other project
+# needs the option directly, but it's used to influence some other things in
+# toolkit/moz.configure (and possibly top-level moz.configure later on), so
+# define a dummy default here.
+@depends('--help')
+def gonkdir(help):
+    return ''
+
+
 include(include_project_configure)
+
+# By now, gonkdir is either the dummy function above or a real function
+# depending on --with-gonk from b2g/moz.configure.
+@depends(gonkdir)
+def gonkdir_for_old_configure(value):
+    if value:
+        add_old_configure_assignment('gonkdir', value)
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -186,28 +186,24 @@ def old_configure_options(*options):
     '--enable-cpp-rtti',
     '--enable-crashreporter',
     '--enable-ctypes',
     '--enable-dbm',
     '--enable-dbus',
     '--enable-debug',
     '--enable-debug-js-modules',
     '--enable-debug-symbols',
-    '--enable-default-toolkit',
     '--enable-directshow',
     '--enable-dmd',
     '--enable-dtrace',
     '--enable-dump-painting',
     '--enable-elf-hack',
-    '--enable-eme',
     '--enable-extensions',
     '--enable-faststripe',
     '--enable-feeds',
-    '--enable-ffmpeg',
-    '--enable-fmp4',
     '--enable-gamepad',
     '--enable-gc-trace',
     '--enable-gconf',
     '--enable-gczeal',
     '--enable-gio',
     '--enable-gnomeui',
     '--enable-gold',
     '--enable-gps-debug',
@@ -294,17 +290,16 @@ def old_configure_options(*options):
     '--enable-verify-mar',
     '--enable-vtune',
     '--enable-warnings-as-errors',
     '--enable-webapp-runtime',
     '--enable-webrtc',
     '--enable-websms-backend',
     '--enable-webspeech',
     '--enable-webspeechtestbackend',
-    '--enable-wmf',
     '--enable-xul',
     '--enable-zipwriter',
     '--no-create',
     '--prefix',
     '--with-adjust-sdk-keyfile',
     '--with-android-cxx-stl',
     '--with-android-distribution-directory',
     '--with-android-gnu-compiler-version',
@@ -327,28 +322,24 @@ def old_configure_options(*options):
     '--with-debug-label',
     '--with-default-mozilla-five-home',
     '--with-distribution-id',
     '--with-doc-include-dirs',
     '--with-doc-input-dirs',
     '--with-doc-output-dir',
     '--with-float-abi',
     '--with-fpu',
-    '--with-gl-provider',
-    '--with-gonk',
     '--with-gonk-toolchain-prefix',
     '--with-google-api-keyfile',
     '--with-google-oauth-api-keyfile',
     '--with-gradle',
     '--with-intl-api',
     '--with-ios-sdk',
     '--with-java-bin-path',
     '--with-jitreport-granularity',
-    '--with-l10n-base',
-    '--with-libxul-sdk',
     '--with-linux-headers',
     '--with-macbundlename-prefix',
     '--with-macos-private-frameworks',
     '--with-macos-sdk',
     '--with-mozilla-api-keyfile',
     '--with-nspr-prefix',
     '--with-nspr-cflags',
     '--with-nspr-libs',
@@ -367,17 +358,16 @@ def old_configure_options(*options):
     '--with-system-nss',
     '--with-system-png',
     '--with-system-zlib',
     '--with-thumb',
     '--with-thumb-interwork',
     '--with-unify-dist',
     '--with-user-appdir',
     '--with-windows-version',
-    '--with-x',
     '--with-xulrunner-stub-name',
     '--x-includes',
     '--x-libraries',
 
     # Below are the configure flags used by comm-central.
     '--enable-ldap',
     '--enable-mapi',
     '--enable-calendar',
new file mode 100644
--- /dev/null
+++ b/build/windows_toolchain.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python2.7
+# 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/.
+
+# This script is used to create and manipulate archives containing
+# files necessary to build Firefox on Windows (referred to as the
+# "Windows toolchain").
+#
+# When updating behavior of this script, remember to update the docs
+# in ``build/docs/toolchains.rst``.
+
+from __future__ import absolute_import, unicode_literals
+
+import hashlib
+import os
+import sys
+
+from mozpack.files import (
+    FileFinder,
+)
+from mozpack.mozjar import (
+    JarWriter,
+)
+import mozpack.path as mozpath
+
+
+# mozpack.match patterns for files under "Microsoft Visual Studio 14.0".
+VS_PATTERNS = [
+    {
+        'pattern': 'DIA SDK/bin/**',
+        # Various tools don't like spaces in filenames. So remove it.
+        'rewrite': [('DIA SDK/', 'DIASDK/')],
+        'ignore': (
+            'DIA SDK/bin/arm/**',
+        ),
+    },
+    {
+        'pattern': 'DIA SDK/idl/**',
+        'rewrite': [('DIA SDK/', 'DIASDK/')],
+    },
+    {
+        'pattern': 'DIA SDK/include/**',
+        'rewrite': [('DIA SDK/', 'DIASDK/')],
+    },
+    {
+        'pattern': 'DIA SDK/lib/**',
+        'rewrite': [('DIA SDK/', 'DIASDK/')],
+        'ignore': (
+            'DIA SDK/lib/arm/**',
+        ),
+    },
+    # ATL is needed by Breakpad.
+    {
+        'pattern': 'VC/atlmfc/include/**',
+    },
+    {
+        'pattern': 'VC/atlmfc/lib/atls.*',
+    },
+    {
+        'pattern': 'VC/atlmfc/lib/amd64/atls.*',
+    },
+    {
+        'pattern': 'VC/bin/**',
+        # We only care about compiling on amd64 for amd64 or x86 targets.
+        'ignore': (
+            'VC/bin/amd64_arm/**',
+            'VC/bin/arm/**',
+            'VC/bin/x86_arm/**',
+            'VC/bin/x86_amd64/**',
+        ),
+    },
+    {
+        'pattern': 'VC/include/**',
+    },
+    {
+        'pattern': 'VC/lib/**',
+        'ignore': (
+            'VC/lib/arm/**',
+            'VC/lib/onecore/**',
+            'VC/lib/store/**',
+        ),
+    },
+    {
+        'pattern': 'VC/redist/x64/Microsoft.VC140.CRT/**',
+    },
+    {
+        'pattern': 'VC/redist/x86/Microsoft.VC140.CRT/**',
+    },
+]
+
+SDK_RELEASE = '10.0.10586.0'
+
+# Files from the Windows 10 SDK to install.
+SDK_PATTERNS = [
+    {
+        'pattern': 'bin/x64/**',
+    },
+    {
+        'pattern': 'Include/%s/**' % SDK_RELEASE,
+    },
+    {
+        'pattern': 'Lib/%s/ucrt/x64/**' % SDK_RELEASE,
+    },
+    {
+        'pattern': 'Lib/%s/ucrt/x86/**' % SDK_RELEASE,
+    },
+    {
+        'pattern': 'Lib/%s/um/x64/**' % SDK_RELEASE,
+    },
+    {
+        'pattern': 'Lib/%s/um/x86/**' % SDK_RELEASE,
+    },
+    {
+        'pattern': 'Redist/D3D/**',
+    },
+    {
+        'pattern': 'Redist/ucrt/DLLs/x64/**',
+    },
+    {
+        'pattern': 'Redist/ucrt/DLLs/x86/**',
+    },
+]
+
+
+def find_vs_paths():
+    """Resolve source locations of files.
+
+    Returns a 2-tuple of (Visual Studio Path, SDK Path).
+    """
+    pf = os.environ.get('ProgramFiles(x86)')
+    if not pf:
+        raise Exception('No "ProgramFiles(x86)" environment variable. '
+                        'Not running on 64-bit Windows?')
+
+    vs_path = os.path.join(pf, 'Microsoft Visual Studio 14.0')
+    if not os.path.exists(vs_path):
+        raise Exception('%s does not exist; Visual Studio 2015 not installed?' %
+                        vs_path)
+
+    sdk_path = os.path.join(pf, 'Windows Kits', '10')
+    if not os.path.exists(sdk_path):
+        raise Exception('%s does not exist; Windows 10 SDK not installed?' %
+                        sdk_path)
+
+    return vs_path, sdk_path
+
+
+def resolve_files():
+    """Resolve the files that constitute a standalone toolchain.
+
+    This is a generator of (dest path, file) where the destination
+    path is relative and the file instance is a BaseFile from mozpack.
+    """
+    vs_path, sdk_path = find_vs_paths()
+
+    for entry in VS_PATTERNS:
+        finder = FileFinder(vs_path, find_executables=False,
+                            ignore=entry.get('ignore', []))
+        for p, f in finder.find(entry['pattern']):
+            assert p.startswith(('VC/', 'DIA SDK/'))
+
+            for source, dest in entry.get('rewrite', []):
+                p = p.replace(source, dest)
+
+            yield p.encode('utf-8'), f
+
+    for entry in SDK_PATTERNS:
+        finder = FileFinder(sdk_path, find_executables=False,
+                            ignore=entry.get('ignore', []))
+        for p, f in finder.find(entry['pattern']):
+            # We remove the SDK version from the path so we don't have
+            # to update other configs when we change the SDK version.
+            p = p.replace('/%s/' % SDK_RELEASE, '/')
+            relpath = 'SDK/%s' % p
+
+            yield relpath.encode('utf-8'), f
+
+
+def resolve_files_and_hash(manifest):
+    """Resolve files and hash their data.
+
+    This is a generator of 3-tuples of (relpath, data, mode).
+
+    As data is read, the manifest is populated with metadata.
+    Keys are set to the relative file path. Values are 2-tuples
+    of (data length, sha-256).
+    """
+    assert manifest == {}
+    for p, f in resolve_files():
+        data = f.read()
+
+        sha256 = hashlib.sha256()
+        sha256.update(data)
+        manifest[p] = (len(data), sha256.hexdigest())
+
+        yield p, data, f.mode
+
+
+def format_manifest(manifest):
+    """Return formatted SHA-256 manifests as a byte strings."""
+    sha256_lines = []
+    for path, (length, sha256) in sorted(manifest.items()):
+        sha256_lines.append(b'%s\t%d\t%s' % (sha256, length, path))
+
+    # Trailing newline.
+    sha256_lines.append(b'')
+
+    return b'\n'.join(sha256_lines)
+
+
+def write_zip(zip_path, prefix=None):
+    """Write toolchain data to a zip file."""
+    if isinstance(prefix, unicode):
+        prefix = prefix.encode('utf-8')
+
+    with JarWriter(file=zip_path, optimize=False, compress=5) as zip:
+        manifest = {}
+        for p, data, mode in resolve_files_and_hash(manifest):
+            print(p)
+            if prefix:
+                p = mozpath.join(prefix, p)
+
+            zip.add(p, data, mode=mode)
+
+        sha256_manifest = format_manifest(manifest)
+
+        sdk_path = b'SDK_VERSION'
+        sha256_path = b'MANIFEST.SHA256'
+        if prefix:
+            sdk_path = mozpath.join(prefix, sdk_path)
+            sha256_path = mozpath.join(prefix, sha256_path)
+
+        zip.add(sdk_path, SDK_RELEASE.encode('utf-8'))
+        zip.add(sha256_path, sha256_manifest)
+
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3:
+        print('usage: %s create-zip <filename.zip>' % sys.argv[0])
+        sys.exit(1)
+
+    assert sys.argv[1] == 'create-zip'
+    destzip = sys.argv[2]
+    # TODO make prefix a CLI argument
+    write_zip(destzip, prefix='vs2015u1')
+
+    sha1 = hashlib.sha1()
+    sha256 = hashlib.sha256()
+    sha512 = hashlib.sha512()
+
+    with open(destzip, 'rb') as fh:
+        data = fh.read()
+        sha1.update(data)
+        sha256.update(data)
+        sha512.update(data)
+
+    print('Hashes of %s (size=%d)' % (destzip, len(data)))
+    print('SHA-1:   %s' % sha1.hexdigest())
+    print('SHA-256: %s' % sha256.hexdigest())
+    print('SHA-512: %s' % sha512.hexdigest())
--- a/chrome/moz.build
+++ b/chrome/moz.build
@@ -31,10 +31,10 @@ FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '!/xpcom',
     '/dom/base',
     '/netwerk/base',
     '/netwerk/protocol/res',
     '/xpcom/components'
 ]
 
-if CONFIG['MOZ_ENABLE_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     CXXFLAGS += CONFIG['TK_CFLAGS']
--- a/devtools/shared/Loader.jsm
+++ b/devtools/shared/Loader.jsm
@@ -57,28 +57,38 @@ XPCOMUtils.defineLazyGetter(loaderModule
   };
 });
 XPCOMUtils.defineLazyGetter(loaderModules, "xpcInspector", () => {
   return Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
 });
 XPCOMUtils.defineLazyGetter(loaderModules, "indexedDB", () => {
   // On xpcshell, we can't instantiate indexedDB without crashing
   try {
-    return Cu.Sandbox(this, {wantGlobalProperties:["indexedDB"]}).indexedDB;
+    let sandbox
+      = Cu.Sandbox(CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(),
+                   {wantGlobalProperties: ["indexedDB"]});
+    return sandbox.indexedDB;
+
   } catch(e) {
     return {};
   }
 });
 
 XPCOMUtils.defineLazyGetter(loaderModules, "CSS", () => {
-  return Cu.Sandbox(this, {wantGlobalProperties: ["CSS"]}).CSS;
+  let sandbox
+    = Cu.Sandbox(CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(),
+                 {wantGlobalProperties: ["CSS"]});
+  return sandbox.CSS;
 });
 
 XPCOMUtils.defineLazyGetter(loaderModules, "URL", () => {
-  return Cu.Sandbox(this, {wantGlobalProperties: ["URL"]}).URL;
+  let sandbox
+    = Cu.Sandbox(CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(),
+                 {wantGlobalProperties: ["URL"]});
+  return sandbox.URL;
 });
 
 var sharedGlobalBlocklist = ["sdk/indexed-db"];
 
 /**
  * Used when the tools should be loaded from the Firefox package itself.
  * This is the default case.
  */
--- a/docshell/base/timeline/WorkerTimelineMarker.h
+++ b/docshell/base/timeline/WorkerTimelineMarker.h
@@ -10,17 +10,17 @@
 #include "TimelineMarker.h"
 #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
 
 namespace mozilla {
 
 class WorkerTimelineMarker : public TimelineMarker
 {
 public:
-  WorkerTimelineMarker(ProfileTimelineWorkerOperationType aOperationType,
+  WorkerTimelineMarker(dom::ProfileTimelineWorkerOperationType aOperationType,
                        MarkerTracingType aTracingType)
     : TimelineMarker("Worker", aTracingType, MarkerStackRequest::NO_STACK)
     , mOperationType(aOperationType)
   {}
 
   virtual UniquePtr<AbstractTimelineMarker> Clone() override
   {
     WorkerTimelineMarker* clone = new WorkerTimelineMarker(mOperationType, GetTracingType());
@@ -33,14 +33,14 @@ public:
     TimelineMarker::AddDetails(aCx, aMarker);
 
     if (GetTracingType() == MarkerTracingType::START) {
       aMarker.mWorkerOperation.Construct(mOperationType);
     }
   }
 
 private:
-  ProfileTimelineWorkerOperationType mOperationType;
+  dom::ProfileTimelineWorkerOperationType mOperationType;
 };
 
 } // namespace mozilla
 
 #endif /* mozilla_WorkerTimelineMarker_h_ */
--- a/dom/apps/Webapps.js
+++ b/dom/apps/Webapps.js
@@ -875,32 +875,30 @@ WebappsApplicationMgmt.prototype = {
 
   init: function(aWindow, aHasFullMgmtPrivilege) {
     this._window = aWindow;
 
     this.initDOMRequestHelper(aWindow, ["Webapps:Uninstall:Return:OK",
                                         "Webapps:Uninstall:Broadcast:Return:OK",
                                         "Webapps:Uninstall:Return:KO",
                                         "Webapps:Install:Return:OK",
-                                        "Webapps:GetNotInstalled:Return:OK",
                                         "Webapps:GetIcon:Return",
                                         "Webapps:Import:Return",
                                         "Webapps:ExtractManifest:Return",
                                         "Webapps:SetEnabled:Return"]);
     cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
                           {
                             messages: ["Webapps:Install:Return:OK",
                                        "Webapps:Uninstall:Return:OK",
                                        "Webapps:Uninstall:Broadcast:Return:OK",
                                        "Webapps:SetEnabled:Return"]
                           }
                          );
 
     if (!aHasFullMgmtPrivilege) {
-      this.getNotInstalled = null;
       this.applyDownload = null;
     }
   },
 
   uninit: function() {
     cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
                           ["Webapps:Install:Return:OK",
                            "Webapps:Uninstall:Return:OK",
@@ -956,29 +954,16 @@ WebappsApplicationMgmt.prototype = {
         manifestURL: aApp.manifestURL,
         iconID: aIconID,
         entryPoint: aEntryPoint,
         requestID: aResolverId
       });
     });
   },
 
-  getNotInstalled: function() {
-    let request = this.createRequest();
-    let principal = this._window.document.nodePrincipal;
-
-    cpmm.sendAsyncMessage("Webapps:GetNotInstalled", {
-      oid: this._id,
-      topId: this._topId,
-      requestID: this.getRequestId(request)
-    }, null, principal);
-
-    return request;
-  },
-
   import: function(aBlob) {
     let principal = this._window.document.nodePrincipal;
     return this.createPromiseWithId((aResolverId) => {
       cpmm.sendAsyncMessage("Webapps:Import",
         { blob: aBlob,
           oid: this._id,
           topId: this._topId,
           requestID: aResolverId
@@ -1049,19 +1034,16 @@ WebappsApplicationMgmt.prototype = {
     if (!((msg.oid == this._id && req) ||
           aMessage.name == "Webapps:Install:Return:OK" ||
           aMessage.name == "Webapps:Uninstall:Broadcast:Return:OK" ||
           aMessage.name == "Webapps:SetEnabled:Return")) {
       return;
     }
 
     switch (aMessage.name) {
-      case "Webapps:GetNotInstalled:Return:OK":
-        Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
-        break;
       case "Webapps:Install:Return:OK":
         {
           let app = createContentApplicationObject(this._window, msg.app);
           let event =
             new this._window.MozApplicationEvent("install", { application: app });
           this.__DOM_IMPL__.dispatchEvent(event);
         }
         break;
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -203,17 +203,16 @@ this.DOMApplicationRegistry = {
 
   init: function() {
     // Keep the messages in sync with the lazy-loading in browser.js (bug 1171013).
     this.messages = ["Webapps:Install",
                      "Webapps:Uninstall",
                      "Webapps:GetSelf",
                      "Webapps:CheckInstalled",
                      "Webapps:GetInstalled",
-                     "Webapps:GetNotInstalled",
                      "Webapps:Launch",
                      "Webapps:LocationChange",
                      "Webapps:InstallPackage",
                      "Webapps:GetList",
                      "Webapps:RegisterForMessages",
                      "Webapps:UnregisterForMessages",
                      "Webapps:CancelDownload",
                      "Webapps:CheckForUpdate",
@@ -1299,17 +1298,16 @@ this.DOMApplicationRegistry = {
           Services.prefs.prefHasUserValue("dom.mozApps.homescreenURL") &&
           Services.prefs.getCharPref("dom.mozApps.homescreenURL") ==
           appsService.getManifestURLByLocalId(principal.appId);
 
         allowed = checkPermission("webapps-manage") ||
                   (checkPermission("homescreen-webapps-manage") && isCurrentHomescreen);
         break;
 
-      case "Webapps:GetNotInstalled":
       case "Webapps:ApplyDownload":
       case "Webapps:Import":
       case "Webapps:ExtractManifest":
       case "Webapps:SetEnabled":
         allowed = checkPermission("webapps-manage");
         break;
 
       case "Webapps:RegisterBEP":
@@ -1391,19 +1389,16 @@ this.DOMApplicationRegistry = {
           this.onLocationChange(msg.oid);
           break;
         case "Webapps:CheckInstalled":
           this.checkInstalled(msg, mm);
           break;
         case "Webapps:GetInstalled":
           this.getInstalled(msg, mm);
           break;
-        case "Webapps:GetNotInstalled":
-          this.getNotInstalled(msg, mm);
-          break;
         case "Webapps:InstallPackage": {
           if (AppConstants.platform == "android" && !AppConstants.MOZ_B2GDROID) {
             Services.obs.notifyObservers(mm, "webapps-runtime-install-package", JSON.stringify(msg));
           } else {
             this.doInstallPackage(msg, mm);
           }
           break;
         }
@@ -4333,21 +4328,16 @@ this.DOMApplicationRegistry = {
 
     this._readManifests(tmp).then((aResult) => {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       aMm.sendAsyncMessage("Webapps:GetInstalled:Return:OK", this.formatMessage(aData));
     });
   },
 
-  getNotInstalled: function(aData, aMm) {
-    aData.apps = [];
-    aMm.sendAsyncMessage("Webapps:GetNotInstalled:Return:OK", this.formatMessage(aData));
-  },
-
   getIcon: function(aData, aMm) {
     let sendError = (aError) => {
       debug("getIcon error: " + aError);
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:GetIcon:Return", this.formatMessage(aData));
     };
 
     let app = this.getAppByManifestURL(aData.manifestURL);
--- a/dom/apps/tests/test_list_api.xul
+++ b/dom/apps/tests/test_list_api.xul
@@ -42,17 +42,16 @@ for (var p in props) {
 
 var mgmtProps = {
   addEventListener: "function",
   applyDownload: "function",
   dispatchEvent: "function",
   getEventHandler: "function",
   getAll: "function",
   getIcon: "function",
-  getNotInstalled: "function",
   uninstall: "function",
   oninstall: "object",
   onuninstall: "object",
   onenabledstatechange: "object",
   ownerGlobal: "object",
   removeEventListener: "function",
   setEventHandler: "function",
   extractManifest: "function",
--- a/dom/apps/tests/test_third_party_homescreen.html
+++ b/dom/apps/tests/test_third_party_homescreen.html
@@ -86,17 +86,16 @@ function runApp(aApp, aCallback) {
       var mgmt = content.window.navigator.mozApps.mgmt;
       is(typeof mgmt.getAll, "function", "get getAll");
       is(typeof mgmt.uninstall, "function", "get uninstall");
       is(typeof mgmt.oninstall, "object", "get oninstall");
       is(typeof mgmt.onuninstall, "object", "get onuninstall");
       is(typeof mgmt.onenabledstatechange, "object", "get onenabledstatechange");
 
       [
-        "getNotInstalled",
         "applyDownload",
         "import",
         "extractManifest",
         "setEnabled"
       ].forEach(function(func) {
          is(typeof mgmt[func], "undefined", "shouldn't get" + func);
        });
     } else {
--- a/dom/base/WindowNamedPropertiesHandler.cpp
+++ b/dom/base/WindowNamedPropertiesHandler.cpp
@@ -175,32 +175,34 @@ WindowNamedPropertiesHandler::ownPropNam
 
   // Grab the DOM window.
   nsGlobalWindow* win = xpc::WindowOrNull(JS_GetGlobalForObject(aCx, aProxy));
   nsTArray<nsString> names;
   // The names live on the outer window, which might be null
   nsGlobalWindow* outer = win->GetOuterWindowInternal();
   if (outer) {
     nsDOMWindowList* childWindows = outer->GetWindowList();
-    uint32_t length = childWindows->GetLength();
-    for (uint32_t i = 0; i < length; ++i) {
-      nsCOMPtr<nsIDocShellTreeItem> item =
-        childWindows->GetDocShellTreeItemAt(i);
-      // This is a bit silly, since we could presumably just do
-      // item->GetWindow().  But it's not obvious whether this does the same
-      // thing as GetChildWindow() with the item's name (due to the complexity
-      // of FindChildWithName).  Since GetChildWindow is what we use in
-      // getOwnPropDescriptor, let's try to be consistent.
-      nsString name;
-      item->GetName(name);
-      if (!names.Contains(name)) {
-        // Make sure we really would expose it from getOwnPropDescriptor.
-        nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(name);
-        if (childWin && ShouldExposeChildWindow(name, childWin)) {
-          names.AppendElement(name);
+    if (childWindows) {
+      uint32_t length = childWindows->GetLength();
+      for (uint32_t i = 0; i < length; ++i) {
+        nsCOMPtr<nsIDocShellTreeItem> item =
+          childWindows->GetDocShellTreeItemAt(i);
+        // This is a bit silly, since we could presumably just do
+        // item->GetWindow().  But it's not obvious whether this does the same
+        // thing as GetChildWindow() with the item's name (due to the complexity
+        // of FindChildWithName).  Since GetChildWindow is what we use in
+        // getOwnPropDescriptor, let's try to be consistent.
+        nsString name;
+        item->GetName(name);
+        if (!names.Contains(name)) {
+          // Make sure we really would expose it from getOwnPropDescriptor.
+          nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(name);
+          if (childWin && ShouldExposeChildWindow(name, childWin)) {
+            names.AppendElement(name);
+          }
         }
       }
     }
   }
   if (!AppendNamedPropertyIds(aCx, aProxy, names, false, aProps)) {
     return false;
   }
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1581,16 +1581,27 @@ nsDocument::~nsDocument()
       // record mixed object subrequest telemetry
       if (mHasMixedContentObjectSubrequest) {
         /* mixed object subrequest loaded on page*/
         Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 1);
       } else {
         /* no mixed object subrequests loaded on page*/
         Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 0);
       }
+
+      // record CSP telemetry on this document
+      if (mHasCSP) {
+        Accumulate(Telemetry::CSP_DOCUMENTS_COUNT, 1);
+      }
+      if (mHasUnsafeInlineCSP) {
+        Accumulate(Telemetry::CSP_UNSAFE_INLINE_DOCUMENTS_COUNT, 1);
+      }
+      if (mHasUnsafeEvalCSP) {
+        Accumulate(Telemetry::CSP_UNSAFE_EVAL_DOCUMENTS_COUNT, 1);
+      }
     }
   }
 
   ReportUseCounters();
 
   mInDestructor = true;
   mInUnlinkOrDeletion = true;
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -627,16 +627,40 @@ public:
    * Set the mixed content object subrequest flag for this document.
    */
   void SetHasMixedContentObjectSubrequest(bool aHasMixedContentObjectSubrequest)
   {
     mHasMixedContentObjectSubrequest = aHasMixedContentObjectSubrequest;
   }
 
   /**
+   * Set CSP flag for this document.
+   */
+  void SetHasCSP(bool aHasCSP)
+  {
+    mHasCSP = aHasCSP;
+  }
+
+  /**
+   * Set unsafe-inline CSP flag for this document.
+   */
+  void SetHasUnsafeInlineCSP(bool aHasUnsafeInlineCSP)
+  {
+    mHasUnsafeInlineCSP = aHasUnsafeInlineCSP;
+  }
+
+  /**
+   * Set unsafe-eval CSP flag for this document.
+   */
+  void SetHasUnsafeEvalCSP(bool aHasUnsafeEvalCSP)
+  {
+    mHasUnsafeEvalCSP = aHasUnsafeEvalCSP;
+  }
+
+  /**
    * Get tracking content blocked flag for this document.
    */
   bool GetHasTrackingContentBlocked()
   {
     return mHasTrackingContentBlocked;
   }
 
   /**
@@ -2929,16 +2953,25 @@ protected:
   bool mHasMixedDisplayContentLoaded : 1;
 
   // True if a document has blocked Mixed Display/Passive Content (see nsMixedContentBlocker.cpp)
   bool mHasMixedDisplayContentBlocked : 1;
 
   // True if a document loads a plugin object that attempts to load mixed content subresources through necko(see nsMixedContentBlocker.cpp)
   bool mHasMixedContentObjectSubrequest : 1;
 
+  // True if a document load has a CSP attached.
+  bool mHasCSP : 1;
+
+  // True if a document load has a CSP with unsafe-eval attached.
+  bool mHasUnsafeEvalCSP : 1;
+
+  // True if a document load has a CSP with unsafe-inline attached.
+  bool mHasUnsafeInlineCSP : 1;
+
   // True if a document has blocked Tracking Content
   bool mHasTrackingContentBlocked : 1;
 
   // True if a document has loaded Tracking Content
   bool mHasTrackingContentLoaded : 1;
 
   // True if DisallowBFCaching has been called on this document.
   bool mBFCacheDisallowed : 1;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2447,17 +2447,20 @@ ConvertJSValueToByteString(JSContext* cx
     }
   } else {
     length = js::GetStringLength(s);
   }
 
   static_assert(js::MaxStringLength < UINT32_MAX,
                 "length+1 shouldn't overflow");
 
-  result.SetLength(length);
+  if (!result.SetLength(length, fallible)) {
+    return false;
+  }
+
   JS_EncodeStringToBuffer(cx, s, result.BeginWriting(), length);
 
   return true;
 }
 
 bool
 IsInPrivilegedApp(JSContext* aCx, JSObject* aObj)
 {
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -500,17 +500,16 @@ DOMInterfaces = {
     'implicitJSContext': [ 'respondWith' ],
 },
 
 'FileReader': {
     'implicitJSContext': [ 'readAsArrayBuffer' ],
 },
 
 'FileReaderSync': {
-    'workers': True,
     'wrapperCache': False,
 },
 
 'FontFaceSet': {
     'implicitJSContext': [ 'load' ],
 },
 
 'FontFaceSetIterator': {
@@ -931,23 +930,21 @@ DOMInterfaces = {
 
 'PropertyNodeList': {
     'headerFile': 'HTMLPropertiesCollection.h',
 },
 
 'PushEvent': {
     'headerFile': 'ServiceWorkerEvents.h',
     'nativeType': 'mozilla::dom::workers::PushEvent',
-    'workers': True
 },
 
 'PushMessageData': {
     'headerFile': 'ServiceWorkerEvents.h',
     'nativeType': 'mozilla::dom::workers::PushMessageData',
-    'workers': True
 },
 
 'PushManager': [{
     'workers': False,
     'headerFile': 'mozilla/dom/PushManager.h',
     'nativeType': 'mozilla::dom::PushManager',
 }, {
     'workers': True,
@@ -1609,21 +1606,16 @@ DOMInterfaces = {
     # Rename a few things so we don't have both classes and methods
     # with the same name
     'binaryNames': {
         'console': 'getConsole',
         'performance': 'getPerformance',
     },
 },
 
-'WorkerLocation': {
-    'headerFile': 'mozilla/dom/workers/bindings/Location.h',
-    'workers': True,
-},
-
 'WorkerNavigator': {
     'headerFile': 'mozilla/dom/workers/bindings/Navigator.h',
     'workers': True,
     'implicitJSContext': ['getDataStores'],
 },
 
 'XMLHttpRequest': [
 {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -991,19 +991,20 @@ CanvasRenderingContext2D::~CanvasRenderi
     mUserDatas[i]->Forget();
   }
   sNumLivingContexts--;
   if (!sNumLivingContexts) {
     NS_IF_RELEASE(sErrorTarget);
   }
 #ifdef USE_SKIA_GPU
   if (mVideoTexture) {
-    MOZ_ASSERT(gfxPlatform::GetPlatform()->GetSkiaGLGlue(), "null SkiaGLGlue");
-    gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext()->MakeCurrent();
-    gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext()->fDeleteTextures(1, &mVideoTexture);
+    SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
+    MOZ_ASSERT(glue);
+    glue->GetGLContext()->MakeCurrent();
+    glue->GetGLContext()->fDeleteTextures(1, &mVideoTexture);
   }
 #endif
 
   RemoveDemotableContext(this);
 }
 
 JSObject*
 CanvasRenderingContext2D::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
@@ -4469,18 +4470,19 @@ CanvasRenderingContext2D::DrawImage(cons
 
   nsLayoutUtils::DirectDrawInfo drawInfo;
 
 #ifdef USE_SKIA_GPU
   if (mRenderingMode == RenderingMode::OpenGLBackendMode &&
       mIsSkiaGL &&
       !srcSurf &&
       aImage.IsHTMLVideoElement() &&
-      gfxPlatform::GetPlatform()->GetSkiaGLGlue()) {
+      gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) {
     mozilla::gl::GLContext* gl = gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext();
+    MOZ_ASSERT(gl);
 
     HTMLVideoElement* video = &aImage.GetAsHTMLVideoElement();
     if (!video) {
       return;
     }
 
 #ifdef MOZ_EME
     if (video->ContainsRestrictedContent()) {
@@ -5641,17 +5643,17 @@ CanvasRenderingContext2D::GetCanvasLayer
   if (!mResetLayer && aOldLayer) {
     CanvasRenderingContext2DUserData* userData =
       static_cast<CanvasRenderingContext2DUserData*>(
         aOldLayer->GetUserData(&g2DContextLayerUserData));
 
     CanvasLayer::Data data;
 
     GLuint skiaGLTex = SkiaGLTex();
-    if (skiaGLTex) {
+    if (mIsSkiaGL && skiaGLTex) {
       SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
       MOZ_ASSERT(glue);
 
       data.mGLContext = glue->GetGLContext();
       data.mFrontbufferGLTex = skiaGLTex;
       PersistentBufferProvider *provider = GetBufferProvider(aManager);
       data.mBufferProvider = provider;
     } else {
@@ -5695,17 +5697,17 @@ CanvasRenderingContext2D::GetCanvasLayer
   CanvasLayer::Data data;
   data.mSize = nsIntSize(mWidth, mHeight);
   data.mHasAlpha = !mOpaque;
 
   canvasLayer->SetPreTransactionCallback(
           CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
 
   GLuint skiaGLTex = SkiaGLTex();
-  if (skiaGLTex) {
+  if (mIsSkiaGL && skiaGLTex) {
     SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
     MOZ_ASSERT(glue);
 
     data.mGLContext = glue->GetGLContext();
     data.mFrontbufferGLTex = skiaGLTex;
     PersistentBufferProvider *provider = GetBufferProvider(aManager);
     data.mBufferProvider = provider;
   } else {
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -735,20 +735,21 @@ IMEContentObserver::HandleQueryContentEv
   MOZ_LOG(sIMECOLog, LogLevel::Debug,
     ("IMECO: 0x%p IMEContentObserver::HandleQueryContentEvent(aEvent={ "
      "mMessage=%s })", this, ToChar(aEvent->mMessage)));
 
   AutoRestore<bool> handling(mIsHandlingQueryContentEvent);
   mIsHandlingQueryContentEvent = true;
   ContentEventHandler handler(GetPresContext());
   nsresult rv = handler.HandleQueryContentEvent(aEvent);
-  if (aEvent->mSucceeded) {
-    // We need to guarantee that mRootContent should be always same value for
-    // the observing editor.
-    aEvent->mReply.mContentsRoot = mRootContent;
+
+  if (!IsInitializedWithPlugin() &&
+      NS_WARN_IF(aEvent->mReply.mContentsRoot != mRootContent)) {
+    // Focus has changed unexpectedly, so make the query fail.
+    aEvent->mSucceeded = false;
   }
   return rv;
 }
 
 bool
 IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
                                        WidgetMouseEvent* aMouseEvent)
 {
@@ -1256,17 +1257,18 @@ IMEContentObserver::UpdateSelectionCache
 
   mSelectionData.ClearSelectionData();
 
   // XXX Cannot we cache some information for reducing the cost to compute
   //     selection offset and writing mode?
   WidgetQueryContentEvent selection(true, eQuerySelectedText, mWidget);
   ContentEventHandler handler(GetPresContext());
   handler.OnQuerySelectedText(&selection);
-  if (NS_WARN_IF(!selection.mSucceeded)) {
+  if (NS_WARN_IF(!selection.mSucceeded) ||
+      NS_WARN_IF(selection.mReply.mContentsRoot != mRootContent)) {
     return false;
   }
 
   mFocusedWidget = selection.mReply.mFocusedWidget;
   mSelectionData.mOffset = selection.mReply.mOffset;
   *mSelectionData.mString = selection.mReply.mString;
   mSelectionData.SetWritingMode(selection.GetWritingMode());
   mSelectionData.mReversed = selection.mReply.mReversed;
--- a/dom/html/test/chrome.ini
+++ b/dom/html/test/chrome.ini
@@ -1,7 +1,6 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g' || os == 'android'
 support-files =
   file_anchor_ping.html
 
-[test_allowMedia.html]
 [test_anchor_ping.html]
--- a/dom/html/test/mochitest.ini
+++ b/dom/html/test/mochitest.ini
@@ -603,8 +603,9 @@ skip-if = buildapp == 'b2g' || (e10s && 
 [test_image_clone_load.html]
 [test_bug1203668.html]
 [test_bug1166138.html]
 [test_bug1230665.html]
 [test_filepicker_default_directory.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
 [test_bug1233598.html]
 [test_bug1250401.html]
+[test_allowMedia.html]
--- a/dom/html/test/test_allowMedia.html
+++ b/dom/html/test/test_allowMedia.html
@@ -1,18 +1,18 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=759964
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 759964</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
 
   /** Test for Bug 759964 **/
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(runNextTest);
 
 var SJS = "http://mochi.test:8888/tests/dom/html/test/allowMedia.sjs";
@@ -30,60 +30,52 @@ function runNextTest() {
 }
 
 var tests = [
 
   // Set allowMedia = false, load a page with <audio>, verify the <audio>
   // doesn't load its source.
   function basic() {
     var iframe = insertIframe();
-    docshellForWindow(iframe.contentWindow).allowMedia = false;
+    SpecialPowers.allowMedia(iframe.contentWindow, false);
     loadIframe(iframe, TEST_PAGE, function () {
       verifyPass();
       iframe.remove();
       runNextTest();
     });
   },
 
   // Set allowMedia = false on parent docshell, load a page with <audio> in a
   // child iframe, verify the <audio> doesn't load its source.
   function inherit() {
-    var docshell = docshellForWindow(window);
-    docshell.allowMedia = false;
+    SpecialPowers.allowMedia(window, false);
 
     var iframe = insertIframe();
     loadIframe(iframe, TEST_PAGE, function () {
       verifyPass();
       iframe.remove();
-      docshell.allowMedia = true;
+      SpecialPowers.allowMedia(window, true);
       runNextTest();
     });
   },
 
   // In a display:none iframe, set allowMedia = false, load a page with <audio>,
   // verify the <audio> doesn't load its source.
   function displayNone() {
     var iframe = insertIframe();
     iframe.style.display = "none";
-    docshellForWindow(iframe.contentWindow).allowMedia = false;
+    SpecialPowers.allowMedia(iframe.contentWindow, false);
     loadIframe(iframe, TEST_PAGE, function () {
       verifyPass();
       iframe.remove();
       runNextTest();
     });
   },
 ];
 
-function docshellForWindow(win) {
-  return win.
-         QueryInterface(Ci.nsIInterfaceRequestor).
-         getInterface(Ci.nsIWebNavigation).
-         QueryInterface(Ci.nsIDocShell);
-}
-
 function insertIframe() {
   var iframe = document.createElement("iframe");
   document.body.appendChild(iframe);
   return iframe;
 }
 
 function loadIframe(iframe, url, onDone) {
   iframe.setAttribute("src", url);
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -200,16 +200,20 @@ BenchmarkPlayback::InitDecoder(TrackInfo
     });
 }
 
 void
 BenchmarkPlayback::MainThreadShutdown()
 {
   MOZ_ASSERT(OnThread());
 
+  if (mFinished) {
+    // Nothing more to do.
+    return;
+  }
   mFinished = true;
 
   if (mDecoder) {
     mDecoder->Flush();
     mDecoder->Shutdown();
     mDecoder = nullptr;
   }
 
--- a/dom/media/webaudio/moz.build
+++ b/dom/media/webaudio/moz.build
@@ -10,18 +10,16 @@ with Files('*'):
 DIRS += ['blink']
 
 TEST_DIRS += ['compiledtest']
 
 MOCHITEST_MANIFESTS += [
     'test/mochitest.ini',
 ]
 
-MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
-
 TEST_HARNESS_FILES.testing.mochitest.tests.dom.media.webaudio.test.blink += [
     'test/blink/audio-testing.js',
     'test/blink/convolution-testing.js',
     'test/blink/panner-model-testing.js',
 ]
 
 EXPORTS += [
     'AlignedTArray.h',
deleted file mode 100644
--- a/dom/media/webaudio/test/chrome.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[DEFAULT]
-skip-if = buildapp == 'b2g'
-
-[test_AudioNodeDevtoolsAPI.html]
-[test_bug1027864.html]
-[test_AudioParamDevtoolsAPI.html]
-[test_ScriptProcessorCollected1.html]
--- a/dom/media/webaudio/test/mochitest.ini
+++ b/dom/media/webaudio/test/mochitest.ini
@@ -50,16 +50,18 @@ skip-if = (toolkit == 'gonk') || (toolki
 [test_audioBufferSourceNodeRate.html]
 [test_AudioContext.html]
 skip-if = android_version == '10' # bug 1138462
 [test_audioContextSuspendResumeClose.html]
 skip-if = buildapp == 'mulet'
 tags=capturestream
 [test_audioDestinationNode.html]
 [test_AudioListener.html]
+[test_AudioNodeDevtoolsAPI.html]
+[test_AudioParamDevtoolsAPI.html]
 [test_audioParamExponentialRamp.html]
 [test_audioParamGain.html]
 [test_audioParamLinearRamp.html]
 [test_audioParamSetCurveAtTime.html]
 [test_audioParamSetCurveAtTimeTwice.html]
 [test_audioParamSetCurveAtTimeZeroDuration.html]
 [test_audioParamSetTargetAtTime.html]
 [test_audioParamSetValueAtTime.html]
@@ -83,16 +85,17 @@ tags=capturestream
 [test_bug875402.html]
 [test_bug894150.html]
 [test_bug956489.html]
 [test_bug964376.html]
 [test_bug966247.html]
 tags=capturestream
 [test_bug972678.html]
 [test_bug1118372.html]
+[test_bug1027864.html]
 [test_bug1056032.html]
 skip-if = toolkit == 'android' # bug 1056706
 [test_channelMergerNode.html]
 [test_channelMergerNodeWithVolume.html]
 [test_channelSplitterNode.html]
 [test_channelSplitterNodeWithVolume.html]
 skip-if = (android_version == '18' && debug) # bug 1158417
 [test_convolverNode.html]
@@ -163,16 +166,17 @@ skip-if = (toolkit == 'gonk' && !debug) 
 [test_pannerNodeChannelCount.html]
 [test_pannerNodeHRTFSymmetry.html]
 [test_pannerNodeTail.html]
 [test_pannerNode_maxDistance.html]
 [test_stereoPannerNode.html]
 [test_stereoPannerNodePassThrough.html]
 [test_periodicWave.html]
 [test_periodicWaveBandLimiting.html]
+[test_ScriptProcessorCollected1.html]
 [test_scriptProcessorNode.html]
 [test_scriptProcessorNodeChannelCount.html]
 [test_scriptProcessorNodePassThrough.html]
 [test_scriptProcessorNode_playbackTime1.html]
 [test_scriptProcessorNodeZeroInputOutput.html]
 [test_scriptProcessorNodeNotConnected.html]
 [test_sequentialBufferSourceWithResampling.html]
 [test_singleSourceDest.html]
--- a/dom/media/webaudio/test/test_AudioNodeDevtoolsAPI.html
+++ b/dom/media/webaudio/test/test_AudioNodeDevtoolsAPI.html
@@ -1,51 +1,53 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test the devtool AudioNode API</title>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-  Components.utils.import('resource://gre/modules/Services.jsm');
+  SimpleTest.waitForExplicitFinish();
 
-  SimpleTest.waitForExplicitFinish();
+  function id(node) {
+    return SpecialPowers.getPrivilegedProps(node, "id");
+  }
 
   var ac = new AudioContext();
   var ids;
   var weak;
   (function() {
     var src1 = ac.createBufferSource();
     var src2 = ac.createBufferSource();
-    ok(src2.id > src1.id, "The ID should be monotonic");
-    ok(src1.id > ac.destination.id, "The ID of the destination node should be the lowest");
-    ids = [src1.id, src2.id];
-    weak = Components.utils.getWeakReference(src1);
-    is(weak.get(), src1, "The node should support a weak reference");
+    ok(id(src2) > id(src1), "The ID should be monotonic");
+    ok(id(src1) > id(ac.destination), "The ID of the destination node should be the lowest");
+    ids = [id(src1), id(src2)];
+    weak = SpecialPowers.Cu.getWeakReference(src1);
+    is(SpecialPowers.unwrap(weak.get()), src1, "The node should support a weak reference");
   })();
   function observer(subject, topic, data) {
     var id = parseInt(data);
     var index = ids.indexOf(id);
     if (index != -1) {
       info("Dropping id " + id + " at index " + index);
       ids.splice(index, 1);
       if (ids.length == 0) {
         SimpleTest.executeSoon(function() {
           is(weak.get(), null, "The weak reference must be dropped now");
-          Services.obs.removeObserver(observer, "webaudio-node-demise");
+          SpecialPowers.removeObserver(observer, "webaudio-node-demise");
           SimpleTest.finish();
         });
       }
     }
   }
-  Services.obs.addObserver(observer, "webaudio-node-demise", false);
+  SpecialPowers.addObserver(observer, "webaudio-node-demise", false);
 
   forceCC();
   forceCC();
 
   function forceCC() {
     SpecialPowers.DOMWindowUtils.cycleCollect();
     SpecialPowers.DOMWindowUtils.garbageCollect();
     SpecialPowers.DOMWindowUtils.garbageCollect();
--- a/dom/media/webaudio/test/test_AudioParamDevtoolsAPI.html
+++ b/dom/media/webaudio/test/test_AudioParamDevtoolsAPI.html
@@ -1,24 +1,25 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test the devtool AudioParam API</title>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-  Components.utils.import('resource://gre/modules/Services.jsm');
-
   function checkIdAndName(node, name) {
-    is(node.id, node[name].parentNodeId, "The parent id should be correct");
-    is(node[name].name, name, "The name of the AudioParam should be correct.");
+    is(SpecialPowers.getPrivilegedProps(node, "id"),
+       SpecialPowers.getPrivilegedProps(node[name], "parentNodeId"),
+       "The parent id should be correct");
+    is(SpecialPowers.getPrivilegedProps(node[name], "name"), name,
+       "The name of the AudioParam should be correct.");
   }
 
   var ac = new AudioContext(),
       gain = ac.createGain(),
       osc = ac.createOscillator(),
       del = ac.createDelay(),
       source = ac.createBufferSource(),
       stereoPanner = ac.createStereoPanner(),
--- a/dom/media/webaudio/test/test_ScriptProcessorCollected1.html
+++ b/dom/media/webaudio/test/test_ScriptProcessorCollected1.html
@@ -1,35 +1,34 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test ScriptProcessorNode in cycle with no listener is collected</title>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script class="testbody" type="text/javascript">
 
-Components.utils.import('resource://gre/modules/Services.jsm');
 SimpleTest.waitForExplicitFinish();
 
 var observer = function(subject, topic, data) {
   var id = parseInt(data);
   var index = ids.indexOf(id);
   if (index != -1) {
     ok(true, "Collected AudioNode id " + id + " at index " + index);
     ids.splice(index, 1);
   }
 }
 
-Services.obs.addObserver(observer, "webaudio-node-demise", false);
+SpecialPowers.addObserver(observer, "webaudio-node-demise", false);
 
 SimpleTest.registerCleanupFunction(function() {
   if (observer) {
-    Services.obs.removeObserver(observer, "webaudio-node-demise");
+    SpecialPowers.removeObserver(observer, "webaudio-node-demise");
   }
 });
 
 var ac = new AudioContext();
 
 var testProcessor = ac.createScriptProcessor(256, 1, 0);
 var delay = ac.createDelay();
 testProcessor.connect(delay);
@@ -54,28 +53,32 @@ testProcessor.onaudioprocess = function(
     break;
   case 3:
     // Another GC should not be required after testProcessor would have
     // received another audioprocess event.
     SpecialPowers.forceCC();
     // Expect that webaudio-demise has been queued.
     // Queue another event to check.
     SimpleTest.executeSoon(function() {
-      Services.obs.removeObserver(observer, "webaudio-node-demise");
+      SpecialPowers.removeObserver(observer, "webaudio-node-demise");
       observer = null;
       event.target.onaudioprocess = null;
       ok(ids.length == 0, "All expected nodes should be collected");
       SimpleTest.finish();
     });
     break;
   }
 };
 
+function id(node) {
+  return SpecialPowers.getPrivilegedProps(node, "id");
+}
+
 // Nodes with these ids should be collected.
-var ids = [ testProcessor.id, delay.id, gain.id ];
+var ids = [ id(testProcessor), id(delay), id(gain) ];
 testProcessor = null;
 delay = null;
 gain = null;
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/webaudio/test/test_bug1027864.html
+++ b/dom/media/webaudio/test/test_bug1027864.html
@@ -1,40 +1,43 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test bug 1027864</title>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-Components.utils.import('resource://gre/modules/Services.jsm');
 SimpleTest.waitForExplicitFinish();
 
 function observer(subject, topic, data) {
   var id = parseInt(data);
   var index = ids.indexOf(id);
   if (index != -1) {
     ok(true, "Dropping id " + id + " at index " + index);
     ids.splice(index, 1);
     if (ids.length == 0) {
       SimpleTest.executeSoon(function() {
         SimpleTest.finish();
       });
     }
   }
 }
 
-Services.obs.addObserver(observer, "webaudio-node-demise", false);
+function id(node) {
+  return SpecialPowers.getPrivilegedProps(node, "id");
+}
+
+SpecialPowers.addObserver(observer, "webaudio-node-demise", false);
 
 SimpleTest.registerCleanupFunction(function() {
-  Services.obs.removeObserver(observer, "webaudio-node-demise");
+  SpecialPowers.removeObserver(observer, "webaudio-node-demise");
 });
 
 var ac = new AudioContext();
 var ids;
 
 (function() {
   var delay = ac.createDelay();
   delay.delayTime.value = 0.03;
@@ -48,17 +51,17 @@ var ids;
   gain.connect(ac.destination);
 
   var source = ac.createOscillator();
 
   source.connect(gain);
   source.start(ac.currentTime);
   source.stop(ac.currentTime + 0.1);
 
-  ids = [ delay.id, gain.id, source.id ];
+  ids = [ id(delay), id(gain), id(source) ];
 })();
 
 setInterval(function() {
   forceCC();
 }, 200);
 
 function forceCC() {
   SpecialPowers.DOMWindowUtils.cycleCollect();
--- a/dom/media/webspeech/synth/speechd/SpeechDispatcherService.cpp
+++ b/dom/media/webspeech/synth/speechd/SpeechDispatcherService.cpp
@@ -12,17 +12,23 @@
 #include "nsEscape.h"
 #include "nsISupports.h"
 #include "nsPrintfCString.h"
 #include "nsReadableUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "prlink.h"
 
-#define URI_PREFIX "urn:moz-tts:sapi:"
+#include <math.h>
+#include <stdlib.h>
+
+#define URI_PREFIX "urn:moz-tts:speechd:"
+
+#define MAX_RATE static_cast<float>(2.5)
+#define MIN_RATE static_cast<float>(0.5)
 
 // Some structures for libspeechd
 typedef enum {
   SPD_EVENT_BEGIN,
   SPD_EVENT_END,
   SPD_EVENT_INDEX_MARK,
   SPD_EVENT_CANCEL,
   SPD_EVENT_PAUSE,
@@ -468,27 +474,28 @@ SpeechDispatcherService::Speak(const nsA
   }
 
   spd_set_synthesis_voice(mSpeechdClient,
                           NS_ConvertUTF16toUTF8(voice->mName).get());
 
   // We provide a volume of 0.0 to 1.0, speech-dispatcher expects 0 - 100.
   spd_set_volume(mSpeechdClient, static_cast<int>(aVolume * 100));
 
-  // We provide a rate of 0.1 to 10 with 1 being default.
-  // speech-dispatcher expects -100 to 100 with 0 being default.
-  int rate = 0;
-
+  // aRate is a value of 0.1 (0.1x) to 10 (10x) with 1 (1x) being normal rate.
+  // speechd expects -100 to 100 with 0 being normal rate.
+  float rate = 0;
   if (aRate > 1) {
-    rate = static_cast<int>((aRate - 1) * 10);
-  } else if (aRate <= 1) {
-    rate = static_cast<int>((aRate - 1) * (100/0.9));
+    // Each step to 100 is logarithmically distributed up to 2.5x.
+    rate = log10(std::min(aRate, MAX_RATE)) / log10(MAX_RATE) * 100;
+  } else if (aRate < 1) {
+    // Each step to -100 is logarithmically distributed down to 0.5x.
+    rate = log10(std::max(aRate, MIN_RATE)) / log10(MIN_RATE) * -100;
   }
 
-  spd_set_voice_rate(mSpeechdClient, rate);
+  spd_set_voice_rate(mSpeechdClient, static_cast<int>(rate));
 
   // We provide a pitch of 0 to 2 with 1 being the default.
   // speech-dispatcher expects -100 to 100 with 0 being default.
   spd_set_voice_pitch(mSpeechdClient, static_cast<int>((aPitch - 1) * 100));
 
   // The last three parameters don't matter for an indirect service
   nsresult rv = aTask->Setup(callback, 0, 0, 0);
 
--- a/dom/media/webspeech/synth/windows/SapiService.cpp
+++ b/dom/media/webspeech/synth/windows/SapiService.cpp
@@ -326,20 +326,31 @@ SapiService::Speak(const nsAString& aTex
   RefPtr<ISpObjectToken> voiceToken;
   if (!mVoices.Get(aUri, getter_AddRefs(voiceToken))) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (FAILED(mSapiClient->SetVoice(voiceToken))) {
     return NS_ERROR_FAILURE;
   }
+
   if (FAILED(mSapiClient->SetVolume(static_cast<USHORT>(aVolume * 100)))) {
     return NS_ERROR_FAILURE;
   }
-  if (FAILED(mSapiClient->SetRate(static_cast<long>(10 * log10(aRate))))) {
+
+  // The max supported rate in SAPI engines is 3x, and the min is 1/3x. It is
+  // expressed by an integer. 0 being normal rate, -10 is 1/3 and 10 is 3x.
+  // Values below and above that are allowed, but the engine may clip the rate
+  // to its maximum capable value.
+  // "Each increment between -10 and +10 is logarithmically distributed such
+  //  that incrementing or decrementing by 1 is multiplying or dividing the
+  //  rate by the 10th root of 3"
+  // https://msdn.microsoft.com/en-us/library/ee431826(v=vs.85).aspx
+  long rate = aRate != 0 ? static_cast<long>(10 * log10(aRate) / log10(3)) : 0;
+  if (FAILED(mSapiClient->SetRate(rate))) {
     return NS_ERROR_FAILURE;
   }
 
   // Set the pitch using xml
   nsAutoString xml;
   xml.AssignLiteral("<pitch absmiddle=\"");
   xml.AppendFloat(aPitch * 10.0f - 10.0f);
   xml.AppendLiteral("\">");
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -67,17 +67,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     UNIFIED_SOURCES += [
         'nsPluginNativeWindow.cpp',
         'nsPluginsDirDarwin.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'nsPluginsDirUnix.cpp',
     ]
-    if CONFIG['MOZ_ENABLE_GTK']:
+    if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         # This file cannot be built in unified mode because of name clashes in X11 headers.
         SOURCES += [
             'nsPluginNativeWindowGtk.cpp',
         ]
     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
         UNIFIED_SOURCES += [
             'nsPluginNativeWindowQt.cpp',
         ]
--- a/dom/plugins/base/nsPluginsDirUnix.cpp
+++ b/dom/plugins/base/nsPluginsDirUnix.cpp
@@ -199,17 +199,17 @@ static void LoadExtraSharedLibs()
                 // otherwise it'll decrease performance by calling popen() in SearchForSoname
                 // every time for each bogus name
                 prefs->SetCharPref(PREF_PLUGINS_SONAME, (const char *)sonameListToSave);
             }
             PL_strfree(sonameList);
         }
     }
 }
-#endif //MOZ_WIDGET_GTK2
+#endif //MOZ_WIDGET_GTK == 2
 
 /* nsPluginsDir implementation */
 
 bool nsPluginsDir::IsPluginFile(nsIFile* file)
 {
     nsAutoCString filename;
     if (NS_FAILED(file->GetNativeLeafName(filename)))
         return false;
@@ -297,17 +297,17 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
         if (!pLibrary) {
             DisplayPR_LoadLibraryErrorMessage(libSpec.value.pathname);
             return NS_ERROR_FAILURE;
         }
     }
 #else
     *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
     pLibrary = *outLibrary;
-#endif  // MOZ_WIDGET_GTK2
+#endif  // MOZ_WIDGET_GTK == 2
 
 #ifdef DEBUG
     printf("LoadPlugin() %s returned %lx\n", 
            libSpec.value.pathname, (unsigned long)pLibrary);
 #endif
 
     if (!pLibrary) {
         return NS_ERROR_FAILURE;
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/file_checkcookie.sjs
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+function handleRequest(request, response) {
+  try {
+    var cookie = request.getHeader("Cookie");
+  } catch (e) {
+    cookie = "EMPTY_COOKIE";
+  }
+
+  // avoid confusing cache behaviors.
+  response.setHeader("Cache-Control", "no-cache", false);
+  // allow XHR requests accross origin.
+  response.setHeader("Access-control-allow-origin", "*");
+  response.setHeader("Content-type", "text/plain", false);
+  response.setStatusLine(request.httpVersion, "200", "OK");
+  response.write(cookie);
+}
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/file_setcookie.html
@@ -0,0 +1,9 @@
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+    <head>
+        <meta charset=UTF-8>
+    <body>
+        <script>document.cookie = "found=another_cookie";</script>
+    </body>
+</html>
--- a/dom/plugins/test/mochitest/mochitest.ini
+++ b/dom/plugins/test/mochitest/mochitest.ini
@@ -91,16 +91,20 @@ skip-if = release_build # Bug 1172627
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(needs plugin support) b2g-debug(needs plugin support) b2g-desktop(needs plugin support)
 [test_painting.html]
 skip-if = (toolkit == "cocoa" && e10s) # bug 1252230
 [test_plugin_scroll_invalidation.html]
 skip-if = toolkit != "gtk2"
 support-files = plugin_scroll_invalidation.html
 [test_plugin_scroll_painting.html]
 skip-if = true # Bug 596491
+[test_pluginstream_3rdparty.html]
+support-files =
+  file_checkcookie.sjs
+  file_setcookie.html
 [test_pluginstream_asfile.html]
 [test_pluginstream_asfileonly.html]
 [test_pluginstream_err.html]
 [test_pluginstream_geturl.html]
 [test_pluginstream_geturlnotify.html]
 [test_pluginstream_newstream.html]
 [test_pluginstream_post.html]
 [test_pluginstream_poststream.html]
@@ -128,9 +132,9 @@ skip-if = os != "win"
 skip-if = !(os == "win" && processor == "x86_64" && !e10s) # Bug 1253957
 [test_windowless_ime.html]
 skip-if = os != "win" || e10s
 [test_visibility.html]
 skip-if = toolkit == "cocoa"
 [test_zero_opacity.html]
 [test_bug1165981.html]
 skip-if = !(os == "win" && processor == "x86_64" && !e10s) # Bug 1253957
-[test_bug1245545.html]
\ No newline at end of file
+[test_bug1245545.html]
--- a/dom/plugins/test/mochitest/pluginstream.js
+++ b/dom/plugins/test/mochitest/pluginstream.js
@@ -1,15 +1,20 @@
   SimpleTest.waitForExplicitFinish();
 
-  function frameLoaded() {
+  function frameLoaded(finishWhenCalled = true, lastObject = false) {
     var testframe = document.getElementById('testframe');
-    var embed = document.getElementsByTagName('embed')[0];
+    function getNode(list) {
+      if (list.length === 0)
+        return undefined;
+      return lastObject ? list[list.length - 1] : list[0];
+    }
+    var embed = getNode(document.getElementsByTagName('embed'));
     if (undefined === embed)
-      embed = document.getElementsByTagName('object')[0];
+      embed = getNode(document.getElementsByTagName('object'));
 
     // In the file:// URI case, this ends up being cross-origin.
     // Skip these checks in that case.
     if (testframe.contentDocument) {
       var content = testframe.contentDocument.body.innerHTML;
       if (!content.length)
         return;
 
@@ -23,10 +28,12 @@
       req.overrideMimeType('text/plain; charset=x-user-defined');
       req.send(null);
       is(req.status, 200, "bad XMLHttpRequest status");
       is(content, req.responseText.replace(/\r\n/g, "\n"),
          "content doesn't match");
     }
 
     is(embed.getError(), "pass", "plugin reported error");
-    SimpleTest.finish();
+    if (finishWhenCalled) {
+      SimpleTest.finish();
+    }
   }
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_pluginstream_3rdparty.html
@@ -0,0 +1,76 @@
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <title>NPAPI NPN_GetURL NPStream Test</title>
+  <meta charset=UTF-8>
+  <script type="text/javascript"
+          src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript"
+          src="pluginstream.js"></script>
+  <script type="text/javascript" src="plugin-utils.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript">
+    setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+  </script>
+  <link rel="stylesheet" type="text/css"
+        href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+  <p id="display"></p>
+
+  <iframe id="testframe" name="testframe"></iframe>
+
+  <script>
+    /**
+     * Tests that we still properly do or don't send cookies for requests from
+     * plugins when the user has disabled 3rd-party cookies. See
+     * pluginstream.js where we verify that we get the same content as for XHR
+     * requests.
+     */
+    SimpleTest.waitForExplicitFinish();
+    function get_embed_elt() {
+      var e = document.createElement("embed");
+      e.setAttribute("streammode", "normal");
+      e.setAttribute("streamchunksize", "1024");
+      e.setAttribute("frame", "testframe");
+      e.setAttribute("id", "embedtest");
+      e.setAttribute("style", "width: 400px; height: 100px;");
+      e.setAttribute("type", "application/x-test");
+      return e;
+    }
+
+    function* test_runner() {
+      function create_embed(host) {
+        var e = get_embed_elt();
+
+        const url =
+          `http://${host}/tests/dom/plugins/test/mochitest/file_checkcookie.sjs`;
+        e.setAttribute('geturl', url);
+        document.body.appendChild(e);
+
+        return new Promise(resolve => {
+          $('testframe').addEventListener("load", function loaded() {
+            $('testframe').removeEventListener("load", loaded);
+            resolve();
+          });
+        });
+      }
+
+      // Same origin
+      yield create_embed("mochi.test:8888");
+      yield create_embed("example.org");
+    }
+
+    document.cookie = "found=a_cookie";
+    var example_iframe = document.createElement("iframe");
+    example_iframe.src = "http://example.org/tests/dom/plugins/test/mochitest/file_setcookie.html";
+    example_iframe.addEventListener("load", () => {
+      $('testframe').addEventListener("load", () => frameLoaded(false, true));
+      SpecialPowers.pushPrefEnv({ set: [[ 'network.cookie.cookieBehavior', 1 ]] },
+                                () => (spawn_task(test_runner).then(SimpleTest.finish)));
+    });
+    document.body.appendChild(example_iframe);
+  </script>
+ </body>
+ </html>
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -101,16 +101,19 @@ this.PushService = {
   _db: null,
   _options: null,
   _visibleNotifications: new Map(),
 
   // Callback that is called after attempting to
   // reduce the quota for a record. Used for testing purposes.
   _updateQuotaTestCallback: null,
 
+  // Set of timeout ID of tasks to reduce quota.
+  _updateQuotaTimeouts: new Set(),
+
   // When serverURI changes (this is used for testing), db is cleaned up and a
   // a new db is started. This events must be sequential.
   _stateChangeProcessQueue: null,
   _stateChangeProcessEnqueue: function(op) {
     if (!this._stateChangeProcessQueue) {
       this._stateChangeProcessQueue = Promise.resolve();
     }
 
@@ -234,17 +237,17 @@ this.PushService = {
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       /*
        * We need to call uninit() on shutdown to clean up things that modules
        * aren't very good at automatically cleaning up, so we don't get shutdown
        * leaks on browser shutdown.
        */
-      case "xpcom-shutdown":
+      case "quit-application":
         this.uninit();
         break;
       case "network-active-changed":         /* On B2G. */
       case "network:offline-status-changed": /* On desktop. */
         this._stateChangeProcessEnqueue(_ =>
           this._changeStateOfflineEvent(aData === "offline", false)
         );
         break;
@@ -418,17 +421,17 @@ this.PushService = {
             return this._stopService(STOPPING_SERVICE_EVENT);
           }
         }
     }
   },
 
   /**
    * PushService initialization is divided into 4 parts:
-   * init() - start listening for xpcom-shutdown and serverURL changes.
+   * init() - start listening for quit-application and serverURL changes.
    *          state is change to PUSH_SERVICE_INIT
    * startService() - if serverURL is present this function is called. It starts
    *                  listening for broadcasted messages, starts db and
    *                  PushService connection (WebSocket).
    *                  state is change to PUSH_SERVICE_ACTIVATING.
    * startObservers() - start other observers.
    * changeStateConnectionEnabledEvent  - checks prefs and offline state.
    *                                      It changes state to:
@@ -440,17 +443,17 @@ this.PushService = {
     console.debug("init()");
 
     if (this._state > PUSH_SERVICE_UNINIT) {
       return;
     }
 
     this._setState(PUSH_SERVICE_ACTIVATING);
 
-    Services.obs.addObserver(this, "xpcom-shutdown", false);
+    Services.obs.addObserver(this, "quit-application", false);
 
     if (options.serverURI) {
       // this is use for xpcshell test.
 
       let [service, uri] = this._findService(options.serverURI);
       if (!service) {
         this._setState(PUSH_SERVICE_INIT);
         return;
@@ -536,32 +539,35 @@ this.PushService = {
   },
 
   /**
    * PushService uninitialization is divided into 3 parts:
    * stopObservers() - stot observers started in startObservers.
    * stopService() - It stops listening for broadcasted messages, stops db and
    *                 PushService connection (WebSocket).
    *                 state is changed to PUSH_SERVICE_INIT.
-   * uninit() - stop listening for xpcom-shutdown and serverURL changes.
+   * uninit() - stop listening for quit-application and serverURL changes.
    *            state is change to PUSH_SERVICE_UNINIT
    */
   _stopService: function(event) {
     console.debug("stopService()");
 
     if (this._state < PUSH_SERVICE_ACTIVATING) {
       return;
     }
 
     this._stopObservers();
 
     this._service.disconnect();
     this._service.uninit();
     this._service = null;
 
+    this._updateQuotaTimeouts.forEach((timeoutID) => clearTimeout(timeoutID));
+    this._updateQuotaTimeouts.clear();
+
     if (!this._db) {
       return Promise.resolve();
     }
     if (event == UNINIT_EVENT) {
       // If it is uninitialized just close db.
       this._db.close();
       this._db = null;
       return Promise.resolve();
@@ -595,17 +601,17 @@ this.PushService = {
   uninit: function() {
     console.debug("uninit()");
 
     if (this._state == PUSH_SERVICE_UNINIT) {
       return;
     }
 
     prefs.ignore("serverURL", this);
-    Services.obs.removeObserver(this, "xpcom-shutdown");
+    Services.obs.removeObserver(this, "quit-application");
 
     this._stateChangeProcessEnqueue(_ =>
       {
         this._changeServerURL("", UNINIT_EVENT);
         this._setState(PUSH_SERVICE_UNINIT);
         console.debug("uninit: shutdown complete!");
       });
   },
@@ -796,18 +802,24 @@ this.PushService = {
         decodedPromise = Promise.resolve(null);
       }
       return decodedPromise.then(message => {
         if (shouldNotify) {
           notified = this._notifyApp(record, message);
         }
         // Update quota after the delay, at which point
         // we check for visible notifications.
-        setTimeout(() => this._updateQuota(keyID),
-          prefs.get("quotaUpdateDelay"));
+        let timeoutID = setTimeout(_ =>
+          {
+            this._updateQuota(keyID);
+            if (!this._updateQuotaTimeouts.delete(timeoutID)) {
+              console.debug("receivedPushMessage: quota update timeout missing?");
+            }
+          }, prefs.get("quotaUpdateDelay"));
+        this._updateQuotaTimeouts.add(timeoutID);
         return notified;
       }, error => {
         console.error("receivedPushMessage: Error decrypting message", error);
       });
     }).catch(error => {
       console.error("receivedPushMessage: Error notifying app", error);
     });
   },
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -214,16 +214,17 @@ var SubscriptionListener = function(aSub
   console.debug("SubscriptionListener()");
   this._subInfo = aSubInfo;
   this._resolve = aResolve;
   this._reject = aReject;
   this._data = '';
   this._serverURI = aServerURI;
   this._service = aPushServiceHttp2;
   this._ctime = Date.now();
+  this._retryTimeoutID = null;
 };
 
 SubscriptionListener.prototype = {
 
   onStartRequest: function(aRequest, aContext) {},
 
   onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
     console.debug("SubscriptionListener: onDataAvailable()");
@@ -256,22 +257,27 @@ SubscriptionListener.prototype = {
     }
 
     var statusCode = aRequest.QueryInterface(Ci.nsIHttpChannel).responseStatus;
 
     if (Math.floor(statusCode / 100) == 5) {
       if (this._subInfo.retries < prefs.get("http2.maxRetries")) {
         this._subInfo.retries++;
         var retryAfter = retryAfterParser(aRequest);
-        setTimeout(_ => this._reject(
+        this._retryTimeoutID = setTimeout(_ =>
           {
-            retry: true,
-            subInfo: this._subInfo
-          }),
-          retryAfter);
+            this._reject(
+              {
+                retry: true,
+                subInfo: this._subInfo
+              });
+            this._service.removeListenerPendingRetry(this);
+            this._retryTimeoutID = null;
+          }, retryAfter);
+        this._service.addListenerPendingRetry(this);
       } else {
         this._reject(new Error("Unexpected server response: " + statusCode));
       }
       return;
     } else if (statusCode != 201) {
       this._reject(new Error("Unexpected server response: " + statusCode));
       return;
     }
@@ -324,16 +330,25 @@ SubscriptionListener.prototype = {
       originAttributes: this._subInfo.record.originAttributes,
       systemRecord: this._subInfo.record.systemRecord,
       ctime: Date.now(),
     });
 
     Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_HTTP2_TIME").add(Date.now() - this._ctime);
     this._resolve(reply);
   },
+
+  abortRetry: function() {
+    if (this._retryTimeoutID != null) {
+      clearTimeout(this._retryTimeoutID);
+      this._retryTimeoutID = null;
+    } else {
+      console.debug("SubscriptionListener.abortRetry: aborting non-existent retry?");
+    }
+  },
 };
 
 function retryAfterParser(aRequest) {
   var retryAfter = 0;
   try {
     var retryField = aRequest.getResponseHeader("retry-after");
     if (isNaN(retryField)) {
       retryAfter = Date.parse(retryField) - (new Date().getTime());
@@ -397,16 +412,19 @@ function linkParser(linkHeader, serverUR
 this.PushServiceHttp2 = {
   _mainPushService: null,
   _serverURI: null,
 
   // Keep information about all connections, e.g. the channel, listener...
   _conns: {},
   _started: false,
 
+  // Set of SubscriptionListeners that are pending a subscription retry attempt.
+  _listenersPendingRetry: new Set(),
+
   newPushDB: function() {
     return new PushDB(kPUSHHTTP2DB_DB_NAME,
                       kPUSHHTTP2DB_DB_VERSION,
                       kPUSHHTTP2DB_STORE_NAME,
                       "subscriptionUri",
                       PushRecordHttp2);
   },
 
@@ -673,20 +691,25 @@ this.PushServiceHttp2 = {
         } catch (e) {}
       }
       delete this._conns[aSubscriptionUri];
     }
   },
 
   uninit: function() {
     console.debug("uninit()");
+    this._abortPendingSubscriptionRetries();
     this._shutdownConnections(true);
     this._mainPushService = null;
   },
 
+  _abortPendingSubscriptionRetries: function() {
+    this._listenersPendingRetry.forEach((listener) => listener.abortRetry());
+    this._listenersPendingRetry.clear();
+  },
 
   request: function(action, aRecord) {
     switch (action) {
       case "register":
         return this._subscribeResource(aRecord);
      case "unregister":
         this._shutdownSubscription(aRecord.subscriptionUri);
         return this._unsubscribeResource(aRecord.subscriptionUri);
@@ -747,16 +770,26 @@ this.PushServiceHttp2 = {
       this._resubscribe(aSubscriptionUri);
     } else if (Math.floor(aRequest.responseStatus / 100) == 2) { // This should be 204
       setTimeout(_ => this._listenForMsgs(aSubscriptionUri), 0);
     } else {
       this._retryAfterBackoff(aSubscriptionUri, -1);
     }
   },
 
+  addListenerPendingRetry: function(aListener) {
+    this._listenersPendingRetry.add(aListener);
+  },
+
+  removeListenerPendingRetry: function(aListener) {
+    if (!this._listenersPendingRetry.remove(aListener)) {
+      console.debug("removeListenerPendingRetry: listener not in list?");
+    }
+  },
+
   _pushChannelOnStop: function(aUri, aAckUri, aMessage, cryptoParams) {
     console.debug("pushChannelOnStop()");
 
     this._mainPushService.receivedPushMessage(
       aUri, aMessage, cryptoParams, record => {
         // Always update the stored record.
         return record;
       }
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -609,16 +609,19 @@ nsCSPContext::SetRequestContext(nsIDOMDo
     mLoadingPrincipal = doc->NodePrincipal();
     doc->GetReferrer(mReferrer);
     mInnerWindowID = doc->InnerWindowID();
     // the innerWindowID is not available for CSPs delivered through the
     // header at the time setReqeustContext is called - let's queue up
     // console messages until it becomes available, see flushConsoleMessages
     mQueueUpMessages = !mInnerWindowID;
     mCallingChannelLoadGroup = doc->GetDocumentLoadGroup();
+
+    // set the flag on the document for CSP telemetry
+    doc->SetHasCSP(true);
   }
   else {
     NS_WARNING("No Document in SetRequestContext; can not query loadgroup; sending reports may fail.");
     mLoadingPrincipal = aPrincipal;
     mLoadingPrincipal->GetURI(getter_AddRefs(mSelfURI));
     // if no document is available, then it also does not make sense to queue console messages
     // sending messages to the browser conolse instead of the web console in that case.
     mQueueUpMessages = false;
--- a/dom/security/nsCSPContext.h
+++ b/dom/security/nsCSPContext.h
@@ -76,16 +76,20 @@ class nsCSPContext : public nsIContentSe
 
     // Hands off! Don't call this method unless you know what you
     // are doing. It's only supposed to be called from within
     // the principal destructor to avoid a tangling pointer.
     void clearLoadingPrincipal() {
       mLoadingPrincipal = nullptr;
     }
 
+    nsWeakPtr GetLoadingContext(){
+      return mLoadingContext;
+    }
+
   private:
     bool permitsInternal(CSPDirective aDir,
                          nsIURI* aContentLocation,
                          nsIURI* aOriginalURI,
                          const nsAString& aNonce,
                          bool aWasRedirected,
                          bool aIsPreload,
                          bool aSpecific,
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -573,31 +573,39 @@ nsCSPParser::keywordSource()
 
   // Special case handling for 'self' which is not stored internally as a keyword,
   // but rather creates a nsCSPHostSrc using the selfURI
   if (CSP_IsKeyword(mCurToken, CSP_SELF)) {
     return CSP_CreateHostSrcFromURI(mSelfURI);
   }
 
   if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_INLINE)) {
+      nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
+      if (doc) {
+        doc->SetHasUnsafeInlineCSP(true);
+      }
     // make sure script-src only contains 'unsafe-inline' once;
     // ignore duplicates and log warning
     if (mUnsafeInlineKeywordSrc) {
       const char16_t* params[] = { mCurToken.get() };
       logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringDuplicateSrc",
                                params, ArrayLength(params));
       return nullptr;
     }
     // cache if we encounter 'unsafe-inline' so we can invalidate (ignore) it in
     // case that script-src directive also contains hash- or nonce-.
     mUnsafeInlineKeywordSrc = new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
     return mUnsafeInlineKeywordSrc;
   }
 
   if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_EVAL)) {
+    nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
+    if (doc) {
+      doc->SetHasUnsafeEvalCSP(true);
+    }
     return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
   }
   return nullptr;
 }
 
 // host-source = [ scheme "://" ] host [ port ] [ path ]
 nsCSPHostSrc*
 nsCSPParser::hostSource()
--- a/dom/tests/mochitest/bugs/test_resize_move_windows.html
+++ b/dom/tests/mochitest/bugs/test_resize_move_windows.html
@@ -69,28 +69,33 @@ function getNewY(aWindow)
 /**
  * hitEventLoop is called when we want to check something but we can't rely on
  * an event or a specific number of event loop hiting.
  * This method can be called by specifying a condition, a test (using SimpleTest
  * API), how many times the event loop has to be hitten and what to call next.
  * If times < 0, the event loop will be hitten as long as the condition isn't
  * true or the test doesn't time out.
  */
-function hitEventLoop(condition, test, times, next) {
-  if (condition() || times == 0) {
-    test();
-    next();
-    return;
-  }
+function hitEventLoop(condition, test, times) {
+  return new Promise(function(resolve, reject) {
+    function doMagic() {
+      if (condition() || times == 0) {
+        test();
+        resolve();
+        return;
+      }
 
-  setTimeout(hitEventLoop, 0, condition, test, times - 1, next);
+      setTimeout(doMagic, 0, condition, test, times - 1);
+    }
+
+    doMagic();
+  });
 }
 
-function checkChangeIsDisabled(aWindow, aNext)
-{
+function checkChangeIsDisabled(aWindow) {
   // We want to check that nothing has changed. Having a high value would take
   // too much time. Worse thing that could happen is random green.
   var hits = 5;
 
   function getProp(propName) {
     return window[propName + "Getter"].call(aWindow);
   }
 
@@ -160,17 +165,17 @@ function checkChangeIsDisabled(aWindow, 
    */
   aWindow.outerWidth *= 2;
   aWindow.outerHeight *= 2;
 
   // We did a lot of changes. Now, we are going to wait and see if something
   // happens.
   // NOTE: if this happens to fail, you will have to check manually which
   // operation has been accepted.
-  hitEventLoop(changeCondition, changeTest, hits, aNext);
+  return hitEventLoop(changeCondition, changeTest, hits);
 }
 
 function checkChangeIsEnabled(aWindow, aNext)
 {
   // Something should happen. We are not going to go to the next test until
   // it does.
   var hits = -1;
 
@@ -241,83 +246,98 @@ function checkChangeIsEnabled(aWindow, a
    * Size checks.
    */
   prevWidth = aWindow.innerWidth;
   prevHeight = aWindow.innerHeight;
 
   aWindow.innerWidth = getNewWidth(aWindow);
   aWindow.innerHeight = getNewHeight(aWindow);
 
-  hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
+  hitEventLoop(sizeChangeCondition, sizeChangeTest, hits)
+  .then(function() {
     aWindow.resizeTo(getNewWidth(aWindow), getNewHeight(aWindow));
-
-  hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
+  })
+  .then(function() {
+    return hitEventLoop(sizeChangeCondition, sizeChangeTest, hits);
+  })
+  .then(function () {
     aWindow.resizeBy(getNewWidth(aWindow) - aWindow.innerWidth,
                      getNewHeight(aWindow) - aWindow.innerHeight);
-
-  hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
+  })
+  .then(function() {
+    return hitEventLoop(sizeChangeCondition, sizeChangeTest, hits);
+  })
+  .then(function () {
     prevWidth = aWindow.innerWidth = getNewWidth(aWindow);
     prevHeight = aWindow.innerHeight = getNewHeight(aWindow);
     aWindow.sizeToContent();
-
-  hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
-  /**
-   * Position checks.
-   */
+  })
+  .then(function() {
+    hitEventLoop(sizeChangeCondition, sizeChangeTest, hits);
+  })
+  .then(function() {
+    /**
+     * Position checks.
+     */
     prevX = aWindow.screenX;
     prevY = aWindow.screenY;
 
     aWindow.screenX = getNewX(aWindow);
     aWindow.screenY = getNewY(aWindow);
-
-  hitEventLoop(posChangeCondition, posChangeTest, hits, function () {
+  })
+  .then(function() {
+    return hitEventLoop(posChangeCondition, posChangeTest, hits);
+  })
+  .then(function() {
     prevX = aWindow.screenX;
     prevY = aWindow.screenY;
 
     aWindow.moveTo(getNewX(aWindow), getNewY(aWindow));
-
-  hitEventLoop(posChangeCondition, posChangeTest, hits, function () {
+  })
+  .then(function() {
+    return hitEventLoop(posChangeCondition, posChangeTest, hits);
+  })
+  .then(function() {
     prevX = aWindow.screenX;
     prevY = aWindow.screenY;
 
     aWindow.moveBy(getNewX(aWindow) - aWindow.screenX,
                    getNewY(aWindow) - aWindow.screenY);
-
-  hitEventLoop(posChangeCondition, posChangeTest, hits, function () {
-  /**
-   * Outer width/height checks.
-   */
+  })
+  .then(function() {
+    return hitEventLoop(posChangeCondition, posChangeTest, hits);
+  })
+  .then(function() {
+    /**
+     * Outer width/height checks.
+     */
     oWidth = aWindow.outerWidth;
     oHeight = aWindow.outerHeight;
 
     aWindow.outerWidth = oWidth * 2;
     aWindow.outerHeight = oHeight * 2;
-
-  hitEventLoop(outerChangeCondition, outerChangeTest, hits, aNext);
-  });
-  });
-  });
-  });
-  });
-  });
-  });
+  })
+  .then(function() {
+    return hitEventLoop(outerChangeCondition, outerChangeTest, hits);
+  })
+  .then(aNext);
 }
 
 SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false]]}, function() {
 SimpleTest.waitForFocus(function() {
   if (screen.width <= 200 || screen.height <= 200) {
     todo(false, "The screen needs to be bigger than 200px*200px to run this test.");
     SimpleTest.finish();
     return;
   }
 
   backValues();
 
   // The current window can't change it's own size and position.
-  checkChangeIsDisabled(window, function() {
+  checkChangeIsDisabled(window).then(function() {
     // We create a window and check that it can change its own size and position.
     // However, passing size/position parameters to window.open should work.
     var w = window.open("data:text/html,<script>" +
       "function check(next) {" +
       "  var is_range = function(aTest, aValue, aRange, aMsg) {" +
       "    window.opener.ok(aTest < aValue + aRange && aTest > aValue - aRange, aMsg);" +
       "  };" +
       "  is_range(window.innerWidth, 170, 5, 'parameter width should be taken into account');" +
@@ -334,24 +354,24 @@ SimpleTest.waitForFocus(function() {
         checkChangeIsEnabled(w, function() {
           w.close();
 
           // If we call window.open with an empty string as a third parameter,
           // by default, it will create a new tab instead of a new window.
           // In that case, we shouldn't allow the caller to change the size/position.
           w = window.open("data:text/html,<script>" +
             "function check(next) {" +
-            "  window.opener.checkChangeIsDisabled(window, next);" +
+            "  window.opener.checkChangeIsDisabled(window).then(next);" +
             "} <\/script>", '', '');
 
           SimpleTest.waitForFocus(function() {
             w.check(function() {
 
               // The current window can't change the size and position of the new tab.
-              checkChangeIsDisabled(w, function() {
+              checkChangeIsDisabled(w).then(function() {
                 w.close();
 
                 restoreValues();
                 SimpleTest.finish();
               });
             });
           }, w, false);
         });
--- a/dom/webidl/Apps.webidl
+++ b/dom/webidl/Apps.webidl
@@ -116,18 +116,16 @@ interface DOMApplication : EventTarget {
 
 [JSImplementation="@mozilla.org/webapps/manager;1",
  ChromeOnly,
  CheckAnyPermissions="webapps-manage homescreen-webapps-manage"]
 interface DOMApplicationsManager : EventTarget {
   DOMRequest getAll();
 
   [CheckAnyPermissions="webapps-manage"]
-  DOMRequest getNotInstalled();
-  [CheckAnyPermissions="webapps-manage"]
   void applyDownload(DOMApplication app);
   DOMRequest uninstall(DOMApplication app);
 
   [CheckAnyPermissions="webapps-manage"]
   Promise<DOMApplication> import(Blob blob);
   [CheckAnyPermissions="webapps-manage"]
   Promise<any> extractManifest(Blob blob);
 
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -22,17 +22,16 @@
 #include "nsIInputStream.h"
 #include "nsISeekableStream.h"
 #include "nsISupportsImpl.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 
 #include "RuntimeService.h"
 
-USING_WORKERS_NAMESPACE
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::dom::Optional;
 using mozilla::dom::GlobalObject;
 
 // static
 already_AddRefed<FileReaderSync>
 FileReaderSync::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
@@ -42,17 +41,17 @@ FileReaderSync::Constructor(const Global
   return frs.forget();
 }
 
 bool
 FileReaderSync::WrapObject(JSContext* aCx,
                            JS::Handle<JSObject*> aGivenProto,
                            JS::MutableHandle<JSObject*> aReflector)
 {
-  return FileReaderSyncBinding_workers::Wrap(aCx, this, aGivenProto, aReflector);
+  return FileReaderSyncBinding::Wrap(aCx, this, aGivenProto, aReflector);
 }
 
 void
 FileReaderSync::ReadAsArrayBuffer(JSContext* aCx,
                                   JS::Handle<JSObject*> aScopeObj,
                                   Blob& aBlob,
                                   JS::MutableHandle<JSObject*> aRetval,
                                   ErrorResult& aRv)
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -1,32 +1,28 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
-#ifndef mozilla_dom_workers_filereadersync_h__
-#define mozilla_dom_workers_filereadersync_h__
+#ifndef mozilla_dom_filereadersync_h__
+#define mozilla_dom_filereadersync_h__
 
 #include "Workers.h"
 
 class nsIInputStream;
 
 namespace mozilla {
 class ErrorResult;
 
 namespace dom {
 class Blob;
 class GlobalObject;
 template<typename> class Optional;
-} // namespace dom
-} // namespace mozilla
-
-BEGIN_WORKERS_NAMESPACE
 
 class FileReaderSync final
 {
   NS_INLINE_DECL_REFCOUNTING(FileReaderSync)
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~FileReaderSync()
@@ -46,11 +42,12 @@ public:
                          Blob& aBlob, JS::MutableHandle<JSObject*> aRetval,
                          ErrorResult& aRv);
   void ReadAsBinaryString(Blob& aBlob, nsAString& aResult, ErrorResult& aRv);
   void ReadAsText(Blob& aBlob, const Optional<nsAString>& aEncoding,
                   nsAString& aResult, ErrorResult& aRv);
   void ReadAsDataURL(Blob& aBlob, nsAString& aResult, ErrorResult& aRv);
 };
 
-END_WORKERS_NAMESPACE
+} // namespace dom
+} // namespace mozilla
 
-#endif // mozilla_dom_workers_filereadersync_h__
+#endif // mozilla_dom_filereadersync_h__
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -44,32 +44,34 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Navigator.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollector.h"
 #include "nsDOMJSUtils.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsISupportsImpl.h"
 #include "nsLayoutStatics.h"
+#include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMPrivate.h"
 #include "OSFileConstants.h"
 #include "xpcpublic.h"
 
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
 
 #include "Principal.h"
 #include "SharedWorker.h"
 #include "WorkerDebuggerManager.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
+#include "WorkerScope.h"
 #include "WorkerThread.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 USING_WORKERS_NAMESPACE
 
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -26,55 +26,56 @@
 #include "nsError.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentUtils.h"
 #include "nsDocShellCID.h"
 #include "nsISupportsPrimitives.h"
 #include "nsNetUtil.h"
 #include "nsIPipe.h"
 #include "nsIOutputStream.h"
+#include "nsPrintfCString.h"
 #include "nsScriptLoader.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOM.h"
 #include "xpcpublic.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/LoadContext.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/dom/CacheBinding.h"
 #include "mozilla/dom/cache/CacheTypes.h"
 #include "mozilla/dom/cache/Cache.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/ChannelInfo.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/InternalResponse.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/Response.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/UniquePtr.h"
 #include "Principal.h"
 #include "WorkerFeature.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WorkerScope.h"
 
 #define MAX_CONCURRENT_SCRIPTS 1000
 
 USING_WORKERS_NAMESPACE
 
+using namespace mozilla;
+using namespace mozilla::dom;
 using mozilla::dom::cache::Cache;
 using mozilla::dom::cache::CacheStorage;
-using mozilla::dom::Promise;
-using mozilla::dom::PromiseNativeHandler;
-using mozilla::ErrorResult;
 using mozilla::ipc::PrincipalInfo;
-using mozilla::UniquePtr;
 
 namespace {
 
 nsIURI*
 GetBaseURI(bool aIsMainScript, WorkerPrivate* aWorkerPrivate)
 {
   MOZ_ASSERT(aWorkerPrivate);
   nsIURI* baseURI;
--- a/dom/workers/ServiceWorkerClient.cpp
+++ b/dom/workers/ServiceWorkerClient.cpp
@@ -8,17 +8,20 @@
 #include "ServiceWorkerClient.h"
 #include "ServiceWorkerContainer.h"
 
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/Navigator.h"
 #include "mozilla/dom/ServiceWorkerMessageEvent.h"
 #include "mozilla/dom/ServiceWorkerMessageEventBinding.h"
 #include "nsGlobalWindow.h"
+#include "nsIBrowserDOMWindow.h"
 #include "nsIDocument.h"
+#include "ServiceWorker.h"
+#include "ServiceWorkerPrivate.h"
 #include "WorkerPrivate.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::workers;
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClient, mOwner)
 
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -1,34 +1,39 @@
 /* -*- Mode: C++; tab-width: 8; 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 "ServiceWorkerClients.h"
+
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseWorkerProxy.h"
 
 #include "ServiceWorkerClient.h"
-#include "ServiceWorkerClients.h"
 #include "ServiceWorkerManager.h"
+#include "ServiceWorkerPrivate.h"
 #include "ServiceWorkerWindowClient.h"
 
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WorkerScope.h"
 
+#include "nsContentUtils.h"
+#include "nsIBrowserDOMWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIWebProgressListener.h"
 #include "nsIWindowMediator.h"
 #include "nsIWindowWatcher.h"
+#include "nsNetUtil.h"
 #include "nsPIWindowWatcher.h"
 #include "nsWindowWatcher.h"
 #include "nsWeakReference.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::workers;
 
--- a/dom/workers/ServiceWorkerContainer.cpp
+++ b/dom/workers/ServiceWorkerContainer.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; 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 "ServiceWorkerContainer.h"
 
+#include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIServiceWorkerManager.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -5,54 +5,61 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ServiceWorkerEvents.h"
 
 #include "nsIConsoleReportCollector.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsINetworkInterceptController.h"
 #include "nsIOutputStream.h"
+#include "nsIScriptError.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStreamUtils.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsSerializationHelper.h"
 #include "nsQueryObject.h"
+#include "ServiceWorkerClient.h"
+#include "ServiceWorkerManager.h"
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/FetchEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortList.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/workers/bindings/ServiceWorker.h"
 
 #ifndef MOZ_SIMPLEPUSH
+#include "mozilla/dom/PushEventBinding.h"
+#include "mozilla/dom/PushMessageDataBinding.h"
+
 #include "nsIUnicodeDecoder.h"
 #include "nsIUnicodeEncoder.h"
 
 #include "mozilla/dom/BodyUtil.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "mozilla/dom/TypedArray.h"
 #endif
 
 #include "js/Conversions.h"
 #include "js/TypeDecls.h"
 #include "WorkerPrivate.h"
 #include "xpcpublic.h"
 
 using namespace mozilla::dom;
+using namespace mozilla::dom::workers;
 
 BEGIN_WORKERS_NAMESPACE
 
 CancelChannelRunnable::CancelChannelRunnable(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
                                              nsresult aStatus)
   : mChannel(aChannel)
   , mStatus(aStatus)
 {
@@ -1013,16 +1020,22 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Pu
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PushMessageData)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PushMessageData)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushMessageData)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
+JSObject*
+PushMessageData::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return mozilla::dom::PushMessageDataBinding::Wrap(aCx, this, aGivenProto);
+}
+
 void
 PushMessageData::Json(JSContext* cx, JS::MutableHandle<JS::Value> aRetval,
                       ErrorResult& aRv)
 {
   if (NS_FAILED(EnsureDecodedText())) {
     aRv.Throw(NS_ERROR_DOM_UNKNOWN_ERR);
     return;
   }
@@ -1122,16 +1135,22 @@ PushEvent::Constructor(mozilla::dom::Eve
 NS_IMPL_ADDREF_INHERITED(PushEvent, ExtendableEvent)
 NS_IMPL_RELEASE_INHERITED(PushEvent, ExtendableEvent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PushEvent)
 NS_INTERFACE_MAP_END_INHERITING(ExtendableEvent)
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(PushEvent, ExtendableEvent, mData)
 
+JSObject*
+PushEvent::WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return mozilla::dom::PushEventBinding::Wrap(aCx, this, aGivenProto);
+}
+
 #endif /* ! MOZ_SIMPLEPUSH */
 
 ExtendableMessageEvent::ExtendableMessageEvent(EventTarget* aOwner)
   : ExtendableEvent(aOwner)
   , mData(JS::UndefinedValue())
 {
   mozilla::HoldJSObjects(this);
 }
--- a/dom/workers/ServiceWorkerEvents.h
+++ b/dom/workers/ServiceWorkerEvents.h
@@ -11,33 +11,33 @@
 #include "mozilla/dom/ExtendableEventBinding.h"
 #include "mozilla/dom/ExtendableMessageEventBinding.h"
 #include "mozilla/dom/FetchEventBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/workers/bindings/ServiceWorker.h"
 
 #ifndef MOZ_SIMPLEPUSH
-#include "mozilla/dom/PushEventBinding.h"
-#include "mozilla/dom/PushMessageDataBinding.h"
 #include "mozilla/dom/File.h"
 #endif
 
 #include "nsProxyRelease.h"
 #include "nsContentUtils.h"
 
 class nsIInterceptedChannel;
 
 namespace mozilla {
 namespace dom {
 class Blob;
 class MessagePort;
 class MessagePortList;
 class Request;
 class ResponseOrPromise;
+
+struct PushEventInit;
 } // namespace dom
 } // namespace mozilla
 
 BEGIN_WORKERS_NAMESPACE
 
 class CancelChannelRunnable final : public nsRunnable
 {
   nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
@@ -183,20 +183,17 @@ public:
 
 class PushMessageData final : public nsISupports,
                               public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushMessageData)
 
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    return mozilla::dom::PushMessageDataBinding_workers::Wrap(aCx, this, aGivenProto);
-  }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsISupports* GetParentObject() const {
     return mOwner;
   }
 
   void Json(JSContext* cx, JS::MutableHandle<JS::Value> aRetval,
             ErrorResult& aRv);
   void Text(nsAString& aData);
@@ -223,20 +220,17 @@ protected:
   explicit PushEvent(mozilla::dom::EventTarget* aOwner);
   ~PushEvent() {}
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PushEvent, ExtendableEvent)
   NS_FORWARD_TO_EVENT
 
-  virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    return mozilla::dom::PushEventBinding_workers::Wrap(aCx, this, aGivenProto);
-  }
+  virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static already_AddRefed<PushEvent>
   Constructor(mozilla::dom::EventTarget* aOwner,
               const nsAString& aType,
               const PushEventInit& aOptions,
               ErrorResult& aRv);
 
   static already_AddRefed<PushEvent>
--- a/dom/workers/ServiceWorkerManagerParent.cpp
+++ b/dom/workers/ServiceWorkerManagerParent.cpp
@@ -20,22 +20,16 @@ using namespace ipc;
 
 namespace dom {
 namespace workers {
 
 namespace {
 
 uint64_t sServiceWorkerManagerParentID = 0;
 
-void
-AssertIsInMainProcess()
-{
-  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
-}
-
 class RegisterServiceWorkerCallback final : public nsRunnable
 {
 public:
   RegisterServiceWorkerCallback(const ServiceWorkerRegistrationData& aData,
                                 uint64_t aParentID)
     : mData(aData)
     , mParentID(aParentID)
   {
--- a/dom/workers/ServiceWorkerManagerService.cpp
+++ b/dom/workers/ServiceWorkerManagerService.cpp
@@ -2,16 +2,17 @@
 /* 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 "ServiceWorkerManagerService.h"
 #include "ServiceWorkerManagerParent.h"
 #include "ServiceWorkerRegistrar.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/unused.h"
 
 namespace mozilla {
 
 using namespace ipc;
 
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -1,20 +1,38 @@
 /* -*- Mode: C++; tab-width: 8; 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 "ServiceWorkerPrivate.h"
+
 #include "ServiceWorkerManager.h"
+#include "nsContentUtils.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsIHttpHeaderVisitor.h"
+#include "nsINetworkInterceptController.h"
+#include "nsISupportsImpl.h"
+#include "nsIUploadChannel2.h"
+#include "nsNetUtil.h"
+#include "nsProxyRelease.h"
+#include "nsQueryObject.h"
 #include "nsStreamUtils.h"
 #include "nsStringStream.h"
+#include "WorkerRunnable.h"
+#include "WorkerScope.h"
+#include "mozilla/Assertions.h"
 #include "mozilla/dom/FetchUtil.h"
 #include "mozilla/dom/IndexedDatabaseManager.h"
+#include "mozilla/dom/InternalHeaders.h"
+#include "mozilla/dom/NotificationEvent.h"
+#include "mozilla/dom/PromiseNativeHandler.h"
+#include "mozilla/dom/PushEventBinding.h"
+#include "mozilla/dom/RequestBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 BEGIN_WORKERS_NAMESPACE
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerPrivate)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerPrivate)
--- a/dom/workers/ServiceWorkerPrivate.h
+++ b/dom/workers/ServiceWorkerPrivate.h
@@ -6,21 +6,24 @@
 
 #ifndef mozilla_dom_workers_serviceworkerprivate_h
 #define mozilla_dom_workers_serviceworkerprivate_h
 
 #include "nsCOMPtr.h"
 
 #include "WorkerPrivate.h"
 
+class nsIInterceptedChannel;
+
 namespace mozilla {
 namespace dom {
 namespace workers {
 
 class ServiceWorkerInfo;
+class ServiceWorkerRegistrationInfo;
 class KeepAliveToken;
 
 class LifeCycleEventCallback : public nsRunnable
 {
 public:
   // Called on the worker thread.
   virtual void
   SetResult(bool aResult) = 0;
--- a/dom/workers/ServiceWorkerRegistrar.cpp
+++ b/dom/workers/ServiceWorkerRegistrar.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAutoPtr.h"
+#include "nsContentUtils.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla::ipc;
--- a/dom/workers/ServiceWorkerScriptCache.cpp
+++ b/dom/workers/ServiceWorkerScriptCache.cpp
@@ -14,18 +14,20 @@
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "nsICacheInfoChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIStreamLoader.h"
 #include "nsIThreadRetargetableRequest.h"
 
 #include "nsIPrincipal.h"
+#include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsScriptLoader.h"
+#include "ServiceWorkerManager.h"
 #include "Workers.h"
 #include "nsStringStream.h"
 
 using mozilla::dom::cache::Cache;
 using mozilla::dom::cache::CacheStorage;
 
 BEGIN_WORKERS_NAMESPACE
 
--- a/dom/workers/ServiceWorkerScriptCache.h
+++ b/dom/workers/ServiceWorkerScriptCache.h
@@ -11,16 +11,18 @@
 
 class nsILoadGroup;
 class nsIPrincipal;
 
 namespace mozilla {
 namespace dom {
 namespace workers {
 
+class ServiceWorkerRegistrationInfo;
+
 namespace serviceWorkerScriptCache {
 
 nsresult
 PurgeCache(nsIPrincipal* aPrincipal, const nsAString& aCacheName);
 
 nsresult
 GenerateCacheName(nsAString& aName);
 
--- a/dom/workers/ServiceWorkerWindowClient.cpp
+++ b/dom/workers/ServiceWorkerWindowClient.cpp
@@ -7,19 +7,22 @@
 
 #include "ServiceWorkerWindowClient.h"
 
 #include "mozilla/Mutex.h"
 #include "mozilla/dom/ClientBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseWorkerProxy.h"
 #include "mozilla/UniquePtr.h"
+#include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "WorkerPrivate.h"
+#include "WorkerScope.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::workers;
 
 using mozilla::UniquePtr;
 
 JSObject*
 ServiceWorkerWindowClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
--- a/dom/workers/SharedWorker.cpp
+++ b/dom/workers/SharedWorker.cpp
@@ -16,16 +16,17 @@
 #include "nsIClassInfoImpl.h"
 #include "nsIDOMEvent.h"
 
 #include "RuntimeService.h"
 #include "WorkerPrivate.h"
 
 using mozilla::dom::Optional;
 using mozilla::dom::Sequence;
+using mozilla::dom::MessagePort;
 using namespace mozilla;
 
 USING_WORKERS_NAMESPACE
 
 SharedWorker::SharedWorker(nsPIDOMWindowInner* aWindow,
                            WorkerPrivate* aWorkerPrivate,
                            MessagePort* aMessagePort)
   : DOMEventTargetHelper(aWindow)
--- a/dom/workers/WorkerDebuggerManager.h
+++ b/dom/workers/WorkerDebuggerManager.h
@@ -9,16 +9,17 @@
 
 #include "Workers.h"
 
 #include "nsIObserver.h"
 #include "nsIWorkerDebuggerManager.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
+#include "nsThreadUtils.h"
 
 #define WORKERDEBUGGERMANAGER_CID \
   { 0x62ec8731, 0x55ad, 0x4246, \
     { 0xb2, 0xea, 0xf2, 0x6c, 0x1f, 0xe1, 0x9d, 0x2d } }
 #define WORKERDEBUGGERMANAGER_CONTRACTID \
   "@mozilla.org/dom/workers/workerdebuggermanager;1"
 
 BEGIN_WORKERS_NAMESPACE
rename from dom/workers/Location.cpp
rename to dom/workers/WorkerLocation.cpp
--- a/dom/workers/Location.cpp
+++ b/dom/workers/WorkerLocation.cpp
@@ -1,27 +1,28 @@
 /* -*- Mode: C++; tab-width: 8; 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 "Location.h"
+#include "mozilla/dom/WorkerLocation.h"
 
 #include "mozilla/dom/WorkerLocationBinding.h"
 
-BEGIN_WORKERS_NAMESPACE
+namespace mozilla {
+namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WorkerLocation)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WorkerLocation, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WorkerLocation, Release)
 
 /* static */ already_AddRefed<WorkerLocation>
-WorkerLocation::Create(WorkerPrivate::LocationInfo& aInfo)
+WorkerLocation::Create(workers::WorkerPrivate::LocationInfo& aInfo)
 {
   RefPtr<WorkerLocation> location =
     new WorkerLocation(NS_ConvertUTF8toUTF16(aInfo.mHref),
                        NS_ConvertUTF8toUTF16(aInfo.mProtocol),
                        NS_ConvertUTF8toUTF16(aInfo.mHost),
                        NS_ConvertUTF8toUTF16(aInfo.mHostname),
                        NS_ConvertUTF8toUTF16(aInfo.mPort),
                        NS_ConvertUTF8toUTF16(aInfo.mPathname),
@@ -30,12 +31,13 @@ WorkerLocation::Create(WorkerPrivate::Lo
                        aInfo.mOrigin);
 
   return location.forget();
 }
 
 JSObject*
 WorkerLocation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
-  return WorkerLocationBinding_workers::Wrap(aCx, this, aGivenProto);
+  return WorkerLocationBinding::Wrap(aCx, this, aGivenProto);
 }
 
-END_WORKERS_NAMESPACE
+} // namespace dom
+} // namespace mozilla
rename from dom/workers/Location.h
rename to dom/workers/WorkerLocation.h
--- a/dom/workers/Location.h
+++ b/dom/workers/WorkerLocation.h
@@ -1,22 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
-#ifndef mozilla_dom_workers_location_h__
-#define mozilla_dom_workers_location_h__
+#ifndef mozilla_dom_location_h__
+#define mozilla_dom_location_h__
 
 #include "Workers.h"
 #include "WorkerPrivate.h"
 #include "nsWrapperCache.h"
 
-BEGIN_WORKERS_NAMESPACE
+namespace mozilla {
+namespace dom {
 
 class WorkerLocation final : public nsWrapperCache
 {
   nsString mHref;
   nsString mProtocol;
   nsString mHost;
   nsString mHostname;
   nsString mPort;
@@ -53,17 +54,17 @@ class WorkerLocation final : public nsWr
   }
 
 public:
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WorkerLocation)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WorkerLocation)
 
   static already_AddRefed<WorkerLocation>
-  Create(WorkerPrivate::LocationInfo& aInfo);
+  Create(workers::WorkerPrivate::LocationInfo& aInfo);
 
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsISupports* GetParentObject() const {
     return nullptr;
   }
 
@@ -104,11 +105,12 @@ public:
     aHash = mHash;
   }
   void GetOrigin(nsString& aOrigin) const
   {
     aOrigin = mOrigin;
   }
 };
 
-END_WORKERS_NAMESPACE
+} // namespace dom
+} // namespace mozilla
 
-#endif // mozilla_dom_workers_location_h__
+#endif // mozilla_dom_location_h__
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -42,17 +42,19 @@
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Likely.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/Exceptions.h"
+#include "mozilla/dom/ExtendableMessageEventBinding.h"
 #include "mozilla/dom/FunctionBinding.h"
+#include "mozilla/dom/IndexedDatabaseManager.h"
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/MessagePortList.h"
 #include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseDebugging.h"
@@ -88,16 +90,17 @@
 #ifdef DEBUG
 #include "nsThreadManager.h"
 #endif
 
 #include "Navigator.h"
 #include "Principal.h"
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
+#include "ServiceWorkerEvents.h"
 #include "ServiceWorkerManager.h"
 #include "ServiceWorkerWindowClient.h"
 #include "SharedWorker.h"
 #include "WorkerDebuggerManager.h"
 #include "WorkerFeature.h"
 #include "WorkerRunnable.h"
 #include "WorkerScope.h"
 #include "WorkerThread.h"
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -16,28 +16,28 @@
 #include "mozilla/dom/IDBFactory.h"
 #include "mozilla/dom/ImageBitmap.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseWorkerProxy.h"
 #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
 #include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
 #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
 #include "mozilla/dom/WorkerGlobalScopeBinding.h"
+#include "mozilla/dom/WorkerLocation.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/Services.h"
 #include "nsServiceManagerUtils.h"
 
 #include "nsIDocument.h"
 #include "nsIServiceWorkerManager.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
-#include "Location.h"
 #include "Navigator.h"
 #include "Principal.h"
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "Performance.h"
 #include "ServiceWorkerClients.h"
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -18,30 +18,30 @@ namespace mozilla {
 namespace dom {
 
 class Console;
 class Function;
 class IDBFactory;
 class Promise;
 class RequestOrUSVString;
 class ServiceWorkerRegistrationWorkerThread;
+class WorkerLocation;
 
 namespace cache {
 
 class CacheStorage;
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
 
 BEGIN_WORKERS_NAMESPACE
 
 class ServiceWorkerClients;
 class WorkerPrivate;
-class WorkerLocation;
 class WorkerNavigator;
 class Performance;
 
 class WorkerGlobalScope : public DOMEventTargetHelper,
                           public nsIGlobalObject,
                           public nsSupportsWeakReference
 {
   typedef mozilla::dom::IDBFactory IDBFactory;
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -1,40 +1,40 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # Public stuff.
 EXPORTS.mozilla.dom += [
+    'FileReaderSync.h',
     'ServiceWorkerCommon.h',
     'ServiceWorkerContainer.h',
     'ServiceWorkerEvents.h',
     'ServiceWorkerMessageEvent.h',
     'ServiceWorkerRegistrar.h',
     'ServiceWorkerRegistration.h',
+    'WorkerLocation.h',
     'WorkerPrefs.h',
     'WorkerPrivate.h',
     'WorkerRunnable.h',
     'WorkerScope.h',
 ]
 
 EXPORTS.mozilla.dom.workers += [
     'ServiceWorkerManager.h',
     'WorkerDebuggerManager.h',
     'Workers.h',
 ]
 
 # Stuff needed for the bindings, not really public though.
 EXPORTS.mozilla.dom.workers.bindings += [
     'DataStore.h',
     'DataStoreCursor.h',
-    'FileReaderSync.h',
-    'Location.h',
     'Navigator.h',
     'Performance.h',
     'ServiceWorker.h',
     'ServiceWorkerClient.h',
     'ServiceWorkerClients.h',
     'ServiceWorkerWindowClient.h',
     'SharedWorker.h',
     'URL.h',
@@ -50,17 +50,16 @@ XPIDL_SOURCES += [
     'nsIWorkerDebuggerManager.idl',
 ]
 
 UNIFIED_SOURCES += [
     'ChromeWorkerScope.cpp',
     'DataStore.cpp',
     'DataStoreCursor.cpp',
     'FileReaderSync.cpp',
-    'Location.cpp',
     'Navigator.cpp',
     'Performance.cpp',
     'Principal.cpp',
     'RegisterBindings.cpp',
     'RuntimeService.cpp',
     'ScriptLoader.cpp',
     'ServiceWorker.cpp',
     'ServiceWorkerClient.cpp',
@@ -75,16 +74,17 @@ UNIFIED_SOURCES += [
     'ServiceWorkerPrivate.cpp',
     'ServiceWorkerRegistrar.cpp',
     'ServiceWorkerRegistration.cpp',
     'ServiceWorkerScriptCache.cpp',
     'ServiceWorkerWindowClient.cpp',
     'SharedWorker.cpp',
     'URL.cpp',
     'WorkerDebuggerManager.cpp',
+    'WorkerLocation.cpp',
     'WorkerPrivate.cpp',
     'WorkerRunnable.cpp',
     'WorkerScope.cpp',
     'WorkerThread.cpp',
     'XMLHttpRequest.cpp',
     'XMLHttpRequestUpload.cpp',
 ]
 
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -69,17 +69,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] in {'c
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'beos':
     EXPORTS.cairo += [
         'cairo-beos.h',
     ]
     SOURCES += [
         'cairo-beos-surface.cpp',
     ]
-elif CONFIG['MOZ_WIDGET_GTK']:
+elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     EXPORTS.cairo += [
         'cairo-ps.h',
     ]
     SOURCES += [
         'cairo-ps-surface.c',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     EXPORTS.cairo += [
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -7,17 +7,17 @@
 gl_provider = 'Null'
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     gl_provider = 'WGL'
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     gl_provider = 'CGL'
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
     gl_provider = 'EAGL'
-elif CONFIG['MOZ_WIDGET_GTK']:
+elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     if CONFIG['MOZ_EGL_XRENDER_COMPOSITE']:
         gl_provider = 'EGL'
     else:
         gl_provider = 'GLX'
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     gl_provider = 'GLX'
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     gl_provider = 'EGL'
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2035,17 +2035,23 @@ nsEventStatus AsyncPanZoomController::On
 }
 
 nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a long-press in state %d\n", this, mState);
   RefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     CSSPoint geckoScreenPoint;
     if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
-      if (CurrentTouchBlock()->IsDuringFastFling()) {
+      CancelableBlockState* block = CurrentInputBlock();
+      MOZ_ASSERT(block);
+      if (!block->AsTouchBlock()) {
+        APZC_LOG("%p dropping long-press because some non-touch block interrupted it\n", this);
+        return nsEventStatus_eIgnore;
+      }
+      if (block->AsTouchBlock()->IsDuringFastFling()) {
         APZC_LOG("%p dropping long-press because of fast fling\n", this);
         return nsEventStatus_eIgnore;
       }
       uint64_t blockId = GetInputQueue()->InjectNewTouchBlock(this);
       controller->HandleLongTap(geckoScreenPoint, aEvent.modifiers, GetGuid(), blockId);
       return nsEventStatus_eConsumeNoDefault;
     }
   }
@@ -2057,18 +2063,31 @@ nsEventStatus AsyncPanZoomController::On
   return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
 }
 
 nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) {
   RefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     CSSPoint geckoScreenPoint;
     if (ConvertToGecko(aPoint, &geckoScreenPoint)) {
-      if (!CurrentTouchBlock()->SetSingleTapOccurred()) {
-        return nsEventStatus_eIgnore;
+      CancelableBlockState* block = CurrentInputBlock();
+      MOZ_ASSERT(block);
+      TouchBlockState* touch = block->AsTouchBlock();
+      // |block| may be a non-touch block in the case where this function is
+      // invoked by GestureEventListener on a timeout. In that case we already
+      // verified that the single tap is allowed so we let it through.
+      // XXX there is a bug here that in such a case the touch block that
+      // generated this tap will not get its mSingleTapOccurred flag set.
+      // See https://bugzilla.mozilla.org/show_bug.cgi?id=1256344#c6
+      if (touch) {
+        if (touch->IsDuringFastFling()) {
+          APZC_LOG("%p dropping single-tap because it was during a fast-fling\n", this);
+          return nsEventStatus_eIgnore;
+        }
+        touch->SetSingleTapOccurred();
       }
       // Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
       // calling controller->HandleSingleTap directly might mean that content receives
       // the single tap message before the corresponding touch-up. To avoid that we
       // schedule the singletap message to run on the next spin of the event loop.
       // See bug 965381 for the issue this was causing.
       controller->PostDelayedTask(
         NewRunnableMethod(controller.get(), &GeckoContentController::HandleSingleTap,
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -617,21 +617,16 @@ protected:
   /**
    * Gets the pointer to the apzc tree manager. All the access to tree manager
    * should be made via this method and not via private variable since this method
    * ensures that no lock is set.
    */
   APZCTreeManager* GetApzcTreeManager() const;
 
   /**
-   * Gets a ref to the input queue that is shared across the entire tree manager.
-   */
-  const RefPtr<InputQueue>& GetInputQueue() const;
-
-  /**
    * Convert ScreenPoint relative to the screen to CSSPoint relative
    * to the parent document. This excludes the transient compositor transform.
    * NOTE: This must be converted to CSSPoint relative to the child
    * document before sending over IPC to a child process.
    */
   bool ConvertToGecko(const ScreenIntPoint& aPoint, CSSPoint* aOut);
 
   enum AxisLockMode {
@@ -815,16 +810,21 @@ public:
    */
   bool ArePointerEventsConsumable(TouchBlockState* aBlock, uint32_t aTouchPoints);
 
   /**
    * Clear internal state relating to touch input handling.
    */
   void ResetTouchInputState();
 
+  /**
+   * Gets a ref to the input queue that is shared across the entire tree manager.
+   */
+  const RefPtr<InputQueue>& GetInputQueue() const;
+
 private:
   void CancelAnimationAndGestureState();
 
   RefPtr<InputQueue> mInputQueue;
   CancelableBlockState* CurrentInputBlock() const;
   TouchBlockState* CurrentTouchBlock() const;
   bool HasReadyTouchBlock() const;
 
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -439,28 +439,30 @@ void GestureEventListener::HandleInputTi
   }
   default:
     NS_WARNING("Unhandled state upon long tap timeout");
     SetState(GESTURE_NONE);
     break;
   }
 }
 
-void GestureEventListener::HandleInputTimeoutMaxTap()
+void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling)
 {
   GEL_LOG("Running max-tap timeout task in state %d\n", mState);
 
   mMaxTapTimeoutTask = nullptr;
 
   if (mState == GESTURE_FIRST_SINGLE_TOUCH_DOWN) {
     SetState(GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN);
   } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
              mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
     SetState(GESTURE_NONE);
-    TriggerSingleTapConfirmedEvent();
+    if (!aDuringFastFling) {
+      TriggerSingleTapConfirmedEvent();
+    }
   } else {
     NS_WARNING("Unhandled state upon MAX_TAP timeout");
     SetState(GESTURE_NONE);
   }
 }
 
 void GestureEventListener::TriggerSingleTapConfirmedEvent()
 {
@@ -515,18 +517,20 @@ void GestureEventListener::CancelMaxTapT
     mMaxTapTimeoutTask = nullptr;
   }
 }
 
 void GestureEventListener::CreateMaxTapTimeoutTask()
 {
   mLastTapInput = mLastTouchInput;
 
+  TouchBlockState* block = mAsyncPanZoomController->GetInputQueue()->CurrentTouchBlock();
   mMaxTapTimeoutTask =
-    NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap);
+    NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap,
+                      block->IsDuringFastFling());
 
   mAsyncPanZoomController->PostDelayedTask(
     mMaxTapTimeoutTask,
     MAX_TAP_TIME);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -132,17 +132,17 @@ private:
    * finite-state machine triggering state transitions.
    */
   nsEventStatus HandleInputTouchSingleStart();
   nsEventStatus HandleInputTouchMultiStart();
   nsEventStatus HandleInputTouchEnd();
   nsEventStatus HandleInputTouchMove();
   nsEventStatus HandleInputTouchCancel();
   void HandleInputTimeoutLongTap();
-  void HandleInputTimeoutMaxTap();
+  void HandleInputTimeoutMaxTap(bool aDuringFastFling);
 
   void TriggerSingleTapConfirmedEvent();
 
   bool MoveDistanceIsLarge();
 
   /**
    * Do actual state transition and reset substates.
    */
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -82,21 +82,43 @@ InputBlockState::GetBlockId() const
 }
 
 bool
 InputBlockState::IsTargetConfirmed() const
 {
   return mTargetConfirmed;
 }
 
+bool
+InputBlockState::IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB)
+{
+  if (aA == aB) {
+    return true;
+  }
+
+  bool seenA = false;
+  for (size_t i = 0; i < mOverscrollHandoffChain->Length(); ++i) {
+    AsyncPanZoomController* apzc = mOverscrollHandoffChain->GetApzcAtIndex(i);
+    if (apzc == aB) {
+      return seenA;
+    }
+    if (apzc == aA) {
+      seenA = true;
+    }
+  }
+  return false;
+}
+
+
 void
 InputBlockState::SetScrolledApzc(AsyncPanZoomController* aApzc)
 {
-  // An input block should only have one scrolled APZC.
-  MOZ_ASSERT(!mScrolledApzc || mScrolledApzc == aApzc);
+  // With immediate handoff disabled, the scrolled APZC cannot move down the handoff chain
+  // but it can move up the handoff chain if we change scrolling directions.
+  MOZ_ASSERT(!mScrolledApzc || IsAncestorOf(aApzc, mScrolledApzc));
 
   mScrolledApzc = aApzc;
 }
 
 AsyncPanZoomController*
 InputBlockState::GetScrolledApzc() const
 {
   return mScrolledApzc;
@@ -714,26 +736,21 @@ TouchBlockState::SetDuringFastFling()
 }
 
 bool
 TouchBlockState::IsDuringFastFling() const
 {
   return mDuringFastFling;
 }
 
-bool
+void
 TouchBlockState::SetSingleTapOccurred()
 {
-  TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n",
-    this, mDuringFastFling);
-  if (!mDuringFastFling) {
-    mSingleTapOccurred = true;
-    return true;
-  }
-  return false;
+  TBS_LOG("%p setting single-tap-occurred flag\n", this);
+  mSingleTapOccurred = true;
 }
 
 bool
 TouchBlockState::SingleTapOccurred() const
 {
   return mSingleTapOccurred;
 }
 
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -52,16 +52,21 @@ public:
 
   void SetScrolledApzc(AsyncPanZoomController* aApzc);
   AsyncPanZoomController* GetScrolledApzc() const;
 
 protected:
   virtual void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc);
 
 private:
+  // Checks whether |aA| is an ancestor of |aB| (or the same as |aB|) in
+  // |mOverscrollHandoffChain|.
+  bool IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB);
+
+private:
   RefPtr<AsyncPanZoomController> mTargetApzc;
   bool mTargetConfirmed;
   const uint64_t mBlockId;
 
   // The APZC that was actually scrolled by events in this input block.
   // This is used in configurations where a single input block is only
   // allowed to scroll a single APZC (configurations where gfxPrefs::
   // APZAllowImmediateHandoff() is false).
@@ -406,20 +411,18 @@ public:
   void SetDuringFastFling();
   /**
    * @return true iff SetDuringFastFling was called on this block.
    */
   bool IsDuringFastFling() const;
   /**
    * Set the single-tap-occurred flag that indicates that this touch block
    * triggered a single tap event.
-   * @return true if the flag was set. This may not happen if, for example,
-   *         SetDuringFastFling was previously called.
    */
-  bool SetSingleTapOccurred();
+  void SetSingleTapOccurred();
   /**
    * @return true iff the single-tap-occurred flag is set on this block.
    */
   bool SingleTapOccurred() const;
 
   /**
    * Add a new touch event to the queue of events in this input block.
    */
--- a/gfx/layers/apz/test/gtest/InputUtils.h
+++ b/gfx/layers/apz/test/gtest/InputUtils.h
@@ -475,9 +475,20 @@ DoubleTapAndCheckStatus(const RefPtr<Inp
   nsEventStatus statuses[4];
   DoubleTap(aTarget, aPoint, aMcc, &statuses, aOutInputBlockIds);
   EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
   EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]);
   EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[2]);
   EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[3]);
 }
 
+template<class InputReceiver>
+nsEventStatus
+Wheel(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
+      const ScreenPoint& aDelta, TimeStamp aTime, uint64_t* aOutInputBlockId = nullptr)
+{
+  ScrollWheelInput input(MillisecondsSinceStartup(aTime), aTime, 0,
+      ScrollWheelInput::SCROLLMODE_INSTANT, ScrollWheelInput::SCROLLDELTA_PIXEL,
+      aPoint, aDelta.x, aDelta.y, false);
+  return aTarget->ReceiveInputEvent(input, nullptr, aOutInputBlockId);
+}
+
 #endif // mozilla_layers_InputUtils_h
--- a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
+++ b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
@@ -587,8 +587,43 @@ TEST_F(APZCGestureDetectorTester, TapFol
   mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_END, mcc->Time());
   mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
   mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   apzc->AssertStateIsReset();
 }
 
+TEST_F(APZCGestureDetectorTester, LongPressInterruptedByWheel) {
+  // Since the wheel block interrupted the long-press, we don't expect
+  // any long-press notifications. However, this also shouldn't crash, which
+  // is what it used to do.
+  EXPECT_CALL(*mcc, HandleLongTap(_, _, _, _)).Times(0);
+
+  uint64_t touchBlockId = 0;
+  uint64_t wheelBlockId = 0;
+  TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &touchBlockId);
+  mcc->AdvanceByMillis(10);
+  Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time(), &wheelBlockId);
+  EXPECT_NE(touchBlockId, wheelBlockId);
+  mcc->AdvanceByMillis(1000);
+}
+
+TEST_F(APZCGestureDetectorTester, TapTimeoutInterruptedByWheel) {
+  // In this test, even though the wheel block comes right after the tap, the
+  // tap should still be dispatched because it completes fully before the wheel
+  // block arrived.
+  EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
+
+  // We make the APZC zoomable so the gesture detector needs to wait to
+  // distinguish between tap and double-tap. During that timeout is when we
+  // insert the wheel event.
+  MakeApzcZoomable();
+
+  uint64_t touchBlockId = 0;
+  uint64_t wheelBlockId = 0;
+  Tap(apzc, ScreenIntPoint(10, 10), mcc, TimeDuration::FromMilliseconds(100),
+      nullptr, &touchBlockId);
+  mcc->AdvanceByMillis(10);
+  Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time(), &wheelBlockId);
+  EXPECT_NE(touchBlockId, wheelBlockId);
+  while (mcc->RunThroughDelayedTasks());
+}
--- a/gfx/layers/apz/test/reftest/reftest.list
+++ b/gfx/layers/apz/test/reftest/reftest.list
@@ -1,16 +1,16 @@
 # The following tests test the async positioning of the scrollbars.
 # Basic root-frame scrollbar with async scrolling
 fuzzy-if(Android,6,8) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
 fuzzy-if(Android,6,8) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
 fuzzy-if(Android,6,8) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
 fuzzy-if(Android,6,8) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
-fuzzy-if(Android,6,8) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
-fuzzy-if(Android,6,8) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
+fuzzy-if(Android,13,8) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
+fuzzy-if(Android,8,10) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
 
 # Different async zoom levels. Since the scrollthumb gets async-scaled in the
 # compositor, the border-radius ends of the scrollthumb are going to be a little
 # off, hence the fuzzy-if clauses.
 skip-if(!asyncZoom) fuzzy-if(B2G,98,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
 skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-scrollbar-zoom-2-ref.html
 
 # Meta-viewport tag support
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -161,39 +161,44 @@ BasicCompositor::CreateRenderTargetFromS
                                               const CompositingRenderTarget *aSource,
                                               const IntPoint &aSourcePoint)
 {
   MOZ_CRASH("GFX: Shouldn't be called!");
   return nullptr;
 }
 
 already_AddRefed<CompositingRenderTarget>
-BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode)
+BasicCompositor::CreateRenderTargetForWindow(const LayoutDeviceIntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode)
 {
-  if (aBufferMode != BufferMode::BUFFER_NONE) {
-    return CreateRenderTarget(aRect, aInit);
-  }
-
+  MOZ_ASSERT(mDrawTarget);
   MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
 
   if (aRect.width * aRect.height == 0) {
     return nullptr;
   }
 
-  MOZ_ASSERT(mDrawTarget);
+  RefPtr<BasicCompositingRenderTarget> rt;
+  IntRect rect = aRect.ToUnknownRect();
 
-  // Adjust bounds rect to account for new origin at (0, 0).
-  IntRect windowRect = aRect;
-  if (aRect.Size() != mDrawTarget->GetSize()) {
-    windowRect.ExpandToEnclose(IntPoint(0, 0));
-  }
-  RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(mDrawTarget, windowRect);
-
-  if (aInit == INIT_MODE_CLEAR) {
-    mDrawTarget->ClearRect(Rect(aRect - rt->GetOrigin()));
+  if (aBufferMode != BufferMode::BUFFER_NONE) {
+    RefPtr<DrawTarget> target = mWidget->CreateBackBufferDrawTarget(mDrawTarget, aRect);
+    if (!target) {
+      return nullptr;
+    }
+    rt = new BasicCompositingRenderTarget(target, rect);
+  } else {
+    IntRect windowRect = rect;
+    // Adjust bounds rect to account for new origin at (0, 0).
+    if (windowRect.Size() != mDrawTarget->GetSize()) {
+      windowRect.ExpandToEnclose(IntPoint(0, 0));
+    }
+    rt = new BasicCompositingRenderTarget(mDrawTarget, windowRect);
+    if (aInit == INIT_MODE_CLEAR) {
+      mDrawTarget->ClearRect(Rect(rect - rt->GetOrigin()));
+    }
   }
 
   return rt.forget();
 }
 
 already_AddRefed<DataTextureSource>
 BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
 {
@@ -626,17 +631,17 @@ BasicCompositor::BeginFrame(const nsIntR
 
   if (!mDrawTarget || mInvalidRect.IsEmpty()) {
     return;
   }
 
   // Setup an intermediate render target to buffer all compositing. We will
   // copy this into mDrawTarget (the widget), and/or mTarget in EndFrame()
   RefPtr<CompositingRenderTarget> target =
-    CreateRenderTargetForWindow(mInvalidRect.ToUnknownRect(),
+    CreateRenderTargetForWindow(mInvalidRect,
                                 aOpaque ? INIT_MODE_NONE : INIT_MODE_CLEAR,
                                 bufferMode);
   if (!target) {
     if (!mTarget) {
       mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion);
     }
     return;
   }
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -58,17 +58,17 @@ public:
   CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override;
 
   virtual already_AddRefed<CompositingRenderTarget>
   CreateRenderTargetFromSource(const gfx::IntRect &aRect,
                                const CompositingRenderTarget *aSource,
                                const gfx::IntPoint &aSourcePoint) override;
 
   virtual already_AddRefed<CompositingRenderTarget>
-  CreateRenderTargetForWindow(const gfx::IntRect& aRect,
+  CreateRenderTargetForWindow(const LayoutDeviceIntRect& aRect,
                               SurfaceInitMode aInit,
                               BufferMode aBufferMode);
 
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
 
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) override;
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -57,20 +57,22 @@ LOCAL_INCLUDES += [
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
     DEFINES['SK_FONTHOST_CAIRO_STANDALONE'] = 0
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in {
     'android',
     'cocoa',
+    'gtk2',
+    'gtk3',
     'uikit',
     'gonk',
     'qt',
-  } or CONFIG['MOZ_WIDGET_GTK']:
+  }:
     DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DEFINES['UNICODE'] = True
     DEFINES['_UNICODE'] = True
 
 # We should autogenerate these SSE related flags.
 
@@ -376,17 +378,17 @@ def write_mozbuild(sources):
   write_sources(f, sources['gpu'], 4)
 
   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):\n")
   write_sources(f, sources['android'], 4)
 
   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in {'cocoa', 'uikit'}:\n")
   write_sources(f, sources['mac'], 4)
 
-  f.write("if CONFIG['MOZ_WIDGET_GTK']:\n")
+  f.write("if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:\n")
   write_sources(f, sources['linux'], 4)
 
   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':\n")
   write_sources(f, sources['linux'], 4)
 
   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':\n")
   # Windows-specific files don't get unification because of nasty headers.
   # Luckily there are not many files in this.
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -548,17 +548,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in {'coc
         'skia/src/ports/SkTLS_pthread.cpp',
         'skia/src/utils/mac/SkCreateCGImageRef.cpp',
         'skia/src/utils/mac/SkStream_mac.cpp',
         'skia/src/utils/SkThreadUtils_pthread.cpp',
     ]
     SOURCES += [
         'skia/src/ports/SkFontHost_mac.cpp',
     ]
-if CONFIG['MOZ_WIDGET_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     UNIFIED_SOURCES += [
         'skia/src/ports/SkDebug_stdio.cpp',
         'skia/src/ports/SkOSFile_posix.cpp',
         'skia/src/ports/SkOSLibrary_posix.cpp',
         'skia/src/ports/SkTime_Unix.cpp',
         'skia/src/ports/SkTLS_pthread.cpp',
         'skia/src/utils/SkThreadUtils_pthread.cpp',
     ]
@@ -675,20 +675,22 @@ LOCAL_INCLUDES += [
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
     DEFINES['SK_FONTHOST_CAIRO_STANDALONE'] = 0
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in {
     'android',
     'cocoa',
+    'gtk2',
+    'gtk3',
     'uikit',
     'gonk',
     'qt',
-  } or CONFIG['MOZ_WIDGET_GTK']:
+  }:
     DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DEFINES['UNICODE'] = True
     DEFINES['_UNICODE'] = True
 
 # We should autogenerate these SSE related flags.
 
--- a/gfx/src/moz.build
+++ b/gfx/src/moz.build
@@ -76,16 +76,16 @@ LOCAL_INCLUDES += [
     '/dom/ipc',  # for ContentChild.h
 ]
 
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 
-if CONFIG['MOZ_WIDGET_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     CXXFLAGS += CONFIG['MOZ_QT_CFLAGS']
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
--- a/gfx/tests/gtest/TestCompositor.cpp
+++ b/gfx/tests/gtest/TestCompositor.cpp
@@ -1,16 +1,17 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 #include "gfxPrefs.h"
 #include "gfxUtils.h"
 #include "gtest/gtest.h"
+#include "gtest/MozGTestBench.h"
 #include "TestLayers.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/layers/BasicCompositor.h"  // for BasicCompositor
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayerManagerComposite.h"
@@ -222,49 +223,56 @@ static bool CompositeAndCompare(RefPtr<L
   return true;
 }
 
 TEST(Gfx, CompositorConstruct)
 {
   auto layerManagers = GetLayerManagers(GetPlatformBackends());
 }
 
-TEST(Gfx, CompositorSimpleTree)
-{
+static void CompositorSimpleTree() {
+  const int benchmarkRepeatCount = 30;
+
+  RefPtr<DrawTarget> refDT = CreateDT();
+  refDT->FillRect(Rect(0, 0, gCompWidth, gCompHeight), ColorPattern(Color(1.f, 0.f, 1.f, 1.f)));
+  refDT->FillRect(Rect(0, 0, 100, 100), ColorPattern(Color(1.f, 0.f, 0.f, 1.f)));
+  refDT->FillRect(Rect(0, 50, 100, 100), ColorPattern(Color(0.f, 0.f, 1.f, 1.f)));
+
   auto layerManagers = GetLayerManagers(GetPlatformBackends());
   for (size_t i = 0; i < layerManagers.size(); i++) {
-    RefPtr<LayerManagerComposite> layerManager = layerManagers[i].mLayerManager;
-    RefPtr<LayerManager> lmBase = layerManager.get();
-    nsTArray<RefPtr<Layer>> layers;
-    nsIntRegion layerVisibleRegion[] = {
-      nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
-      nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
-      nsIntRegion(IntRect(0, 0, 100, 100)),
-      nsIntRegion(IntRect(0, 50, 100, 100)),
-    };
-    RefPtr<Layer> root = CreateLayerTree("c(ooo)", layerVisibleRegion, nullptr, lmBase, layers);
+    // Benchmark n composites
+    for (size_t n = 0; n < benchmarkRepeatCount; n++) {
+      RefPtr<LayerManagerComposite> layerManager = layerManagers[i].mLayerManager;
+      RefPtr<LayerManager> lmBase = layerManager.get();
+      nsTArray<RefPtr<Layer>> layers;
+      nsIntRegion layerVisibleRegion[] = {
+        nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
+        nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
+        nsIntRegion(IntRect(0, 0, 100, 100)),
+        nsIntRegion(IntRect(0, 50, 100, 100)),
+      };
+      RefPtr<Layer> root = CreateLayerTree("c(ooo)", layerVisibleRegion, nullptr, lmBase, layers);
 
-    { // background
-      ColorLayer* colorLayer = layers[1]->AsColorLayer();
-      colorLayer->SetColor(Color(1.f, 0.f, 1.f, 1.f));
-      colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
-    }
+      { // background
+        ColorLayer* colorLayer = layers[1]->AsColorLayer();
+        colorLayer->SetColor(Color(1.f, 0.f, 1.f, 1.f));
+        colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
+      }
 
-    {
-      ColorLayer* colorLayer = layers[2]->AsColorLayer();
-      colorLayer->SetColor(Color(1.f, 0.f, 0.f, 1.f));
-      colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
-    }
+      {
+        ColorLayer* colorLayer = layers[2]->AsColorLayer();
+        colorLayer->SetColor(Color(1.f, 0.f, 0.f, 1.f));
+        colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
+      }
 
-    {
-      ColorLayer* colorLayer = layers[3]->AsColorLayer();
-      colorLayer->SetColor(Color(0.f, 0.f, 1.f, 1.f));
-      colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
-    }
+      {
+        ColorLayer* colorLayer = layers[3]->AsColorLayer();
+        colorLayer->SetColor(Color(0.f, 0.f, 1.f, 1.f));
+        colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
+      }
 
-    RefPtr<DrawTarget> refDT = CreateDT();
-    refDT->FillRect(Rect(0, 0, gCompWidth, gCompHeight), ColorPattern(Color(1.f, 0.f, 1.f, 1.f)));
-    refDT->FillRect(Rect(0, 0, 100, 100), ColorPattern(Color(1.f, 0.f, 0.f, 1.f)));
-    refDT->FillRect(Rect(0, 50, 100, 100), ColorPattern(Color(0.f, 0.f, 1.f, 1.f)));
-    EXPECT_TRUE(CompositeAndCompare(layerManager, refDT));
+      EXPECT_TRUE(CompositeAndCompare(layerManager, refDT));
+    }
   }
-}
+};
 
+MOZ_GTEST_BENCH(GfxBench, CompositorSimpleTree, &CompositorSimpleTree);
+
--- a/gfx/tests/gtest/TestRegion.cpp
+++ b/gfx/tests/gtest/TestRegion.cpp
@@ -1,16 +1,18 @@
 /* -*- 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 <algorithm>
 
 #include "gtest/gtest.h"
+#include "gtest/MozGTestBench.h"
+#include "nsRect.h"
 #include "nsRegion.h"
 
 using namespace std;
 
 class TestLargestRegion {
 public:
   static void TestSingleRect(nsRect r) {
     nsRegion region(r);
@@ -557,8 +559,27 @@ TEST(Gfx, RegionVisitEdges) {
     r.Or(r, nsRect(25, 50, 28, 5));
     r.Or(r, nsRect(115, 50, 99, 5));
     r.Or(r, nsRect(115, 55, 99, 12));
 
     TestVisit(r);
   }
 
 }
+
+MOZ_GTEST_BENCH(GfxBench, RegionOr, []{
+  const int size = 5000;
+  nsRegion r;
+  for (int i = 0; i < size; i++) {
+    r = r.Or(r, nsRect(i, i, i + 10, i + 10));
+  }
+});
+
+MOZ_GTEST_BENCH(GfxBench, RegionAnd, []{
+  const int size = 5000;
+  nsRegion r(nsRect(0, 0, size, size));
+  for (int i = 0; i < size; i++) {
+    nsRegion rMissingPixel(nsRect(0, 0, size, size));
+    rMissingPixel = rMissingPixel.Sub(rMissingPixel, nsRect(i, i, 1, 1));
+    r = r.And(r, rMissingPixel);
+  }
+});
+
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -1674,9 +1674,9 @@ static void
 ApplyGdkScreenFontOptions(FcPattern *aPattern)
 {
     const cairo_font_options_t *options =
         gdk_screen_get_font_options(gdk_screen_get_default());
 
     cairo_ft_font_options_substitute(options, aPattern);
 }
 
-#endif // MOZ_WIDGET_GTK2
+#endif // MOZ_WIDGET_GTK
--- a/gfx/thebes/gfxFontconfigFonts.cpp
+++ b/gfx/thebes/gfxFontconfigFonts.cpp
@@ -2257,17 +2257,17 @@ static void
 ApplyGdkScreenFontOptions(FcPattern *aPattern)
 {
     const cairo_font_options_t *options =
         gdk_screen_get_font_options(gdk_screen_get_default());
 
     cairo_ft_font_options_substitute(options, aPattern);
 }
 
-#endif // MOZ_WIDGET_GTK2
+#endif // MOZ_WIDGET_GTK
 
 #ifdef USE_SKIA
 already_AddRefed<mozilla::gfx::GlyphRenderingOptions>
 gfxFcFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams)
 {
   cairo_scaled_font_t *scaled_font = CairoScaledFont();
   cairo_font_options_t *options = cairo_font_options_create();
   cairo_scaled_font_get_font_options(scaled_font, options);
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1234,17 +1234,20 @@ gfxPlatform::InitializeSkiaCacheLimits()
 #endif
   }
 }
 
 SkiaGLGlue*
 gfxPlatform::GetSkiaGLGlue()
 {
 #ifdef USE_SKIA_GPU
-  if (!UseAcceleratedCanvas()) {
+  // Check the accelerated Canvas is enabled for the first time,
+  // because the callers should check it before using.
+  if (!mSkiaGlue &&
+      !UseAcceleratedCanvas()) {
     gfxCriticalNote << "Accelerated Skia canvas is disabled";
     return nullptr;
   }
 
   if (!mSkiaGlue) {
     /* Dummy context. We always draw into a FBO.
      *
      * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -95,17 +95,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     SOURCES += [
         'gfxCoreTextShaper.cpp',
         'gfxMacFont.cpp',
         'gfxPlatformMac.cpp',
         'gfxQuartzImageSurface.cpp',
         'gfxQuartzNativeDrawing.cpp',
         'gfxQuartzSurface.cpp',
     ]
-elif CONFIG['MOZ_WIDGET_GTK']:
+elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     EXPORTS += [
         'gfxFontconfigFonts.h',
         'gfxFT2FontBase.h',
         'gfxGdkNativeRenderer.h',
         'gfxPDFSurface.h',
         'gfxPlatformGtk.h',
         'gfxPSSurface.h',
     ]
--- a/image/decoders/icon/moz.build
+++ b/image/decoders/icon/moz.build
@@ -11,17 +11,17 @@ UNIFIED_SOURCES += [
 ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 platform = None
 
-if CONFIG['MOZ_WIDGET_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     platform = 'gtk'
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     platform = 'qt'
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     platform = 'win'
 
--- a/image/decoders/moz.build
+++ b/image/decoders/moz.build
@@ -3,17 +3,17 @@
 # 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/.
 
 toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
 
 # The Icon Channel stuff really shouldn't live in decoders/icon, but we'll
 # fix that another time.
-if CONFIG['MOZ_WIDGET_GTK']:
+if 'gtk' in toolkit:
     DIRS += ['icon/gtk', 'icon']
 elif toolkit == 'qt':
     DIRS += ['icon/qt', 'icon']
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['icon/win', 'icon']
 
 if toolkit == 'cocoa':
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/downscaling/downscale-32px-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<body style="margin: 0px">
+  <img src="lime-red-32px.png">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/downscaling/downscale-32px.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html class="reftest-wait">
+<head>
+  <script>
+    function snapshot() {
+      document.documentElement.removeAttribute('class');
+    }
+  </script>
+</head>
+<!-- NOTE: Using setTimeout to wait for high-quality downscaled version of
+     image to be ready, because there's nothing better we can do. If we fix
+     Bug 1006883, we can do away with this setTimeout.
+
+     For now, the setTimeout is just here to increase the likelihood that we
+     actually test the high-quality downscaled version of the image. If the
+     setTimeout happens to fire before the high-quality downscaled rendering is
+     ready, then this the test will pass without testing what it's trying to
+     test, which is fine as long as that's rare.  -->
+<body style="margin: 0px" onload="setTimeout(snapshot, 50)">
+  <script>
+    var args = location.search.substring(1).split(',');
+    var image = document.createElement('img');
+    image.width = "32";
+    image.height = "32";
+    image.src = 'lime-red-256px' + location.search.substring(1);
+    document.body.appendChild(image);
+  </script>
+</body>
+</html>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b372cba4a21f97f12feb548045785a0f09c762fe
GIT binary patch
literal 74814
zc%1Feu@QhU3<SX!5fxAYf%|XJ7#tG=!=4mqlx<RD&MIr#UfIUo<|A3=|Gs{$r2kb9
z$Is8t&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#
z&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#
z&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#
z&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#
z&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&(F`#&;Jg;BuSDa
NNs=T<k|as`eh1h(f}sEa
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e8578d29341a70e453687abfbda7e39bd8dfa7a5
GIT binary patch
literal 881
zc${NkU<5)CU}WH6h-PMB5CgJ11N_{1xum#&OkPh9mmmhP8lVa`AQe-zB8`E8S;^DI
zF{EP7+bf2Q2Ml-)Y$*9-nQl-N;q>5iep%UxTjj9_mcF-Q*pbX2kT!}&(a1yJn4dpq
V`L~Vp`C?G^@^tlcS?83{1OTn&mL>oI
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3dc808970f7d8fa5b9d66c81d3a7ff3016755059
GIT binary patch
literal 196730
zc%1FdAr8V&6h*;bDv=o0Q-i{=4jhin1Es;>P$Ld6^OL6Lp5=TW^H}fxde`-1+TJvd
zW4n1A_T&9Nx127w@#F2je?0yuU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU
z1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVji
zU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M
z^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9
zI$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMu
zuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l
z{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*
z-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5
z>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?
zo8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#W
zwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7
zL7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X
z7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6
zd_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2
z&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa
z>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~s
zzs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH
z_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_M
zdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJ
zruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmio
zZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui
z(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU
z1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVji
zU(lxa>wH0*-mmioZF;}X7qsd9I$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M
z^95~szs?u5>HRui(5Cn6d_kMuuk!_MdcV#WwCVjiU(lxa>wH0*-mmioZF;}X7qsd9
zI$zMH_v?H?o8GVU1#No2&KI=l{W@RJruXZ7L7U#M^95~szs?u5>HRui(5Cn6d_kMu
Ouk!_MdcV#Wq&)%2bP|pL
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f9f669aa4dfdabf88e313ef47b7b7d5d3e7ea850
GIT binary patch
literal 873
zc$@)g1D5<pNk%v~VE_RD0e}Gj{{R30{{Soi000000RRC20{)DTsmtvTqnr%bi?iOm
z`wxcV$Wi8rrm9J{?hD85O4s&X$@<Rs8x9N#CBCBZC>ko4N~H7YWJ;$rsP(F&YPUqJ
z_Z#Ah#|g0coFS{l=(c$cr@H6ZxP3{_KkxjY{%_PLXaiWtGl-~SxEPb@$if&&@<<sW
zc^OuznS<H+vk8jeIhqz~N{R|#dYU@A8rtgmx*6*^OIwS1tC_32OWAw*3mhCd{8(&!
zoS4kG%-n4Fj2JCFEm&Q6jh+3s-Pi5?eHX4bPF_xTZkMjU4%a^S4j<n(zgBO5PnM6i
z&)@IOKQ;lu3?x|4%Rw#)zbxF+P~k&45wA?7SP{y_{wW!)Y?RVb<3~Ipql|1)63I!F
zDFdw(((=elm@$jY^i$KvO&~dS?!3{n$4{U^cMK&|G|SN{No6c$+7!mq6;T^aO;J_q
zRTNoYY~|W@##cyTM~o#~Hq+TIY1OWU&^F0iOL0NWrCZm-UATGm?sd@D?_W-VH4JW0
zxWwTFi9ana)40@QQIRoBhFsagWy+aVZ8p$Z^XCAeJ%27ensn&Ys7JRxz1nqb*qvF=
z-uxQ(?aR4&@1EQn`0vNTi4R{~9QpCX$(b)7+#LGzztO2r-&-B~^}E@*Z=c&8{P(xv
z$&X)K9{u^V>DjLz+aCV=ukq>6-&!C4{j2%@`R||FAAtWo6(E5FE>$3c2OgCmg9{GT
zAcPP86d{EZ?o=U$7v7X1ha1k+A&4Ko6e5Wuu2dq5C!Uldiz|-QB8)G76eEo@Zd4<V
zH(rz@k2_A(BalBn6eN*DE>t9vM;??UlS>ZNB$QA76D5^X?o%a}SKgB)ms`%$C755n
z6DFBsu2UwOXP%QLn`@5KCY*166DOT>Zc`_ocV3expL<TzC!l{m6DXmBE>kF?haQtC
zql*sHD5Q`65-FvV?ouhHm)?>or<=~wDX5>m5-O>qu2L$hr?OI;Y^~CknQgD?Hmh&7
z3U{k<xhl7-bG=IUt98L@H>`KXig!z_dC97`tb5JM_pE)<>Nl-_)e3m6f!Qj!t%Kc4
z_^pNEYB;Wk<%)Q&iRr4iu8Zx;_^yrd>Nu~D^$K~fk@+gQuao^s`LC6o6#xJ`Mm4vj
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ac8efdf3602d2f6b46575f61590b6a7c11831e2f
GIT binary patch
literal 2865
zc%1ux<NpH&0WUXCHwH#VMg|WcWcYuZ!5PG(2!ITs)C|V|2N(o77#SEDm>C5bm;@P_
z1sVSzVUTBFU}S|TV1NQfCT12^Hg*n9E^eTLtpW^8jLghTEX=H|EG$6TTA(}wiy*6z
zqM;+3a9|?4QlW@Z<HUs=%1#>(iUwW$pkka<)WpdpCN3c<rK+Z`p{ZqJYG!U>Y31zV
z>gMj@=@lFj8WtWA8I_!pnwFlCnN?g;T2@|BS=HRq+ScCD*)?hMl&RCE&zL!D(c&db
zmn~nha@D5ITefc7zGLUELx+zXJ$C%W$y1juU%7hi`i+~n9zJ^f<mt2LFJ8X-`04YP
zuiw7^`1uRuFOWZB0IR=%fxyVb!otkL4)PZxQ#nY1APcLaA)An6AbVn=u#!<Dhlta}
zg&PlYDjNrV5KSt&$R(y?@=*07$ZKGq5$CZcvU~>j7{Xt-7<iZ&fsw~7$Y9U#>(KtE
zHUAm93KlRma4~2wV4?nHzy9lC|2+VQG?3zd>9qfJ@qY%c52L1xnlft2s41hSjG8iP
M%BU$cH|76L09C9*Y5)KL
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2be2e05a59b44d1d66ed188c8943b7c4cee16f52
GIT binary patch
literal 568
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9$ocQ-;uunK>+NMjUIqpZ7Q+Mk
zpQpPqdTT$N^xEsA#@d6+Co(WMFdkq?U@%~iVBle3qdJ#1rXq1^=X3~{#^IAdL#MA}
YWszt8?_JyN156PNp00i_>zopr09JTe#{d8T
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/downscaling/lime-red-256px.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
+     width="256" height="256">
+  <rect width="50%" height="100%" fill="lime"/>
+  <rect x="50%" width="50%" height="100%" fill="red"/>
+</svg>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bfa2e7b7374ceaba1d37ab1d182fb19498f8161a
GIT binary patch
literal 103
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1SJ1Ryj={W^gLZ0Lp+YZJ-d;Y!GMEhWBcE7
tHDiT|=fdYdIhAtt%DeY9d<-xU^Oa#z1(W^8GTql8uBWS?%Q~loCID+x9!LNH
--- a/image/test/reftest/downscaling/reftest.list
+++ b/image/test/reftest/downscaling/reftest.list
@@ -92,16 +92,25 @@ fuzzy(20,999) fails-if(OSX>=1008&&!skiaC
 
 # Non-transparent and transparent ICO images
 == downscale-16px.html?ff-0RGB.ico downscale-16px.html?ff-0RGB.png
 fuzzy(1,1) == downscale-16px.html?ff-ARGB.ico downscale-16px.html?ff-ARGB.png
 
 # Upside-down (negative height) BMP
 == downscale-8px.html?top-to-bottom-16x16-24bpp.bmp downscale-8px.html?bmp-size-16x16-24bpp.png
 
+# Test downscaling from all supported formats from 256 to 32.
+== downscale-32px.html?.bmp downscale-32px-ref.html
+== downscale-32px.html?.gif downscale-32px-ref.html
+fuzzy(1,1024) == downscale-32px.html?.jpg downscale-32px-ref.html
+== downscale-32px.html?.png downscale-32px-ref.html
+== downscale-32px.html?.svg downscale-32px-ref.html
+== downscale-32px.html?-bmp-in.ico downscale-32px-ref.html
+== downscale-32px.html?-png-in.ico downscale-32px-ref.html
+
 # RUN TESTS WITH DOWNSCALE-DURING-DECODE ENABLED:
 # ===============================================
 default-preferences pref(image.downscale-during-decode.enabled,true)
 
 fuzzy(31,127) fuzzy-if(d2d,31,147) == downscale-1.html downscale-1-ref.html # intermittently 147 pixels on win7 accelerated only (not win8)
 
 fuzzy(20,999) != downscale-2a.html?203,52,left about:blank
 fuzzy(20,999) != downscale-2b.html?203,52,left about:blank
@@ -164,8 +173,16 @@ fuzzy(20,999) != downscale-2f.html?205,5
 
 # Non-transparent and transparent ICO images
 fuzzy(1,3) == downscale-16px.html?ff-0RGB.ico downscale-16px.html?ff-0RGB.png
 fuzzy(3,32) == downscale-16px.html?ff-ARGB.ico downscale-16px.html?ff-ARGB.png
 
 # Upside-down (negative height) BMP
 == downscale-8px.html?top-to-bottom-16x16-24bpp.bmp downscale-8px.html?bmp-size-16x16-24bpp.png
 
+# Test downscaling from all supported formats from 256 to 32.
+fuzzy(18,128) == downscale-32px.html?.bmp downscale-32px-ref.html
+fuzzy(18,128) == downscale-32px.html?.gif downscale-32px-ref.html
+fuzzy(19,992) == downscale-32px.html?.jpg downscale-32px-ref.html
+fuzzy(18,128) == downscale-32px.html?.png downscale-32px-ref.html
+== downscale-32px.html?.svg downscale-32px-ref.html
+fuzzy(18,128) == downscale-32px.html?-bmp-in.ico downscale-32px-ref.html
+fuzzy(18,128) == downscale-32px.html?-png-in.ico downscale-32px-ref.html
--- a/intl/lwbrk/moz.build
+++ b/intl/lwbrk/moz.build
@@ -19,20 +19,21 @@ EXPORTS += [
 ]
 
 UNIFIED_SOURCES += [
     'nsJISx4051LineBreaker.cpp',
     'nsSampleWordBreaker.cpp',
     'nsSemanticUnitScanner.cpp',
 ]
 
-if CONFIG['MOZ_WIDGET_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     SOURCES += [
         'nsPangoBreaker.cpp',
     ]
+    CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     SOURCES += [
         'nsUniscribeBreaker.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'nsCarbonBreaker.cpp',
     ]
@@ -41,13 +42,10 @@ else:
         'nsRuleBreaker.cpp',
     ]
     SOURCES += [
         'rulebrk.c',
     ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['MOZ_WIDGET_GTK']:
-    CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
-
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
--- a/ipc/chromium/moz.build
+++ b/ipc/chromium/moz.build
@@ -146,17 +146,17 @@ if os_linux:
     if CONFIG['OS_TARGET'] == 'Android':
         UNIFIED_SOURCES += [
             'src/base/message_pump_android.cc',
         ]
         DEFINES['ANDROID'] = True
         DEFINES['_POSIX_MONOTONIC_CLOCK'] = 0
 
 if os_bsd or os_linux:
-    if CONFIG['MOZ_WIDGET_GTK']:
+    if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         SOURCES += [
             'src/base/message_pump_glib.cc',
         ]
     if CONFIG['MOZ_ENABLE_QT']:
         SOURCES += [
             '!moc_message_pump_qt.cc',
             'src/base/message_pump_qt.cc',
         ]
--- a/ipc/glue/BackgroundParent.h
+++ b/ipc/glue/BackgroundParent.h
@@ -86,12 +86,18 @@ AssertIsOnBackgroundThread();
 #else
 
 inline void
 AssertIsOnBackgroundThread()
 { }
 
 #endif // DEBUG
 
+inline void
+AssertIsInMainProcess()
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_backgroundparent_h__
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -53,22 +53,16 @@ using mozilla::dom::MessagePortParent;
 using mozilla::dom::PMessagePortParent;
 using mozilla::dom::PNuwaParent;
 using mozilla::dom::NuwaParent;
 using mozilla::dom::UDPSocketParent;
 
 namespace {
 
 void
-AssertIsInMainProcess()
-{
-  MOZ_ASSERT(XRE_IsParentProcess());
-}
-
-void
 AssertIsOnMainThread()
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 class TestParent final : public mozilla::ipc::PBackgroundTestParent
 {
   friend class mozilla::ipc::BackgroundParentImpl;
@@ -747,11 +741,11 @@ BackgroundParentImpl::DeallocPQuotaParen
 }
 
 } // namespace ipc
 } // namespace mozilla
 
 void
 TestParent::ActorDestroy(ActorDestroyReason aWhy)
 {
-  AssertIsInMainProcess();
+  mozilla::ipc::AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 }
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -1625,16 +1625,17 @@ class MOZ_STACK_CLASS ModuleValidator
     }
     bool addStandardLibrarySimdOpName(const char* name, SimdOperation op) {
         JSAtom* atom = Atomize(cx_, name, strlen(name));
         if (!atom)
             return false;
         return standardLibrarySimdOpNames_.putNew(atom->asPropertyName(), op);
     }
     bool newSig(Sig&& sig, uint32_t* sigIndex) {
+        *sigIndex = 0;
         if (mg_.numSigs() >= MaxSigs)
             return failCurrentOffset("too many signatures");
 
         *sigIndex = mg_.numSigs();
         mg_.initSig(*sigIndex, Move(sig));
         return true;
     }
     bool declareSig(Sig&& sig, uint32_t* sigIndex) {
@@ -2902,16 +2903,17 @@ CheckFunctionHead(ModuleValidator& m, Pa
     if (fn->pn_funbox->hasDestructuringArgs)
         return m.fail(fn, "destructuring args not allowed");
     return true;
 }
 
 static bool
 CheckArgument(ModuleValidator& m, ParseNode* arg, PropertyName** name)
 {
+    *name = nullptr;
     if (!IsDefinition(arg))
         return m.fail(arg, "duplicate argument name not allowed");
 
     if (arg->isKind(PNK_ASSIGN))
         return m.fail(arg, "default arguments not allowed");
 
     if (!CheckIdentifier(m, arg, arg->name()))
         return false;
@@ -3616,16 +3618,18 @@ IsLiteralOrConstInt(FunctionValidator& f
 static const int32_t NoMask = -1;
 static const bool YesSimd = true;
 static const bool NoSimd = false;
 
 static bool
 CheckArrayAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
                  bool isSimd, Scalar::Type* viewType, int32_t* mask)
 {
+    *mask = 0;
+
     if (!viewName->isKind(PNK_NAME))
         return f.fail(viewName, "base of array access must be a typed array view name");
 
     const ModuleValidator::Global* global = f.lookupGlobal(viewName->name());
     if (!global || !global->isAnyArrayView())
         return f.fail(viewName, "base of array access must be a typed array view name");
 
     *viewType = global->viewType();
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -1081,17 +1081,17 @@ struct ImportName
     {}
 };
 
 typedef Vector<ImportName, 0, SystemAllocPolicy> ImportNameVector;
 
 static bool
 DecodeImport(JSContext* cx, Decoder& d, ModuleGeneratorData* init, ImportNameVector* importNames)
 {
-    const DeclaredSig* sig;
+    const DeclaredSig* sig = nullptr;
     if (!DecodeSignatureIndex(cx, d, *init, &sig))
         return false;
 
     if (!init->imports.emplaceBack(sig))
         return false;
 
     if (!CheckTypeForJS(cx, d, *sig))
         return false;
--- a/js/src/asmjs/WasmTextToBinary.cpp
+++ b/js/src/asmjs/WasmTextToBinary.cpp
@@ -2296,16 +2296,18 @@ ParseHexFloatLiteral(const char16_t* cur
     *result = BitwiseCast<Float>(bits);
     return true;
 }
 
 template <typename Float>
 static bool
 ParseFloatLiteral(WasmParseContext& c, WasmToken token, Float* result)
 {
+    *result = 0;
+
     switch (token.kind()) {
       case WasmToken::Index:
         *result = token.index();
         return true;
       case WasmToken::UnsignedInteger:
         *result = token.uint();
         return true;
       case WasmToken::SignedInteger:
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -34,16 +34,18 @@ using mozilla::IsNaN;
 using mozilla::FloorLog2;
 using mozilla::NumberIsInt32;
 
 ///////////////////////////////////////////////////////////////////////////
 // SIMD
 
 static_assert(unsigned(SimdType::Count) == 12, "sync with TypedObjectConstants.h");
 
+static bool ArgumentToLaneIndex(JSContext* cx, JS::HandleValue v, unsigned limit, unsigned* lane);
+
 static bool
 CheckVectorObject(HandleValue v, SimdType expectedType)
 {
     if (!v.isObject())
         return false;
 
     JSObject& obj = v.toObject();
     if (!obj.is<TypedObject>())
@@ -138,16 +140,23 @@ ErrorWrongTypeArg(JSContext* cx, size_t 
         return false;
 
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR,
                          typeNameStr, charArgIndex);
     JS_free(cx, typeNameStr);
     return false;
 }
 
+static inline bool
+ErrorBadIndex(JSContext* cx)
+{
+    JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
+    return false;
+}
+
 template<typename T>
 static SimdTypeDescr*
 GetTypeDescr(JSContext* cx)
 {
     RootedGlobalObject global(cx, cx->global());
     return GlobalObject::getOrCreateSimdTypeDescr(cx, global, T::type);
 }
 
@@ -849,24 +858,22 @@ BinaryFunc(JSContext* cx, unsigned argc,
 
 template<typename V>
 static bool
 ExtractLane(JSContext* cx, unsigned argc, Value* vp)
 {
     typedef typename V::Elem Elem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
-    if (args.length() < 2 || !IsVectorObject<V>(args[0]) || !args[1].isNumber())
+    if (args.length() < 2 || !IsVectorObject<V>(args[0]))
         return ErrorBadArgs(cx);
 
-    int32_t lane;
-    if (!NumberIsInt32(args[1].toNumber(), &lane))
-        return ErrorBadArgs(cx);
-    if (lane < 0 || uint32_t(lane) >= V::lanes)
-        return ErrorBadArgs(cx);
+    unsigned lane;
+    if (!ArgumentToLaneIndex(cx, args[1], V::lanes, &lane))
+        return false;
 
     Elem* vec = TypedObjectMemory<Elem*>(args[0]);
     Elem val = vec[lane];
     args.rval().set(V::ToValue(val));
     return true;
 }
 
 template<typename V>
@@ -916,22 +923,19 @@ ReplaceLane(JSContext* cx, unsigned argc
     CallArgs args = CallArgsFromVp(argc, vp);
     // Only the first and second arguments are mandatory
     if (args.length() < 2 || !IsVectorObject<V>(args[0]))
         return ErrorBadArgs(cx);
 
     Elem* vec = TypedObjectMemory<Elem*>(args[0]);
     Elem result[V::lanes];
 
-    int32_t lanearg;
-    if (!args[1].isNumber() || !NumberIsInt32(args[1].toNumber(), &lanearg))
-        return ErrorBadArgs(cx);
-    if (lanearg < 0 || uint32_t(lanearg) >= V::lanes)
-        return ErrorBadArgs(cx);
-    uint32_t lane = uint32_t(lanearg);
+    unsigned lane;
+    if (!ArgumentToLaneIndex(cx, args[1], V::lanes, &lane))
+        return false;
 
     Elem value;
     if (!V::Cast(cx, args.get(2), &value))
         return false;
 
     for (unsigned i = 0; i < V::lanes; i++)
         result[i] = i == lane ? value : vec[i];
     return StoreResult<V>(cx, args, result);
@@ -942,24 +946,20 @@ static bool
 Swizzle(JSContext* cx, unsigned argc, Value* vp)
 {
     typedef typename V::Elem Elem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != (V::lanes + 1) || !IsVectorObject<V>(args[0]))
         return ErrorBadArgs(cx);
 
-    uint32_t lanes[V::lanes];
+    unsigned lanes[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
-        int32_t lane;
-        if (!args[i + 1].isNumber() || !NumberIsInt32(args[i + 1].toNumber(), &lane))
-            return ErrorBadArgs(cx);
-        if (lane < 0 || uint32_t(lane) >= V::lanes)
-            return ErrorBadArgs(cx);
-        lanes[i] = uint32_t(lane);
+        if (!ArgumentToLaneIndex(cx, args[i + 1], V::lanes, &lanes[i]))
+            return false;
     }
 
     Elem* val = TypedObjectMemory<Elem*>(args[0]);
 
     Elem result[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++)
         result[i] = val[lanes[i]];
 
@@ -971,24 +971,20 @@ static bool
 Shuffle(JSContext* cx, unsigned argc, Value* vp)
 {
     typedef typename V::Elem Elem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != (V::lanes + 2) || !IsVectorObject<V>(args[0]) || !IsVectorObject<V>(args[1]))
         return ErrorBadArgs(cx);
 
-    uint32_t lanes[V::lanes];
+    unsigned lanes[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
-        int32_t lane;
-        if (!args[i + 2].isNumber() || !NumberIsInt32(args[i + 2].toNumber(), &lane))
-            return ErrorBadArgs(cx);
-        if (lane < 0 || uint32_t(lane) >= (2 * V::lanes))
-            return ErrorBadArgs(cx);
-        lanes[i] = uint32_t(lane);
+        if (!ArgumentToLaneIndex(cx, args[i + 2], 2 * V::lanes, &lanes[i]))
+            return false;
     }
 
     Elem* lhs = TypedObjectMemory<Elem*>(args[0]);
     Elem* rhs = TypedObjectMemory<Elem*>(args[1]);
 
     Elem result[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
         Elem* selectedInput = lanes[i] < V::lanes ? lhs : rhs;
@@ -1303,34 +1299,46 @@ ArgumentToIntegerIndex(JSContext* cx, JS
     // floating point numbers end at 2^53, so make that our upper limit. If we
     // ever support arrays with more than 2^53 elements, this will need to
     // change.
     //
     // Reject infinities, NaNs, and numbers outside the contiguous integer range
     // with a RangeError.
 
     // Write relation so NaNs throw a RangeError.
-    if (!(0 <= d && d <= (uint64_t(1) << 53))) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
-        return false;
-    }
+    if (!(0 <= d && d <= (uint64_t(1) << 53)))
+        return ErrorBadIndex(cx);
 
     // Check that d is an integer, throw a RangeError if not.
     // Note that this conversion could invoke undefined behaviour without the
     // range check above.
     uint64_t i(d);
-    if (d != double(i)) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
-        return false;
-    }
+    if (d != double(i))
+        return ErrorBadIndex(cx);
 
     *index = i;
     return true;
 }
 
+// Extract an integer lane index from a function argument.
+//
+// Register an exception and return false if the argument is not suitable.
+static bool
+ArgumentToLaneIndex(JSContext* cx, JS::HandleValue v, unsigned limit, unsigned* lane)
+{
+    uint64_t arg;
+    if (!ArgumentToIntegerIndex(cx, v, &arg))
+        return false;
+    if (arg >= limit)
+        return ErrorBadIndex(cx);
+
+    *lane = unsigned(arg);
+    return true;
+}
+
 // Look for arguments (ta, idx) where ta is a TypedArray and idx is a
 // non-negative integer.
 // Check that accessBytes can be accessed starting from index idx in the array.
 // Return the array handle in typedArray and idx converted to a byte offset in byteStart.
 static bool
 TypedArrayFromArgs(JSContext* cx, const CallArgs& args, uint32_t accessBytes,
                    MutableHandleObject typedArray, size_t* byteStart)
 {
@@ -1345,21 +1353,20 @@ TypedArrayFromArgs(JSContext* cx, const 
 
     uint64_t index;
     if (!ArgumentToIntegerIndex(cx, args[1], &index))
         return false;
 
     // Do the range check in 64 bits even when size_t is 32 bits.
     // This can't overflow because index <= 2^53.
     uint64_t bytes = index * typedArray->as<TypedArrayObject>().bytesPerElement();
-    if ((bytes + accessBytes) > typedArray->as<TypedArrayObject>().byteLength()) {
-        // Keep in sync with AsmJS OnOutOfBounds function.
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
-        return false;
-    }
+    // Keep in sync with AsmJS OnOutOfBounds function.
+    if ((bytes + accessBytes) > typedArray->as<TypedArrayObject>().byteLength())
+        return ErrorBadIndex(cx);
+
     *byteStart = bytes;
 
     return true;
 }
 
 template<class V, unsigned NumElem>
 static bool
 Load(JSContext* cx, unsigned argc, Value* vp)
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -2268,16 +2268,17 @@ InitTypeClasses(JSContext* cx, HandleObj
 
   RootedObject ABIProto(cx, InitABIClass(cx));
   if (!ABIProto)
     return false;
 
   // Attach objects representing ABI constants.
   if (!DefineABIConstant(cx, ctypesObj, "default_abi", ABI_DEFAULT, ABIProto) ||
       !DefineABIConstant(cx, ctypesObj, "stdcall_abi", ABI_STDCALL, ABIProto) ||
+      !DefineABIConstant(cx, ctypesObj, "thiscall_abi", ABI_THISCALL, ABIProto) ||
       !DefineABIConstant(cx, ctypesObj, "winapi_abi", ABI_WINAPI, ABIProto))
     return false;
 
   // Create objects representing the builtin types, and attach them to the
   // ctypes object. Each type object 't' has:
   //   * [[Class]] "CType"
   //   * __proto__ === ctypes.CType.prototype
   //   * A constructor which creates and returns a CData object, containing
@@ -3912,16 +3913,18 @@ BuildTypeName(JSContext* cx, JSObject* t
       // Add in the calling convention, if it's not cdecl.
       // There's no trailing or leading space needed here, as none of the
       // modifiers can produce a string beginning with an identifier ---
       // except for TYPE_function itself, which is fine because functions
       // can't return functions.
       ABICode abi = GetABICode(fninfo->mABI);
       if (abi == ABI_STDCALL)
         PrependString(result, "__stdcall");
+      else if (abi == ABI_THISCALL)
+        PrependString(result, "__thiscall");
       else if (abi == ABI_WINAPI)
         PrependString(result, "WINAPI");
 
       // Function application binds more tightly than dereferencing, so
       // wrap pointer types in parens. Functions can't return functions
       // (only pointers to them), and arrays can't hold functions
       // (similarly), so we don't need to address those cases.
       if (prevGrouping == TYPE_pointer) {
@@ -4017,16 +4020,19 @@ BuildTypeSource(JSContext* cx,
 
     switch (GetABICode(fninfo->mABI)) {
     case ABI_DEFAULT:
       AppendString(result, "ctypes.default_abi, ");
       break;
     case ABI_STDCALL:
       AppendString(result, "ctypes.stdcall_abi, ");
       break;
+    case ABI_THISCALL:
+      AppendString(result, "ctypes.thiscall_abi, ");
+      break;
     case ABI_WINAPI:
       AppendString(result, "ctypes.winapi_abi, ");
       break;
     case INVALID_ABI:
       MOZ_CRASH("invalid abi");
     }
 
     // Recursively build the source string describing the function return and
@@ -5007,16 +5013,19 @@ ABI::ToSource(JSContext* cx, unsigned ar
   JSString* result;
   switch (GetABICode(obj)) {
     case ABI_DEFAULT:
       result = JS_NewStringCopyZ(cx, "ctypes.default_abi");
       break;
     case ABI_STDCALL:
       result = JS_NewStringCopyZ(cx, "ctypes.stdcall_abi");
       break;
+    case ABI_THISCALL:
+      result = JS_NewStringCopyZ(cx, "ctypes.thiscall_abi");
+      break;
     case ABI_WINAPI:
       result = JS_NewStringCopyZ(cx, "ctypes.winapi_abi");
       break;
     default:
       JS_ReportError(cx, "not a valid ABICode");
       return false;
   }
   if (!result)
@@ -6542,16 +6551,26 @@ GetABI(JSContext* cx, Value abiType, ffi
 
   // determine the ABI from the subset of those available on the
   // given platform. ABI_DEFAULT specifies the default
   // C calling convention (cdecl) on each platform.
   switch (abi) {
   case ABI_DEFAULT:
     *result = FFI_DEFAULT_ABI;
     return true;
+  case ABI_THISCALL:
+#if defined(_WIN64)
+    *result = FFI_WIN64;
+    return true;
+#elif defined(_WIN32)
+    *result = FFI_THISCALL;
+    return true;
+#else
+    break;
+#endif
   case ABI_STDCALL:
   case ABI_WINAPI:
 #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2)
     *result = FFI_STDCALL;
     return true;
 #elif (defined(_WIN64))
     // We'd like the same code to work across Win32 and Win64, so stdcall_api
     // and winapi_abi become aliases to the lone Win64 ABI.
@@ -6687,16 +6706,17 @@ void
 FunctionType::BuildSymbolName(JSString* name,
                               JSObject* typeObj,
                               AutoCString& result)
 {
   FunctionInfo* fninfo = GetFunctionInfo(typeObj);
 
   switch (GetABICode(fninfo->mABI)) {
   case ABI_DEFAULT:
+  case ABI_THISCALL:
   case ABI_WINAPI:
     // For cdecl or WINAPI functions, no mangling is necessary.
     AppendString(result, name);
     break;
 
   case ABI_STDCALL: {
 #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2)
     // On WIN32, stdcall functions look like:
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -206,16 +206,17 @@ enum ErrorNum {
  * ctypes.default_abi corresponds to the cdecl convention, and in almost all
  * cases is the correct choice. ctypes.stdcall_abi is provided for calling
  * stdcall functions on Win32, and implies stdcall symbol name decoration;
  * ctypes.winapi_abi is just stdcall but without decoration.
  */
 enum ABICode {
   ABI_DEFAULT,
   ABI_STDCALL,
+  ABI_THISCALL,
   ABI_WINAPI,
   INVALID_ABI
 };
 
 enum TypeCode {
   TYPE_void_t,
 #define DEFINE_TYPE(name, type, ffiType) TYPE_##name,
   CTYPES_FOR_EACH_TYPE(DEFINE_TYPE)
--- a/js/src/jit-test/tests/SIMD/replacelane.js
+++ b/js/src/jit-test/tests/SIMD/replacelane.js
@@ -56,29 +56,29 @@ function e() {
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
         try {
             let x = SIMD.Int32x4.replaceLane(i4, i < 149 ? 0 : 4, 42);
         } catch(e) {
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof RangeError, true);
             assertEq(i, 149);
             caught = true;
         }
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
         try {
             let x = SIMD.Int32x4.replaceLane(i4, i < 149 ? 0 : 1.1, 42);
         } catch(e) {
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof RangeError, true);
             assertEq(i, 149);
             caught = true;
         }
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
@@ -104,29 +104,29 @@ function e() {
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
         try {
             let x = SIMD.Float32x4.replaceLane(f4, i < 149 ? 0 : 4, 42);
         } catch(e) {
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof RangeError, true);
             assertEq(i, 149);
             caught = true;
         }
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
         try {
             let x = SIMD.Float32x4.replaceLane(f4, i < 149 ? 0 : 1.1, 42);
         } catch(e) {
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof RangeError, true);
             assertEq(i, 149);
             caught = true;
         }
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
@@ -152,29 +152,29 @@ function e() {
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
         try {
             let x = SIMD.Bool32x4.replaceLane(b4, i < 149 ? 0 : 4, true);
         } catch(e) {
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof RangeError, true);
             assertEq(i, 149);
             caught = true;
         }
         assertEq(i < 149 || caught, true);
     }
 
     for (let i = 0; i < 150; i++) {
         let caught = false;
         try {
             let x = SIMD.Bool32x4.replaceLane(b4, i < 149 ? 0 : 1.1, true);
         } catch(e) {
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof RangeError, true);
             assertEq(i, 149);
             caught = true;
         }
         assertEq(i < 149 || caught, true);
     }
 
 }
 
--- a/js/src/jit-test/tests/SIMD/shuffle.js
+++ b/js/src/jit-test/tests/SIMD/shuffle.js
@@ -48,37 +48,39 @@ function f() {
         var r = SIMD.Int32x4.shuffle(i1, i2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
         assertEqX4(r, compI[i % 8]);
 
         // Constant lanes
         assertEqX4(SIMD.Int32x4.shuffle(i1, i2, 3, 2, 4, 5), [4, 3, 5, 6]);
     }
 }
 
-function testBailouts(uglyDuckling) {
+function testBailouts(expectException, uglyDuckling) {
     var i1 = SIMD.Int32x4(1, 2, 3, 4);
     var i2 = SIMD.Int32x4(5, 6, 7, 8);
 
     for (var i = 0; i < 150; i++) {
         // Test bailouts
-        var value = i == 149 ? uglyDuckling : 3;
+        var value = i == 149 ? uglyDuckling : 0;
         var caught = false;
         try {
-            assertEqX4(SIMD.Int32x4.shuffle(i1, i2, value, 2, 4, 5), [4, 3, 5, 6]);
+            assertEqX4(SIMD.Int32x4.shuffle(i1, i2, value, 2, 4, 5), [1, 3, 5, 6]);
         } catch(e) {
             print(e);
             caught = true;
             assertEq(i, 149);
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof TypeError || e instanceof RangeError, true);
         }
-        assertEq(i < 149 || caught, true);
+        if (i == 149)
+            assertEq(caught, expectException);
     }
 }
 
 f();
-testBailouts(-1);
-testBailouts(8);
-testBailouts(2.5);
-testBailouts(undefined);
-testBailouts(null);
-testBailouts({});
-testBailouts('one');
-testBailouts(true);
+testBailouts(true, -1);
+testBailouts(true, 8);
+testBailouts(true, 2.5);
+testBailouts(true, undefined);
+testBailouts(true, {});
+testBailouts(true, 'one');
+testBailouts(false, false);
+testBailouts(false, null);
+testBailouts(false, " 0.0 ");
--- a/js/src/jit-test/tests/SIMD/swizzle.js
+++ b/js/src/jit-test/tests/SIMD/swizzle.js
@@ -37,57 +37,59 @@ function f() {
         var r = SIMD.Int32x4.swizzle(i4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4);
         assertEqX4(r, compI[i % 4]);
 
         // Constant lanes
         assertEqX4(SIMD.Int32x4.swizzle(i4, 3, 2, 1, 0), [4, 3, 2, 1]);
     }
 }
 
-function testBailouts(uglyDuckling) {
+function testBailouts(expectException, uglyDuckling) {
     var i4 = SIMD.Int32x4(1, 2, 3, 4);
     for (var i = 0; i < 150; i++) {
         // Test bailouts
         var value = i == 149 ? uglyDuckling : 0;
         var caught = false;
         try {
             assertEqX4(SIMD.Int32x4.swizzle(i4, value, 3, 2, 0), [1, 4, 3, 1]);
         } catch(e) {
             print(e);
             caught = true;
             assertEq(i, 149);
-            assertEq(e instanceof TypeError, true);
+            assertEq(e instanceof TypeError || e instanceof RangeError, true);
         }
-        assertEq(i < 149 || caught, true);
+        if (i == 149)
+            assertEq(caught, expectException);
     }
 }
 
 function testInt32x4SwizzleBailout() {
     // Test out-of-bounds non-constant indices. This is expected to throw.
     var i4 = SIMD.Int32x4(1, 2, 3, 4);
     for (var i = 0; i < 150; i++) {
         assertEqX4(SIMD.Int32x4.swizzle(i4, i, 3, 2, 0), [i + 1, 4, 3, 1]);
     }
 }
 
 f();
-testBailouts(-1);
-testBailouts(4);
-testBailouts(2.5);
-testBailouts(undefined);
-testBailouts(null);
-testBailouts({});
-testBailouts('one');
-testBailouts(true);
+testBailouts(true, -1);
+testBailouts(true, 4);
+testBailouts(true, 2.5);
+testBailouts(true, undefined);
+testBailouts(true, {});
+testBailouts(true, 'one');
+testBailouts(false, false);
+testBailouts(false, null);
+testBailouts(false, " 0.0 ");
 
 try {
     testInt32x4SwizzleBailout();
     throw 'not caught';
 } catch(e) {
-    assertEq(e instanceof TypeError, true);
+    assertEq(e instanceof RangeError, true);
 }
 
 (function() {
     var zappa = 0;
 
     function testBailouts() {
         var i4 = SIMD.Int32x4(1, 2, 3, 4);
         for (var i = 0; i < 300; i++) {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-unscopables.js
@@ -0,0 +1,37 @@
+// An Environment for a `with` statement does not observe bindings ruled out by @@unscopables.
+
+load(libdir + "asserts.js");
+
+let g = newGlobal();
+g.eval(`
+    let x = 'global';
+    function f() {
+        let obj = {
+            x: 'obj',
+            y: 'obj',
+            [Symbol.unscopables]: {x: 1},
+        };
+        with (obj)
+            debugger;
+    }
+`);
+let dbg = Debugger(g);
+let hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    let env = frame.environment;
+
+    assertEq(env.find("x") !== env, true);
+    assertEq(env.names().indexOf("x"), -1);
+    assertEq(env.getVariable("x"), undefined);
+    assertThrowsInstanceOf(() => env.setVariable("x", 7), TypeError);
+
+    assertEq(env.find("y") === env, true);
+    assertEq(env.getVariable("y"), "obj");
+    env.setVariable("y", 8);
+
+    assertEq(frame.eval("x").return, "global");
+    assertEq(frame.eval("y").return, 8);
+    hits++;
+};
+g.f();
+assertEq(hits, 1);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3202,16 +3202,17 @@ MustBeUInt32(MDefinition* def, MDefiniti
                rhs->maybeConstantValue()->isInt32(0);
     }
 
     if (MConstant* defConst = def->maybeConstantValue()) {
         *pwrapped = defConst;
         return defConst->type() == MIRType_Int32 && defConst->toInt32() >= 0;
     }
 
+    *pwrapped = nullptr;  // silence GCC warning
     return false;
 }
 
 /* static */ bool
 MBinaryInstruction::unsignedOperands(MDefinition* left, MDefinition* right)
 {
     MDefinition* replace;
     if (!MustBeUInt32(left, &replace))
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4710,27 +4710,35 @@ GetSymbolFor(JSContext* cx, HandleString
  *
  * This function is infallible. If it returns null, that means the symbol's
  * [[Description]] is undefined.
  */
 JS_PUBLIC_API(JSString*)
 GetSymbolDescription(HandleSymbol symbol);
 
 /* Well-known symbols. */
+#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(macro) \
+    macro(iterator) \
+    macro(match) \
+    macro(species) \
+    macro(toPrimitive) \
+    macro(unscopables)
+
 enum class SymbolCode : uint32_t {
-    iterator,                       // well-known symbols
-    match,
-    species,
-    toPrimitive,
+    // There is one SymbolCode for each well-known symbol.
+#define JS_DEFINE_SYMBOL_ENUM(name) name,
+    JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM)  // SymbolCode::iterator, etc.
+#undef JS_DEFINE_SYMBOL_ENUM
+    Limit,
     InSymbolRegistry = 0xfffffffe,  // created by Symbol.for() or JS::GetSymbolFor()
     UniqueSymbol = 0xffffffff       // created by Symbol() or JS::NewSymbol()
 };
 
 /* For use in loops that iterate over the well-known symbols. */
-const size_t WellKnownSymbolLimit = 4;
+const size_t WellKnownSymbolLimit = size_t(SymbolCode::Limit);
 
 /**
  * Return the SymbolCode telling what sort of symbol `symbol` is.
  *
  * A symbol's SymbolCode never changes once it is created.
  */
 JS_PUBLIC_API(SymbolCode)
 GetSymbolCode(Handle<Symbol*> symbol);
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -658,16 +658,21 @@ if CONFIG['_MSC_VER']:
     # instantiation request") is emitted for all Parser methods that
     # have a Parser<FullParseHandler> definition but no
     # Parser<SyntaxParseHandler> definition, see bug 1167030.
     CXXFLAGS += ['-wd4661']
     CXXFLAGS += ['-we4067', '-we4258', '-we4275']
     CXXFLAGS += ['-wd4146'] # FIXME: unary minus operator applied to unsigned type (bug 1229189)
     CXXFLAGS += ['-wd4273'] # FIXME: inconsistent dll linkage (bug 1229666)
 
+    # This is intended as a temporary hack to support building with VS2015.
+    # 'noexcept' used with no exception handling mode specified;
+    # termination on exception is not guaranteed. Specify /EHsc
+    CXXFLAGS += ['-wd4577']
+
 if CONFIG['OS_ARCH'] not in ('WINNT', 'HP-UX'):
     OS_LIBS += [
         'm',
     ]
 
 if CONFIG['OS_ARCH'] == 'FreeBSD':
     OS_LIBS += [
         '-pthread',
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -84,21 +84,16 @@ else
   AC_DEFINE(JS_STANDALONE)
   DIST="$MOZ_BUILD_ROOT/dist"
 fi
 AC_SUBST(JS_STANDALONE)
 BUILDING_JS=1
 AC_SUBST(BUILDING_JS)
 AC_SUBST(autoconfmk)
 
-MOZ_ARG_WITH_STRING(gonk,
-[  --with-gonk=DIR
-               location of gonk dir],
-    gonkdir=$withval)
-
 MOZ_ARG_WITH_STRING(gonk-toolchain-prefix,
 [  --with-gonk-toolchain-prefix=DIR
                           prefix to gonk toolchain commands],
     gonk_toolchain_prefix=$withval)
 
 if test -n "$gonkdir" ; then
     kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
     dnl Default to ICS
@@ -635,20 +630,16 @@ DLL_SUFFIX=.so
 OBJ_SUFFIX=o
 LIB_SUFFIX=a
 IMPORT_LIB_SUFFIX=
 DIRENT_INO=d_ino
 MOZ_USER_DIR=".mozilla"
 
 MOZ_FIX_LINK_PATHS="-Wl,-rpath-link,${DIST}/bin -Wl,-rpath-link,${prefix}/lib"
 
-USE_DEPENDENT_LIBS=1
-
-_PLATFORM_DEFAULT_TOOLKIT=cairo-gtk2
-
 dnl Configure platform-specific CPU architecture compiler options.
 dnl ==============================================================
 MOZ_ARCH_OPTS
 
 dnl =================================================================
 dnl Set up and test static assertion macros used to avoid AC_TRY_RUN,
 dnl which is bad when cross compiling.
 dnl =================================================================
@@ -896,17 +887,17 @@ case "$host" in
     if test -n "$_WIN32_MSVC"; then
         HOST_AR=lib
         HOST_AR_FLAGS='-NOLOGO -OUT:$@'
         HOST_CFLAGS="$HOST_CFLAGS -TC -nologo"
         HOST_RANLIB='echo ranlib'
     else
         HOST_CFLAGS="$HOST_CFLAGS -mwindows"
     fi
-    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -DNO_X11 -D_CRT_SECURE_NO_WARNINGS"
+    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
     HOST_BIN_SUFFIX=.exe
 
     case "${host_cpu}" in
     i*86)
         if test -n "$_WIN32_MSVC"; then
             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X86"
         fi
@@ -916,17 +907,17 @@ case "$host" in
             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X64"
         fi
         HOST_CFLAGS="$HOST_CFLAGS -D_AMD64_"
         ;;
     esac
     ;;
 
 *-darwin*)
-    HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX -DXP_MACOSX -DNO_X11"
+    HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX -DXP_MACOSX"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     ;;
 
 *-linux*|*-kfreebsd*-gnu|*-gnu*)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     ;;
 
@@ -948,17 +939,16 @@ case "$target" in
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MOZ_OPTIMIZE_FLAGS="-O3 -fno-stack-protector"
     CFLAGS="$CFLAGS -fno-common"
     CXXFLAGS="$CXXFLAGS -fno-common"
     DLL_SUFFIX=".dylib"
     DSO_LDOPTS=''
     STRIP="$STRIP -x -S"
-    _PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
     LDFLAGS="$LDFLAGS -lobjc"
     # The ExceptionHandling framework is needed for Objective-C exception
     # logging code in nsObjCExceptions.h. Currently we only use that in debug
     # builds.
     _SAVE_LDFLAGS=$LDFLAGS
      AC_MSG_CHECKING([for -framework ExceptionHandling])
     LDFLAGS="$LDFLAGS -framework ExceptionHandling"
     AC_TRY_LINK(,[return 0;],
@@ -991,19 +981,16 @@ case "$target" in
 
         LDFLAGS=$_SAVE_LDFLAGS
     fi
     MOZ_FIX_LINK_PATHS="-Wl,-executable_path,${DIST}/bin"
     ;;
 
 *-android*|*-linuxandroid*)
     AC_DEFINE(NO_PW_GECOS)
-    no_x=yes
-    _PLATFORM_DEFAULT_TOOLKIT=cairo-android
-
     MOZ_GFX_OPTIMIZE_MOBILE=1
     MOZ_OPTIMIZE_FLAGS="-O3 -fno-reorder-functions"
     if test -z "$CLANG_CC"; then
        MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS"
     fi
     # The Maemo builders don't know about this flag
     MOZ_ARM_VFP_FLAGS="-mfpu=vfp"
     ;;
@@ -1217,24 +1204,19 @@ case "$target" in
     AC_DEFINE(HAVE__MSIZE)
     AC_DEFINE(_WINDOWS)
     AC_DEFINE(WIN32)
     AC_DEFINE(XP_WIN)
     AC_DEFINE(XP_WIN32)
     AC_DEFINE(HW_THREADS)
     AC_DEFINE(STDC_HEADERS)
     AC_DEFINE(WIN32_LEAN_AND_MEAN)
-    _PLATFORM_DEFAULT_TOOLKIT='cairo-windows'
     BIN_SUFFIX='.exe'
     MOZ_USER_DIR="Mozilla"
 
-    dnl set NO_X11 defines here as the general check is skipped on win32
-    no_x=yes
-    AC_DEFINE(NO_X11)
-
     case "$host_os" in
     cygwin*|msvc*|mks*)
         AC_MSG_ERROR([Using a Cygwin build environment is unsupported. Configure cannot check for presence of necessary headers. Please upgrade to MozillaBuild; see https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
         ;;
     esac
 
     case "$target" in
     i*86-*)
@@ -2816,18 +2798,16 @@ AC_SUBST(ENABLE_TESTS)
 
 AC_SUBST(ENABLE_STRIP)
 AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(INCREMENTAL_LINKER)
 AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
 
 AC_SUBST(MOZ_FIX_LINK_PATHS)
 
-AC_SUBST(USE_DEPENDENT_LIBS)
-
 AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
 
 AC_SUBST(MOZ_APP_NAME)
 AC_SUBST(MOZ_APP_DISPLAYNAME)
 AC_SUBST(MOZ_APP_VERSION)
 
 AC_SUBST(MOZ_PKG_SPECIAL)
 
@@ -2932,27 +2912,16 @@ elif test "$OS_ARCH" != "WINNT"; then
   AC_DEFINE(XP_UNIX)
 fi
 
 if test "$MOZ_DEBUG"; then
     AC_DEFINE(MOZ_REFLOW_PERF)
     AC_DEFINE(MOZ_REFLOW_PERF_DSP)
 fi
 
-if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK" ; then
-    AC_DEFINE(MOZ_ACCESSIBILITY_ATK)
-    ATK_FULL_VERSION=`$PKG_CONFIG --modversion atk`
-    ATK_MAJOR_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $1 }'`
-    ATK_MINOR_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $2 }'`
-    ATK_REV_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $3 }'`
-    AC_DEFINE_UNQUOTED(ATK_MAJOR_VERSION, $ATK_MAJOR_VERSION)
-    AC_DEFINE_UNQUOTED(ATK_MINOR_VERSION, $ATK_MINOR_VERSION)
-    AC_DEFINE_UNQUOTED(ATK_REV_VERSION, $ATK_REV_VERSION)
-fi
-
 dnl ========================================================
 dnl Determine options to use for running the preprocessor.
 dnl ========================================================
 
 if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT"; then
     PREPROCESS_OPTION="-P -Fi"
 else
     PREPROCESS_OPTION="-E -o "
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-basics.js
@@ -0,0 +1,22 @@
+// Basics of @@unscopables support.
+
+// In with(obj), if obj[@@unscopables][id] is truthy, then the identifier id
+// is not present as a binding in the with-block's scope.
+var x = "global";
+with ({x: "with", [Symbol.unscopables]: {x: true}})
+    assertEq(x, "global");
+
+// But if obj[@@unscopables][id] is false or not present, there is a binding.
+with ({y: "with", z: "with", [Symbol.unscopables]: {y: false}}) {
+    assertEq(y, "with");
+    assertEq(z, "with");
+}
+
+// ToBoolean(obj[@@unscopables][id]) determines whether there's a binding.
+let someValues = [0, -0, NaN, "", undefined, null, "x", {}, []];
+for (let v of someValues) {
+    with ({x: "with", [Symbol.unscopables]: {x: v}})
+        assertEq(x, v ? "global" : "with");
+}
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-closures.js
@@ -0,0 +1,23 @@
+// @@unscopables continues to work after exiting the relevant `with` block,
+// if the environment is captured by a closure.
+
+let env = {
+    x: 9000,
+    [Symbol.unscopables]: {x: true}
+};
+
+function make_adder(x) {
+    with (env)
+        return function (y) { return x + y; };
+}
+assertEq(make_adder(3)(10), 13);
+
+// Same test, but with a bunch of different parts for bad luck
+let x = 500;
+function make_adder_with_eval() {
+    with (env)
+        return eval('y => eval("x + y")');
+}
+assertEq(make_adder_with_eval()(10), 510);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-const.js
@@ -0,0 +1,8 @@
+// @@unscopables prevents a property from having any effect on assigning to a
+// const binding (which is an error).
+
+const x = 1;
+with ({x: 1, [Symbol.unscopables]: {x: true}})
+    assertThrowsInstanceOf(() => {x = 2;}, TypeError);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-delete.js
@@ -0,0 +1,27 @@
+// If obj[@@unscopables][id], then `delete id` works across `with (obj)` scope.
+
+this.niche = 7;
+let obj = { niche: 8, [Symbol.unscopables]: { niche: true } };
+with (obj) {
+    delete niche;
+}
+
+assertEq(obj.niche, 8);
+assertEq("niche" in this, false);
+
+// Same thing, but delete a variable introduced by sloppy direct eval.
+this.niche = 9;
+function f() {
+    eval("var niche = 10;");
+    with (obj) {
+        assertEq(niche, 10);
+        delete niche;
+    }
+    assertEq(niche, 9);
+}
+
+// Of course none of this affects a qualified delete.
+assertEq(delete this.niche, true);
+assertEq("niche" in this, false);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-getters.js
@@ -0,0 +1,41 @@
+// @@unscopables checks can call getters.
+
+// The @@unscopables property itself can be a getter.
+let hit1 = 0;
+let x = "global x";
+let env1 = {
+    x: "env1.x",
+    get [Symbol.unscopables]() {
+        hit1++;
+        return {x: true};
+    }
+};
+with (env1)
+    assertEq(x, "global x");
+assertEq(hit1, 1);
+
+// It can throw; the exception is propagated out.
+function Fit() {}
+with ({x: 0, get [Symbol.unscopables]() { throw new Fit; }})
+    assertThrowsInstanceOf(() => x, Fit);
+
+// Individual properties on the @@unscopables object can have getters.
+let hit2 = 0;
+let env2 = {
+    x: "env2.x",
+    [Symbol.unscopables]: {
+        get x() {
+            hit2++;
+            return true;
+        }
+    }
+};
+with (env2)
+    assertEq(x, "global x");
+assertEq(hit2, 1);
+
+// And they can throw.
+with ({x: 0, [Symbol.unscopables]: {get x() { throw new Fit; }}})
+    assertThrowsInstanceOf(() => x, Fit);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-global.js
@@ -0,0 +1,18 @@
+// @@unscopables does not affect the global environment.
+
+this.x = "global property x";
+let y = "global lexical y";
+this[Symbol.unscopables] = {x: true, y: true};
+assertEq(x, "global property x");
+assertEq(y, "global lexical y");
+assertEq(eval("x"), "global property x");
+assertEq(eval("y"), "global lexical y");
+
+// But it does affect `with` statements targeting the global object.
+{
+    let x = "local x";
+    with (this)
+        assertEq(x, "local x");
+}
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-ignored.js
@@ -0,0 +1,22 @@
+// In these cases, @@unscopables should not be consulted.
+
+// Because obj has no properties `assertEq` or `x`,
+// obj[@@unscopables] is not checked here:
+var obj = {
+    get [Symbol.unscopables]() {
+        throw "tried to read @@unscopables";
+    }
+};
+var x = 3;
+with (obj)
+    assertEq(x, 3);
+
+// If @@unscopables is present but not an object, it is ignored:
+for (let nonObject of [undefined, null, "nothing", Symbol.for("moon")]) {
+    let y = 4;
+    let obj2 = {[Symbol.unscopables]: nonObject, y: 5};
+    with (obj2)
+        assertEq(y, 5);
+}
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-miss.js
@@ -0,0 +1,7 @@
+// Trying to access a binding that doesn't exist due to @@unscopables
+// is a ReferenceError.
+
+with ({x: 1, [Symbol.unscopables]: {x: true}})
+    assertThrowsInstanceOf(() => x, ReferenceError);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-mutation-frozen.js
@@ -0,0 +1,18 @@
+// When env[@@unscopables].x changes, bindings can appear even if env is inextensible.
+
+let x = "global";
+let unscopables = {x: true};
+let env = Object.create(null);
+env[Symbol.unscopables] = unscopables;
+env.x = "object";
+Object.freeze(env);
+
+for (let i = 0; i < 1004; i++) {
+    if (i === 1000)
+        unscopables.x = false;
+    with (env) {
+        assertEq(x, i < 1000 ? "global" : "object");
+    }
+}
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-mutation.js
@@ -0,0 +1,44 @@
+// When obj[@@unscopables].x changes, bindings appear and disappear accordingly.
+
+let x = "global";
+function getX() { return x; }
+
+let unscopables = {x: true};
+let obj = {x: "obj", [Symbol.unscopables]: unscopables};
+
+with (obj) {
+    assertEq(x, "global");
+    x = "global-1";
+    assertEq(x, "global-1");
+    assertEq(obj.x, "obj");
+
+    unscopables.x = false;  // suddenly x appears in the with-environment
+
+    assertEq(x, "obj");
+    x = "obj-1";
+    assertEq(getX(), "global-1");  // unchanged
+    assertEq(obj.x, "obj-1");
+
+    unscopables.x = true;  // *poof*
+
+    assertEq(x, "global-1");
+    x = "global-2";
+    assertEq(getX(), "global-2");
+    assertEq(obj.x, "obj-1");  // unchanged
+
+    // The determination of which binding is assigned happens when the LHS of
+    // assignment is evaluated, before the RHS. This is observable if we make
+    // the binding appear or disappear during evaluation of the RHS, before
+    // assigning.
+    x = (unscopables.x = false, "global-3");
+    assertEq(getX(), "global-3");
+    assertEq(obj.x, "obj-1");
+
+    x = (unscopables.x = true, "obj-2");
+    assertEq(getX(), "global-3");
+    assertEq(obj.x, "obj-2");
+}
+
+assertEq(x, "global-3");
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-proto.js
@@ -0,0 +1,39 @@
+// @@unscopables treats properties found on prototype chains the same as other
+// properties.
+
+const x = "global x";
+const y = "global y";
+
+// obj[@@unscopables].x works when obj.x is inherited via the prototype chain.
+let proto = {x: "object x", y: "object y"};
+let env = Object.create(proto);
+env[Symbol.unscopables] = {x: true, y: false};
+with (env) {
+    assertEq(x, "global x");
+    assertEq(delete x, false);
+    assertEq(y, "object y");
+}
+assertEq(env.x, "object x");
+
+// @@unscopables works if is inherited via the prototype chain.
+env = {
+    x: "object",
+    [Symbol.unscopables]: {x: true, y: true}
+};
+for (let i = 0; i < 50; i++)
+    env = Object.create(env);
+env.y = 1;
+with (env) {
+    assertEq(x, "global x");
+    assertEq(y, "global y");
+}
+
+// @@unscopables works if the obj[@@unscopables][id] property is inherited.
+env = {
+    x: "object",
+    [Symbol.unscopables]: Object.create({x: true})
+};
+with (env)
+    assertEq(x, "global x");
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-proxy.js
@@ -0,0 +1,46 @@
+// Object operations are performed in the right order, as observed by proxies.
+
+let log = [];
+function LoggingProxyHandlerWrapper(name, handler={}) {
+    return new Proxy(handler, {
+        get(t, id) {
+            let method = handler[id];
+            return function (...args) {
+                log.push([name + "." + id, ...args.filter(v => typeof v !== "object")]);
+                if (method === undefined)
+                    return Reflect[id].apply(null, args);
+                return method.apply(this, args);
+            };
+        }
+    });
+}
+
+function LoggingProxy(name, target) {
+    return new Proxy(target, new LoggingProxyHandlerWrapper(name));
+}
+
+let proto = {x: 44};
+let proto_proxy = new LoggingProxy("proto", proto);
+let unscopables = {x: true};
+let unscopables_proxy = new LoggingProxy("unscopables", {x: true});
+let env = Object.create(proto_proxy, {
+    [Symbol.unscopables]: { value: unscopables_proxy }
+});
+let env_proxy = new LoggingProxy("env", env);
+
+let x = 11;
+function f() {
+    with (env_proxy)
+        return x;
+}
+
+assertEq(f(), 11);
+
+assertDeepEq(log, [
+    ["env.has", "x"],
+    ["proto.has", "x"],
+    ["env.get", Symbol.unscopables],
+    ["unscopables.get", "x"]
+]);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-strict.js
@@ -0,0 +1,32 @@
+// Strict assignment to the name of a property that's masked by @@unscopables
+// throws a ReferenceError.
+
+let env = {k: 1};
+let f;
+with (env) {
+    f = function () {
+        "use strict";
+        k = 2;
+    };
+}
+
+f();
+assertEq(env.k, 2);
+
+env[Symbol.unscopables] = {k: true};
+assertThrowsInstanceOf(f, ReferenceError);
+
+// @@unscopables is tested when the LHS of assignment is evaluated, so there is
+// no effect on the assignment if it is changed while evaluating the RHS.
+let g;
+with (env) {
+    g = function () {
+        "use strict";
+        k = (env[Symbol.unscopables].k = true, 3);
+    }
+}
+env[Symbol.unscopables].k = false;
+g();
+assertEq(env.k, 3);
+
+reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/unscopables-tdz.js
@@ -0,0 +1,9 @@
+// Accessing an uninitialized variable due to @@unscopables is still a ReferenceError.
+
+with ({x: 1, [Symbol.unscopables]: {x: true}})
+    assertThrowsInstanceOf(() => x, ReferenceError);
+
+let x;
+
+reportCompare(0, 0);
+
--- a/js/src/tests/ecma_6/Symbol/well-known.js
+++ b/js/src/tests/ecma_6/Symbol/well-known.js
@@ -1,15 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/ */
 
 var names = [
     "iterator",
     "match",
     "species",
+    "toPrimitive",
+    "unscopables"
 ];
 
 for (var name of names) {
     // Well-known symbols exist.
     assertEq(typeof Symbol[name], "symbol");
 
     // They are never in the registry.
     assertEq(Symbol[name] !== Symbol.for("Symbol." + name), true);
--- a/js/src/tests/ecma_7/SIMD/replaceLane.js
+++ b/js/src/tests/ecma_7/SIMD/replaceLane.js
@@ -83,144 +83,144 @@ function test() {
       [Float32x4(NaN, -0, Infinity, -Infinity), 0]
   ];
   testType('Float32x4', Float32x4inputs);
 
   var v = Float32x4inputs[1][0];
   assertEqX4(Float32x4.replaceLane(v, 0), replaceLane0(simdToArray(v), NaN));
   assertEqX4(Float32x4.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Float32x4.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Float32x4.replaceLane(v, 4, good), TypeError);
-  assertThrowsInstanceOf(() => Float32x4.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Float32x4.replaceLane(v, 4, good), RangeError);
+  assertThrowsInstanceOf(() => Float32x4.replaceLane(v, 1.1, good), RangeError);
 
   var Float64x2inputs = [
       [Float64x2(1, 2), 5],
       [Float64x2(1.87, 2.08), Math.fround(13.37)],
       [Float64x2(NaN, -0), 0]
   ];
   testType('Float64x2', Float64x2inputs);
 
   var v = Float64x2inputs[1][0];
   assertEqX2(Float64x2.replaceLane(v, 0), replaceLane0(simdToArray(v), NaN));
   assertEqX2(Float64x2.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Float64x2.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Float64x2.replaceLane(v, 2, good), TypeError);
-  assertThrowsInstanceOf(() => Float64x2.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Float64x2.replaceLane(v, 2, good), RangeError);
+  assertThrowsInstanceOf(() => Float64x2.replaceLane(v, 1.1, good), RangeError);
 
   var Int8x16inputs = [[Int8x16(0, 1, 2, 3, 4, 5, 6, 7, -1, -2, -3, -4, -5, -6, INT8_MIN, INT8_MAX), 17]];
   testType('Int8x16', Int8x16inputs);
 
   var v = Int8x16inputs[0][0];
   assertEqX16(Int8x16.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
   assertEqX16(Int8x16.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Int8x16.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Int8x16.replaceLane(v, 16, good), TypeError);
-  assertThrowsInstanceOf(() => Int8x16.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Int8x16.replaceLane(v, 16, good), RangeError);
+  assertThrowsInstanceOf(() => Int8x16.replaceLane(v, 1.1, good), RangeError);
 
   var Int16x8inputs = [[Int16x8(0, 1, 2, 3, -1, -2, INT16_MIN, INT16_MAX), 9]];
   testType('Int16x8', Int16x8inputs);
 
   var v = Int16x8inputs[0][0];
   assertEqX8(Int16x8.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
   assertEqX8(Int16x8.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Int16x8.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Int16x8.replaceLane(v, 8, good), TypeError);
-  assertThrowsInstanceOf(() => Int16x8.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Int16x8.replaceLane(v, 8, good), RangeError);
+  assertThrowsInstanceOf(() => Int16x8.replaceLane(v, 1.1, good), RangeError);
 
   var Int32x4inputs = [
       [Int32x4(1, 2, 3, 4), 5],
       [Int32x4(INT32_MIN, INT32_MAX, 3, 4), INT32_MIN],
   ];
   testType('Int32x4', Int32x4inputs);
 
   var v = Int32x4inputs[1][0];
   assertEqX4(Int32x4.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
   assertEqX4(Int32x4.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Int32x4.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Int32x4.replaceLane(v, 4, good), TypeError);
-  assertThrowsInstanceOf(() => Int32x4.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Int32x4.replaceLane(v, 4, good), RangeError);
+  assertThrowsInstanceOf(() => Int32x4.replaceLane(v, 1.1, good), RangeError);
 
   var Uint8x16inputs = [[Uint8x16(0, 1, 2, 3, 4, 5, 6, 7, -1, -2, -3, -4, -5, -6, INT8_MIN, UINT8_MAX), 17]];
   testType('Uint8x16', Uint8x16inputs);
 
   var v = Uint8x16inputs[0][0];
   assertEqX16(Uint8x16.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
   assertEqX16(Uint8x16.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Uint8x16.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Uint8x16.replaceLane(v, 16, good), TypeError);
-  assertThrowsInstanceOf(() => Uint8x16.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Uint8x16.replaceLane(v, 16, good), RangeError);
+  assertThrowsInstanceOf(() => Uint8x16.replaceLane(v, 1.1, good), RangeError);
 
   var Uint16x8inputs = [[Uint16x8(0, 1, 2, 3, -1, -2, INT16_MIN, UINT16_MAX), 9]];
   testType('Uint16x8', Uint16x8inputs);
 
   var v = Uint16x8inputs[0][0];
   assertEqX8(Uint16x8.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
   assertEqX8(Uint16x8.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Uint16x8.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Uint16x8.replaceLane(v, 8, good), TypeError);
-  assertThrowsInstanceOf(() => Uint16x8.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Uint16x8.replaceLane(v, 8, good), RangeError);
+  assertThrowsInstanceOf(() => Uint16x8.replaceLane(v, 1.1, good), RangeError);
 
   var Uint32x4inputs = [
       [Uint32x4(1, 2, 3, 4), 5],
       [Uint32x4(INT32_MIN, UINT32_MAX, INT32_MAX, 4), UINT32_MAX],
   ];
   testType('Uint32x4', Uint32x4inputs);
 
   var v = Uint32x4inputs[1][0];
   assertEqX4(Uint32x4.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
   assertEqX4(Uint32x4.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
   assertThrowsInstanceOf(() => Uint32x4.replaceLane(v, 0, bad), TestError);
-  assertThrowsInstanceOf(() => Uint32x4.replaceLane(v, 4, good), TypeError);
-  assertThrowsInstanceOf(() => Uint32x4.replaceLane(v, 1.1, good), TypeError);
+  assertThrowsInstanceOf(() => Uint32x4.replaceLane(v, 4, good), RangeError);
+  assertThrowsInstanceOf(() => Uint32x4.replaceLane(v, 1.1, good), RangeError);
 
   var Bool64x2inputs = [
       [Bool64x2(true, true), false],
   ];
   testType('Bool64x2', Bool64x2inputs);
 
   var v = Bool64x2inputs[0][0];
   assertEqX2(Bool64x2.replaceLane(v, 0),       replaceLane0(simdToArray(v), false));
   assertEqX2(Bool64x2.replaceLane(v, 0, true), replaceLane0(simdToArray(v), true));
   assertEqX2(Bool64x2.replaceLane(v, 0, bad),  replaceLane0(simdToArray(v), true));
-  assertThrowsInstanceOf(() => Bool64x2.replaceLane(v, 4, true), TypeError);
-  assertThrowsInstanceOf(() => Bool64x2.replaceLane(v, 1.1, false), TypeError);
+  assertThrowsInstanceOf(() => Bool64x2.replaceLane(v, 4, true), RangeError);
+  assertThrowsInstanceOf(() => Bool64x2.replaceLane(v, 1.1, false), RangeError);
 
   var Bool32x4inputs = [
       [Bool32x4(true, true, true, true), false],
   ];
   testType('Bool32x4', Bool32x4inputs);
 
   var v = Bool32x4inputs[0][0];
   assertEqX4(Bool32x4.replaceLane(v, 0),       replaceLane0(simdToArray(v), false));
   assertEqX4(Bool32x4.replaceLane(v, 0, true), replaceLane0(simdToArray(v), true));
   assertEqX4(Bool32x4.replaceLane(v, 0, bad),  replaceLane0(simdToArray(v), true));
-  assertThrowsInstanceOf(() => Bool32x4.replaceLane(v, 4, true), TypeError);
-  assertThrowsInstanceOf(() => Bool32x4.replaceLane(v, 1.1, false), TypeError);
+  assertThrowsInstanceOf(() => Bool32x4.replaceLane(v, 4, true), RangeError);
+  assertThrowsInstanceOf(() => Bool32x4.replaceLane(v, 1.1, false), RangeError);
 
   var Bool16x8inputs = [
       [Bool16x8(true, true, true, true, true, true, true, true), false],
   ];
 
   testType('Bool16x8', Bool16x8inputs);
   var v = Bool16x8inputs[0][0];
   assertEqX8(Bool16x8.replaceLane(v, 0),       replaceLane0(simdToArray(v), false));
   assertEqX8(Bool16x8.replaceLane(v, 0, true), replaceLane0(simdToArray(v), true));
   assertEqX8(Bool16x8.replaceLane(v, 0, bad),  replaceLane0(simdToArray(v), true));
-  assertThrowsInstanceOf(() => Bool16x8.replaceLane(v, 16, true), TypeError);
-  assertThrowsInstanceOf(() => Bool16x8.replaceLane(v, 1.1, false), TypeError);
+  assertThrowsInstanceOf(() => Bool16x8.replaceLane(v, 16, true), RangeError);
+  assertThrowsInstanceOf(() => Bool16x8.replaceLane(v, 1.1, false), RangeError);
 
   var Bool8x16inputs = [
       [Bool8x16(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true), false],
   ];
 
   testType('Bool8x16', Bool8x16inputs);
   var v = Bool8x16inputs[0][0];
   assertEqX16(Bool8x16.replaceLane(v, 0),       replaceLane0(simdToArray(v), false));
   assertEqX16(Bool8x16.replaceLane(v, 0, true), replaceLane0(simdToArray(v), true));
   assertEqX16(Bool8x16.replaceLane(v, 0, bad),  replaceLane0(simdToArray(v), true));
-  assertThrowsInstanceOf(() => Bool8x16.replaceLane(v, 16, true), TypeError);
-  assertThrowsInstanceOf(() => Bool8x16.replaceLane(v, 1.1, false), TypeError);
+  assertThrowsInstanceOf(() => Bool8x16.replaceLane(v, 16, true), RangeError);
+  assertThrowsInstanceOf(() => Bool8x16.replaceLane(v, 1.1, false), RangeError);
 
   if (typeof reportCompare === "function")
     reportCompare(true, true);
 }
 
 test();
--- a/js/src/tests/ecma_7/SIMD/swizzle-shuffle.js
+++ b/js/src/tests/ecma_7/SIMD/swizzle-shuffle.js
@@ -100,67 +100,79 @@ function testSwizzleForType(type) {
                     [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
                     [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
                     [5, 14, 3, 2, 6, 9, 1, 10, 7, 11, 4, 0, 13, 15, 8, 12]];
         for (var t of vals) {
           assertEqVec(type.swizzle(v, ...t), swizzle16(simdToArray(v), ...t));
         }
     }
 
-    // Test that we throw if an lane argument isn't an int32 or isn't in bounds.
+    // Test that we throw if an lane argument doesn't coerce to an integer in bounds.
     if (lanes == 2) {
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, undefined), RangeError);
+
+        type.swizzle(v, 0, "00.0");
+        type.swizzle(v, 0, null);
+        type.swizzle(v, 0, false);
+        type.swizzle(v, 0, true);
 
         // In bounds is [0, 1]
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 2), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 2), RangeError);
     } else if (lanes == 4) {
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, undefined), RangeError);
+
+        type.swizzle(v, 0, 0, 0, "00.0");
+        type.swizzle(v, 0, 0, 0, null);
+        type.swizzle(v, 0, 0, 0, false);
+        type.swizzle(v, 0, 0, 0, true);
 
         // In bounds is [0, 3]
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 4), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 4), RangeError);
     } else if (lanes == 8) {
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, undefined), RangeError);
+
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, "00.0");
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, null);
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, false);
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, true);
 
         // In bounds is [0, 7]
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 8), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 8), RangeError);
     } else {
         assertEq(lanes, 16);
 
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, undefined), RangeError);
+
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "00.0");
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null);
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false);
+        type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true);
 
         // In bounds is [0, 15]
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), RangeError);
     }
 }
 
 function testSwizzleInt8x16() {
     var v = Int16x8(1, 2, 3, 4, 5, 6, 7, 8);
 
     assertThrowsInstanceOf(function() {
         Int8x16.swizzle(v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -345,65 +357,57 @@ function testShuffleForType(type) {
             [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15] = t;
             assertEqVec(type.shuffle(lhs, rhs, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15),
                         shuffle16(simdToArray(lhs), simdToArray(rhs), s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15));
         }
     }
 
     // Test that we throw if an lane argument isn't an int32 or isn't in bounds.
     if (lanes == 2) {
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, undefined), RangeError);
 
         // In bounds is [0, 3]
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 4), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 4), RangeError);
     } else if (lanes == 4) {
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, undefined), RangeError);
 
         // In bounds is [0, 7]
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 8), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 8), RangeError);
     } else if (lanes == 8) {
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, undefined), RangeError);
 
         // In bounds is [0, 15]
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 16), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 16), RangeError);
     } else {
         assertEq(lanes, 16);
 
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "one"), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, undefined), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {valueOf: function(){return 42}}), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "one"), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, undefined), RangeError);
 
         // In bounds is [0, 31]
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1), TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1), RangeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), RangeError);
     }
 }
 
 function testShuffleInt8x16() {
     var v = Int16x8(1, 2, 3, 4, 5, 6, 7, 8);
 
     assertThrowsInstanceOf(function() {
         Int8x16.shuffle(v, v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
--- a/js/src/tests/ecma_7/SIMD/typedobjects.js
+++ b/js/src/tests/ecma_7/SIMD/typedobjects.js
@@ -27,20 +27,20 @@ function testFloat32x4Alignment() {
 
 function testFloat32x4Getters() {
   var f = Float32x4(11, 22, 33, 44);
   assertEq(Float32x4.extractLane(f, 0), 11);
   assertEq(Float32x4.extractLane(f, 1), 22);
   assertEq(Float32x4.extractLane(f, 2), 33);
   assertEq(Float32x4.extractLane(f, 3), 44);
 
-  assertThrowsInstanceOf(() => Float32x4.extractLane(f, 4), TypeError);
-  assertThrowsInstanceOf(() => Float32x4.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Float32x4.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Float32x4.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Float32x4.extractLane(f, 4), RangeError);
+  assertThrowsInstanceOf(() => Float32x4.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Float32x4.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Float32x4.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Float32x4.extractLane(Int32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Float32x4.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Float32x4.extractLane(f, f), TypeError);
 }
 
 function testFloat32x4Handles() {
   var Array = Float32x4.array(3);
   var array = new Array([Float32x4(1, 2, 3, 4),
@@ -113,20 +113,20 @@ function testFloat64x2Alignment() {
 }
 
 function testFloat64x2Getters() {
   // Create a Float64x2 and check that the getters work:
   var f = Float64x2(11, 22);
   assertEq(Float64x2.extractLane(f, 0), 11);
   assertEq(Float64x2.extractLane(f, 1), 22);
 
-  assertThrowsInstanceOf(() => Float64x2.extractLane(f, 2), TypeError);
-  assertThrowsInstanceOf(() => Float64x2.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Float64x2.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Float64x2.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Float64x2.extractLane(f, 2), RangeError);
+  assertThrowsInstanceOf(() => Float64x2.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Float64x2.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Float64x2.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Float64x2.extractLane(Float32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Float64x2.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Float64x2.extractLane(f, f), TypeError);
 }
 
 function testFloat64x2Handles() {
   var Array = Float64x2.array(3);
   var array = new Array([Float64x2(1, 2),
@@ -213,20 +213,20 @@ function testInt8x16Getters() {
   assertEq(Int8x16.extractLane(f, 9), 10);
   assertEq(Int8x16.extractLane(f, 10), 20);
   assertEq(Int8x16.extractLane(f, 11), 30);
   assertEq(Int8x16.extractLane(f, 12), 40);
   assertEq(Int8x16.extractLane(f, 13), 50);
   assertEq(Int8x16.extractLane(f, 14), 60);
   assertEq(Int8x16.extractLane(f, 15), 70);
 
-  assertThrowsInstanceOf(() => Int8x16.extractLane(f, 16), TypeError);
-  assertThrowsInstanceOf(() => Int8x16.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Int8x16.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Int8x16.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Int8x16.extractLane(f, 16), RangeError);
+  assertThrowsInstanceOf(() => Int8x16.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Int8x16.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Int8x16.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Int8x16.extractLane(Int32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Int8x16.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Int8x16.extractLane(f, f), TypeError);
 }
 
 function testInt8x16Handles() {
   var Array = Int8x16.array(3);
   var array = new Array([Int8x16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
@@ -309,20 +309,20 @@ function testInt16x8Getters() {
   assertEq(Int16x8.extractLane(f, 1), 22);
   assertEq(Int16x8.extractLane(f, 2), 33);
   assertEq(Int16x8.extractLane(f, 3), 44);
   assertEq(Int16x8.extractLane(f, 4), 55);
   assertEq(Int16x8.extractLane(f, 5), 66);
   assertEq(Int16x8.extractLane(f, 6), 77);
   assertEq(Int16x8.extractLane(f, 7), 88);
 
-  assertThrowsInstanceOf(() => Int16x8.extractLane(f, 8), TypeError);
-  assertThrowsInstanceOf(() => Int16x8.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Int16x8.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Int16x8.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Int16x8.extractLane(f, 8), RangeError);
+  assertThrowsInstanceOf(() => Int16x8.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Int16x8.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Int16x8.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Int16x8.extractLane(Int32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Int16x8.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Int16x8.extractLane(f, f), TypeError);
 }
 
 function testInt16x8Handles() {
   var Array = Int16x8.array(3);
   var array = new Array([Int16x8(1, 2, 3, 4, 5, 6, 7, 8),
@@ -397,20 +397,20 @@ function testInt32x4Alignment() {
 function testInt32x4Getters() {
   // Create a Int32x4 and check that the getters work:
   var f = Int32x4(11, 22, 33, 44);
   assertEq(Int32x4.extractLane(f, 0), 11);
   assertEq(Int32x4.extractLane(f, 1), 22);
   assertEq(Int32x4.extractLane(f, 2), 33);
   assertEq(Int32x4.extractLane(f, 3), 44);
 
-  assertThrowsInstanceOf(() => Int32x4.extractLane(f, 4), TypeError);
-  assertThrowsInstanceOf(() => Int32x4.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Int32x4.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Int32x4.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Int32x4.extractLane(f, 4), RangeError);
+  assertThrowsInstanceOf(() => Int32x4.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Int32x4.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Int32x4.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Int32x4.extractLane(Float32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Int32x4.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Int32x4.extractLane(f, f), TypeError);
 }
 
 function testInt32x4Handles() {
   var Array = Int32x4.array(3);
   var array = new Array([Int32x4(1, 2, 3, 4),
@@ -496,20 +496,20 @@ function testUint8x16Getters() {
   assertEq(Uint8x16.extractLane(f, 9), 10);
   assertEq(Uint8x16.extractLane(f, 10), 20);
   assertEq(Uint8x16.extractLane(f, 11), 30);
   assertEq(Uint8x16.extractLane(f, 12), 40);
   assertEq(Uint8x16.extractLane(f, 13), 50);
   assertEq(Uint8x16.extractLane(f, 14), 60);
   assertEq(Uint8x16.extractLane(f, 15), 70);
 
-  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, 16), TypeError);
-  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, 16), RangeError);
+  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Uint8x16.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Uint8x16.extractLane(Uint32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Uint8x16.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Uint8x16.extractLane(f, f), TypeError);
 }
 
 function testUint8x16Handles() {
   var Array = Uint8x16.array(3);
   var array = new Array([Uint8x16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
@@ -592,20 +592,20 @@ function testUint16x8Getters() {
   assertEq(Uint16x8.extractLane(f, 1), 22);
   assertEq(Uint16x8.extractLane(f, 2), 33);
   assertEq(Uint16x8.extractLane(f, 3), 44);
   assertEq(Uint16x8.extractLane(f, 4), 55);
   assertEq(Uint16x8.extractLane(f, 5), 66);
   assertEq(Uint16x8.extractLane(f, 6), 77);
   assertEq(Uint16x8.extractLane(f, 7), 88);
 
-  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, 8), TypeError);
-  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, 8), RangeError);
+  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Uint16x8.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Uint16x8.extractLane(Uint32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Uint16x8.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Uint16x8.extractLane(f, f), TypeError);
 }
 
 function testUint16x8Handles() {
   var Array = Uint16x8.array(3);
   var array = new Array([Uint16x8(1, 2, 3, 4, 5, 6, 7, 8),
@@ -680,20 +680,20 @@ function testUint32x4Alignment() {
 function testUint32x4Getters() {
   // Create a Uint32x4 and check that the getters work:
   var f = Uint32x4(11, 22, 33, 44);
   assertEq(Uint32x4.extractLane(f, 0), 11);
   assertEq(Uint32x4.extractLane(f, 1), 22);
   assertEq(Uint32x4.extractLane(f, 2), 33);
   assertEq(Uint32x4.extractLane(f, 3), 44);
 
-  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, 4), TypeError);
-  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, 4), RangeError);
+  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Uint32x4.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Uint32x4.extractLane(Float32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Uint32x4.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Uint32x4.extractLane(f, f), TypeError);
 }
 
 function testUint32x4Handles() {
   var Array = Uint32x4.array(3);
   var array = new Array([Uint32x4(1, 2, 3, 4),
@@ -769,20 +769,20 @@ function testBool8x16Getters() {
   assertEq(Bool8x16.extractLane(f, 9), true);
   assertEq(Bool8x16.extractLane(f, 10), false);
   assertEq(Bool8x16.extractLane(f, 11), false);
   assertEq(Bool8x16.extractLane(f, 12), true);
   assertEq(Bool8x16.extractLane(f, 13), true);
   assertEq(Bool8x16.extractLane(f, 14), false);
   assertEq(Bool8x16.extractLane(f, 15), false);
 
-  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, 16), TypeError);
-  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, 16), RangeError);
+  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Bool8x16.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Bool8x16.extractLane(Float32x4(1, 2, 3, 4), 0), TypeError);
   assertThrowsInstanceOf(() => Bool8x16.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Bool8x16.extractLane(f, f), TypeError);
 }
 
 function testBool8x16Reify() {
   var Array = Bool8x16.array(3);
   var array = new Array([Bool8x16(true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false),
@@ -832,20 +832,20 @@ function testBool16x8Getters() {
   assertEq(Bool16x8.extractLane(f, 1), false);
   assertEq(Bool16x8.extractLane(f, 2), true);
   assertEq(Bool16x8.extractLane(f, 3), false);
   assertEq(Bool16x8.extractLane(f, 4), true);
   assertEq(Bool16x8.extractLane(f, 5), true);
   assertEq(Bool16x8.extractLane(f, 6), false);
   assertEq(Bool16x8.extractLane(f, 7), false);
 
-  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, 8), TypeError);
-  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, 8), RangeError);
+  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Bool16x8.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Bool16x8.extractLane(Float32x4(1, 2, 3, 4), 0), TypeError);
   assertThrowsInstanceOf(() => Bool16x8.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Bool16x8.extractLane(f, f), TypeError);
 }
 
 function testBool16x8Reify() {
   var Array = Bool16x8.array(3);
   var array = new Array([Bool16x8(true, false, true, false, true, false, true, false),
@@ -888,20 +888,20 @@ function testBool16x8Setters() {
 
 function testBool32x4Getters() {
   // Create a Bool32x4 and check that the getters work:
   var f = Bool32x4(true, false, false, true);
   assertEq(Bool32x4.extractLane(f, 0), true);
   assertEq(Bool32x4.extractLane(f, 1), false);
   assertEq(Bool32x4.extractLane(f, 2), false);
   assertEq(Bool32x4.extractLane(f, 3), true);
-  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, 4), TypeError);
-  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, 4), RangeError);
+  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Bool32x4.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Bool32x4.extractLane(Float32x4(1, 2, 3, 4), 0), TypeError);
   assertThrowsInstanceOf(() => Bool32x4.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Bool32x4.extractLane(f, f), TypeError);
 }
 
 function testBool32x4Reify() {
   var Array = Bool32x4.array(3);
   var array = new Array([Bool32x4(true, false, false, true),
@@ -945,20 +945,20 @@ function testBool32x4Setters() {
 }
 
 function testBool64x2Getters() {
   // Create a Bool64x2 and check that the getters work:
   var f = Bool64x2(true, false);
   assertEq(Bool64x2.extractLane(f, 0), true);
   assertEq(Bool64x2.extractLane(f, 1), false);
 
-  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, 2), TypeError);
-  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, -1), TypeError);
-  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, 0.5), TypeError);
-  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, {}), TypeError);
+  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, 2), RangeError);
+  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, -1), RangeError);
+  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, 0.5), RangeError);
+  assertThrowsInstanceOf(() => Bool64x2.extractLane(f, {}), RangeError);
   assertThrowsInstanceOf(() => Bool64x2.extractLane(Bool32x4(1,2,3,4), 0), TypeError);
   assertThrowsInstanceOf(() => Bool64x2.extractLane(1, 0), TypeError);
   assertThrowsInstanceOf(() => Bool64x2.extractLane(f, f), TypeError);
 }
 
 function testBool64x2Reify() {
   var Array = Bool64x2.array(3);
   var array = new Array([Bool64x2(true, false),
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -288,21 +288,21 @@
     macro(null, null, "null") \
     macro(symbol, symbol, "symbol") \
     /* Well-known atom names must be continuous and ordered, matching \
      * enum JS::SymbolCode in jsapi.h. */ \
     macro(iterator, iterator, "iterator") \
     macro(match, match, "match") \
     macro(species, species, "species") \
     macro(toPrimitive, toPrimitive, "toPrimitive") \
+    macro(unscopables, unscopables, "unscopables") \
     /* Same goes for the descriptions of the well-known symbols. */ \
     macro(Symbol_hasInstance, Symbol_hasInstance, "Symbol.hasInstance") \
     macro(Symbol_isConcatSpreadable, Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable") \
     macro(Symbol_iterator, Symbol_iterator, "Symbol.iterator") \
     macro(Symbol_match,    Symbol_match,    "Symbol.match") \
     macro(Symbol_species,  Symbol_species,  "Symbol.species") \
     macro(Symbol_toPrimitive, Symbol_toPrimitive, "Symbol.toPrimitive") \
-    macro(Symbol_toStringTag, Symbol_toStringTag, "Symbol.toStringTag") \
     macro(Symbol_unscopables, Symbol_unscopables, "Symbol.unscopables") \
     /* Function names for properties named by symbols. */ \
     macro(Symbol_iterator_fun, Symbol_iterator_fun, "[Symbol.iterator]") \
 
 #endif /* vm_CommonPropertyNames_h */
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8867,16 +8867,24 @@ DebuggerEnv_getVariable(JSContext* cx, u
     RootedValue v(cx);
     {
         Maybe<AutoCompartment> ac;
         ac.emplace(cx, env);
 
         /* This can trigger getters. */
         ErrorCopier ec(ac);
 
+        bool found;
+        if (!HasProperty(cx, env, id, &found))
+            return false;
+        if (!found) {
+            args.rval().setUndefined();
+            return true;
+        }
+
         // For DebugScopeObjects, we get sentinel values for optimized out
         // slots and arguments instead of throwing (the default behavior).
         //
         // See wrapDebuggeeValue for how the sentinel values are wrapped.
         if (env->is<DebugScopeObject>()) {
             if (!env->as<DebugScopeObject>().getMaybeSentinelValue(cx, id, &v))
                 return false;
         } else {
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -442,20 +442,19 @@ namespace js {
  * field is a smart pointer that's immutable once initialized.
  * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
  *
  * Well-known symbols are never GC'd. The description() of each well-known
  * symbol is a permanent atom.
  */
 struct WellKnownSymbols
 {
-    js::ImmutableSymbolPtr iterator;
-    js::ImmutableSymbolPtr match;
-    js::ImmutableSymbolPtr species;
-    js::ImmutableSymbolPtr toPrimitive;
+#define DECLARE_SYMBOL(name) js::ImmutableSymbolPtr name;
+    JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
+#undef DECLARE_SYMBOL
 
     const ImmutableSymbolPtr& get(size_t u) const {
         MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
         const ImmutableSymbolPtr* symbols = reinterpret_cast<const ImmutableSymbolPtr*>(this);
         return symbols[u];
     }
 
     const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -750,44 +750,84 @@ DynamicWithObject::create(JSContext* cx,
     obj->setEnclosingScope(enclosing);
     obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
     obj->setFixedSlot(THIS_SLOT, thisv);
     obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
 
     return obj;
 }
 
+/* Implements ES6 8.1.1.2.1 HasBinding steps 7-9. */
+static bool
+CheckUnscopables(JSContext *cx, HandleObject obj, HandleId id, bool *scopable)
+{
+    RootedId unscopablesId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols()
+                                                .get(JS::SymbolCode::unscopables)));
+    RootedValue v(cx);
+    if (!GetProperty(cx, obj, obj, unscopablesId, &v))
+        return false;
+    if (v.isObject()) {
+        RootedObject unscopablesObj(cx, &v.toObject());
+        if (!GetProperty(cx, unscopablesObj, unscopablesObj, id, &v))
+            return false;
+        *scopable = !ToBoolean(v);
+    } else {
+        *scopable = true;
+    }
+    return true;
+}
+
 static bool
 with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
                     MutableHandleObject objp, MutableHandleShape propp)
 {
     if (JSID_IS_ATOM(id, cx->names().dotThis)) {
         objp.set(nullptr);
         propp.set(nullptr);
         return true;
     }
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
-    return LookupProperty(cx, actual, id, objp, propp);
+    if (!LookupProperty(cx, actual, id, objp, propp))
+        return false;
+
+    if (propp) {
+        bool scopable;
+        if (!CheckUnscopables(cx, actual, id, &scopable))
+            return false;
+        if (!scopable) {
+            objp.set(nullptr);
+            propp.set(nullptr);
+        }
+    }
+    return true;
 }
 
 static bool
 with_DefineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<PropertyDescriptor> desc,
                     ObjectOpResult& result)
 {
     MOZ_ASSERT(!JSID_IS_ATOM(id, cx->names().dotThis));
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return DefineProperty(cx, actual, id, desc, result);
 }
 
 static bool
 with_HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
 {
     MOZ_ASSERT(!JSID_IS_ATOM(id, cx->names().dotThis));
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
-    return HasProperty(cx, actual, id, foundp);
+
+    // ES 8.1.1.2.1 step 3-5.
+    if (!HasProperty(cx, actual, id, foundp))
+        return false;
+    if (!*foundp)
+        return true;
+
+    // Steps 7-10. (Step 6 is a no-op.)
+    return CheckUnscopables(cx, actual, id, foundp);
 }
 
 static bool
 with_GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
                  MutableHandleValue vp)
 {
     MOZ_ASSERT(!JSID_IS_ATOM(id, cx->names().dotThis));
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
@@ -2241,22 +2281,35 @@ class DebugScopeProxy : public BaseProxy
                 return false;
         }
 
         // DynamicWithObject isn't a very good proxy.  It doesn't have a
         // JSNewEnumerateOp implementation, because if it just delegated to the
         // target object, the object would indicate that native enumeration is
         // the thing to do, but native enumeration over the DynamicWithObject
         // wrapper yields no properties.  So instead here we hack around the
-        // issue, and punch a hole through to the with object target.
-        Rooted<JSObject*> target(cx, (scope->is<DynamicWithObject>()
-                                      ? &scope->as<DynamicWithObject>().object() : scope));
+        // issue: punch a hole through to the with object target, then manually
+        // examine @@unscopables.
+        bool isWith = scope->is<DynamicWithObject>();
+        Rooted<JSObject*> target(cx, (isWith ? &scope->as<DynamicWithObject>().object() : scope));
         if (!GetPropertyKeys(cx, target, JSITER_OWNONLY, &props))
             return false;
 
+        if (isWith) {
+            size_t j = 0;
+            for (size_t i = 0; i < props.length(); i++) {
+                bool inScope;
+                if (!CheckUnscopables(cx, scope, props[i], &inScope))
+                    return false;
+                if (inScope)
+                    props[j++].set(props[i]);
+            }
+            props.resize(j);
+        }
+
         /*
          * Function scopes are optimized to not contain unaliased variables so
          * they must be manually appended here.
          */
         if (isFunctionScope(*scope)) {
             RootedScript script(cx, scope->as<CallObject>().callee().nonLazyScript());
             for (BindingIter bi(script); bi; bi++) {
                 if (!bi->aliased() && !props.append(NameToId(bi->name())))
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -6071,17 +6071,18 @@ ContainerState::CreateMaskLayer(Layer *a
 
   const MaskLayerImageCache::MaskLayerImageKey* lookupKey = newKey;
 
   // check to see if we can reuse a mask image
   RefPtr<ImageContainer> container =
     GetMaskLayerImageCache()->FindImageFor(&lookupKey);
 
   if (!container) {
-    IntSize surfaceSizeInt(NSToIntCeil(surfaceSize.width),
+    // Make mask image width aligned to 4. See Bug 1245552.
+    IntSize surfaceSizeInt(GetAlignedStride<4>(NSToIntCeil(surfaceSize.width)),
                            NSToIntCeil(surfaceSize.height));
     // no existing mask image, so build a new one
     RefPtr<DrawTarget> dt =
       aLayer->Manager()->CreateOptimalMaskDrawTarget(surfaceSizeInt);
 
     // fail if we can't get the right surface
     if (!dt) {
       NS_WARNING("Could not create DrawTarget for mask layer.");
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -93,19 +93,17 @@ RestyleManager::RestyleManager(nsPresCon
   , mRebuildAllExtraHint(nsChangeHint(0))
   , mRebuildAllRestyleHint(nsRestyleHint(0))
   , mAnimationGeneration(0)
   , mReframingStyleContexts(nullptr)
   , mAnimationsWithDestroyedFrame(nullptr)
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
                      ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR)
-#ifdef DEBUG
   , mIsProcessingRestyles(false)
-#endif
 #ifdef RESTYLE_LOGGING
   , mLoggingDepth(0)
 #endif
 {
   mPendingRestyles.Init(this);
 }
 
 void
@@ -1722,28 +1720,26 @@ RestyleManager::ProcessPendingRestyles()
 
   // First do any queued-up frame creation.  (We should really
   // merge this into the rest of the process, though; see bug 827239.)
   mPresContext->FrameConstructor()->CreateNeededFrames();
 
   // Process non-animation restyles...
   MOZ_ASSERT(!mIsProcessingRestyles,
              "Nesting calls to ProcessPendingRestyles?");
-#ifdef DEBUG
   mIsProcessingRestyles = true;
-#endif
 
   // Before we process any restyles, we need to ensure that style
   // resulting from any animations is up-to-date, so that if any style
   // changes we cause trigger transitions, we have the correct old style
   // for starting the transition.
   bool haveNonAnimation =
     mHavePendingNonAnimationRestyles || mDoRebuildAllStyleData;
   if (haveNonAnimation) {
-    IncrementAnimationGeneration();
+    ++mAnimationGeneration;
     UpdateOnlyAnimationStyles();
   } else {
     // If we don't have non-animation style updates, then we have queued
     // up animation style updates from the refresh driver tick.  This
     // doesn't necessarily include *all* animation style updates, since
     // we might be suppressing main-thread updates for some animations,
     // so we don't want to call UpdateOnlyAnimationStyles, which updates
     // all animations.  In other words, the work that we're about to do
@@ -1766,19 +1762,17 @@ RestyleManager::ProcessPendingRestyles()
   }
 
   ProcessRestyles(mPendingRestyles);
 
   if (!haveNonAnimation) {
     mPresContext->TransitionManager()->SetInAnimationOnlyStyleUpdate(false);
   }
 
-#ifdef DEBUG
   mIsProcessingRestyles = false;
-#endif
 
   NS_ASSERTION(haveNonAnimation || !mHavePendingNonAnimationRestyles,
                "should not have added restyles");
   mHavePendingNonAnimationRestyles = false;
 
   if (mDoRebuildAllStyleData) {
     // We probably wasted a lot of work up above, but this seems safest
     // and it should be rarely used.
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -103,17 +103,24 @@ public:
   static uint64_t GetAnimationGenerationForFrame(nsIFrame* aFrame);
 
   // Update the animation generation count to mark that animation state
   // has changed.
   //
   // This is normally performed automatically by ProcessPendingRestyles
   // but it is also called when we have out-of-band changes to animations
   // such as changes made through the Web Animations API.
-  void IncrementAnimationGeneration() { ++mAnimationGeneration; }
+  void IncrementAnimationGeneration() {
+    // We update the animation generation at start of each call to
+    // ProcessPendingRestyles so we should ignore any subsequent (redundant)
+    // calls that occur while we are still processing restyles.
+    if (!mIsProcessingRestyles) {
+      ++mAnimationGeneration;
+    }
+  }
 
   // Whether rule matching should skip styles associated with animation
   bool SkipAnimationRules() const { return mSkipAnimationRules; }
 
   void SetSkipAnimationRules(bool aSkipAnimationRules) {
     mSkipAnimationRules = aSkipAnimationRules;
   }
 
@@ -560,19 +567,21 @@ private:
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
   ReframingStyleContexts* mReframingStyleContexts;
   AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame;
 
   RestyleTracker mPendingRestyles;
 
-#ifdef DEBUG
+  // Are we currently in the middle of a call to ProcessRestyles?
+  // This flag is used both as a debugging aid to assert that we are not
+  // performing nested calls to ProcessPendingRestyles, as well as to ignore
+  // redundant calls to IncrementAnimationGeneration.
   bool mIsProcessingRestyles;
-#endif
 
 #ifdef RESTYLE_LOGGING
   int32_t mLoggingDepth;
 #endif
 };
 
 /**
  * An ElementRestyler is created for *each* element in a subtree that we
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1198,19 +1198,24 @@ nsPresContext::SetShell(nsIPresShell* aS
       mAnimationManager = nullptr;
     }
     if (mRestyleManager) {
       mRestyleManager->Disconnect();
       mRestyleManager = nullptr;
     }
 
     if (IsRoot()) {
+      nsRootPresContext* thisRoot = static_cast<nsRootPresContext*>(this);
+
       // Have to cancel our plugin geometry timer, because the
       // callback for that depends on a non-null presshell.
-      static_cast<nsRootPresContext*>(this)->CancelApplyPluginGeometryTimer();
+      thisRoot->CancelApplyPluginGeometryTimer();
+
+      // The did-paint timer also depends on a non-null pres shell.
+      thisRoot->CancelDidPaintTimer();
     }
   }
 }
 
 void
 nsPresContext::DoChangeCharSet(const nsCString& aCharSet)
 {
   UpdateCharSet(aCharSet);
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -202,13 +202,13 @@ RESOURCE_FILES.html = [
     'folder.png',
 ]
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 
-if CONFIG['MOZ_WIDGET_GTK']:
+if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     CXXFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['MOZ_ENABLE_QT']:
     CXXFLAGS += CONFIG['MOZ_QT_CFLAGS']
--- a/layout/reftests/bidi/numeral/reftest.list
+++ b/layout/reftests/bidi/numeral/reftest.list
@@ -29,19 +29,19 @@ pref(bidi.numeral,2) == bug441782-1.html
 pref(bidi.numeral,3) == bug441782-1.html bug441782-1-ref.html
 pref(bidi.numeral,4) == bug441782-1.html bug441782-1-ref.html
 pref(bidi.numeral,0) != bug441782-2.html bug441782-2-ref.html
 pref(bidi.numeral,1) == bug441782-2.html bug441782-2-ref.html
 pref(bidi.numeral,2) == bug441782-2.html bug441782-2-ref.html
 pref(bidi.numeral,3) == bug441782-2.html bug441782-2-ref.html
 pref(bidi.numeral,4) == bug441782-2.html bug441782-2-ref.html
 pref(bidi.numeral,0) != bug441782-3.html bug441782-3-ref.html
-fails-if(winWidget&&!layersGPUAccelerated) fuzzy-if(winWidget&&!d2d&&d3d11,13,1) pref(bidi.numeral,1) == bug441782-3.html bug441782-3-ref.html
-fails-if(winWidget&&!layersGPUAccelerated) fuzzy-if(winWidget&&!d2d&&d3d11,13,1) pref(bidi.numeral,2) == bug441782-3.html bug441782-3-ref.html
-fails-if(winWidget&&!layersGPUAccelerated) fuzzy-if(winWidget&&!d2d&&d3d11,13,1) pref(bidi.numeral,3) == bug441782-3.html bug441782-3-ref.html
+fails-if(winWidget&&!layersGPUAccelerated&&!(/^Windows\x20NT\x205\.1/.test(http.oscpu))) fuzzy-if(winWidget&&!d2d&&d3d11,13,1) pref(bidi.numeral,1) == bug441782-3.html bug441782-3-ref.html
+fails-if(winWidget&&!layersGPUAccelerated&&!(/^Windows\x20NT\x205\.1/.test(http.oscpu))) fuzzy-if(winWidget&&!d2d&&d3d11,13,1) pref(bidi.numeral,2) == bug441782-3.html bug441782-3-ref.html
+fails-if(winWidget&&!layersGPUAccelerated&&!(/^Windows\x20NT\x205\.1/.test(http.oscpu))) fuzzy-if(winWidget&&!d2d&&d3d11,13,1) pref(bidi.numeral,3) == bug441782-3.html bug441782-3-ref.html
 pref(bidi.numeral,4) == bug441782-3.html bug441782-3-ref.html
 pref(bidi.numeral,0) != bug441782-4.html bug441782-4-ref.html
 pref(bidi.numeral,1) == bug441782-4.html bug441782-4-ref.html
 pref(bidi.numeral,2) == bug441782-4.html bug441782-4-ref.html
 pref(bidi.numeral,3) == bug441782-4.html bug441782-4-ref.html
 pref(bidi.numeral,4) == bug441782-4.html bug441782-4-ref.html
 pref(bidi.numeral,0) != bug441782-5.html bug441782-5-ref.html
 pref(bidi.numeral,1) == bug441782-5.html bug441782-5-ref.html
--- a/layout/reftests/xul/reftest.list
+++ b/layout/reftests/xul/reftest.list
@@ -1,16 +1,16 @@
 skip-if((B2G&&browserIsRemote)||Mulet) == menuitem-key.xul menuitem-key-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
 # these random-if(Android) are due to differences between Android Native & Xul, see bug 732569
 random-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == menulist-shrinkwrap-1.xul menulist-shrinkwrap-1-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
 random-if(Android||B2G) fails-if(winWidget) skip-if((B2G&&browserIsRemote)||Mulet) == menulist-shrinkwrap-2.xul menulist-shrinkwrap-2-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) == textbox-overflow-1.xul textbox-overflow-1-ref.xul # for bug 749658 # Initial mulet triage: parity with B2G/B2G Desktop
 # accesskeys are not normally displayed on Mac, so skip this test
 skip-if(cocoaWidget) skip-if((B2G&&browserIsRemote)||Mulet) == accesskey.xul accesskey-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(cocoaWidget) fails-if(/^Windows\x20NT\x206\.2/.test(http.oscpu)&&browserIsRemote) fuzzy-if(xulRuntime.widgetToolkit=="gtk3",1,11) skip-if((B2G&&browserIsRemote)||Mulet) == tree-row-outline-1.xul tree-row-outline-1-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop, win8: bug 1254832
+fails-if(cocoaWidget) fails-if(/^Windows\x20NT\x206\.2/.test(http.oscpu)&&browserIsRemote&&layersGPUAccelerated) fuzzy-if(xulRuntime.widgetToolkit=="gtk3",1,11) skip-if((B2G&&browserIsRemote)||Mulet) == tree-row-outline-1.xul tree-row-outline-1-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop, win8: bug 1254832
 skip-if((B2G&&browserIsRemote)||Mulet) != tree-row-outline-1.xul tree-row-outline-1-notref.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) == text-small-caps-1.xul text-small-caps-1-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60) fuzzy-if(cocoaWidget&&browserIsRemote,1,31) fuzzy-if(winWidget&&browserIsRemote&&layersGPUAccelerated,1,50) == inactive-fixed-bg-bug1205630.xul inactive-fixed-bg-bug1205630-ref.html
 
 # Tests for XUL <image> with 'object-fit' & 'object-position':
 # These tests should be very similar to tests in our w3c-css/submitted/images3
 # reftest directory. They live here because they use XUL, and it
 # wouldn't be fair of us to make a W3C testsuite implicitly depend on XUL.
rename from layout/style/test/chrome/additional_sheets_helper.html
rename to layout/style/test/additional_sheets_helper.html
--- a/layout/style/test/chrome/chrome.ini
+++ b/layout/style/test/chrome/chrome.ini
@@ -4,18 +4,16 @@ support-files =
   bug418986-2.js
   bug535806-css.css
   bug535806-html.html
   bug535806-xul.xul
   hover_helper.html
   match.png
   mismatch.png
 
-[test_addSheet.html]
-[test_additional_sheets.html]
 [test_author_specified_style.html]
 [test_bug418986-2.xul]
 [test_bug1157097.html]
 [test_bug1160724.xul]
 [test_bug535806.xul]
 [test_display_mode.html]
 tags = fullscreen
 [test_hover.html]
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -29,16 +29,20 @@ support-files =
   visited_image_loading_frame_empty.html
   visited_image_loading_frame.html
   visited_image_loading.sjs
   visited-lying-inner.html
   visited-pref-iframe.html
   xbl_bindings.xml
 
 [test_acid3_test46.html]
+[test_addSheet.html]
+support-files = additional_sheets_helper.html
+[test_additional_sheets.html]
+support-files = additional_sheets_helper.html
 [test_all_shorthand.html]
 [test_animations.html]
 skip-if = toolkit == 'android'
 [test_animations_async_tests.html]
 support-files = ../../reftests/fonts/Ahem.ttf file_animations_async_tests.html
 [test_animations_dynamic_changes.html]
 [test_animations_effect_timing_duration.html]
 support-files = file_animations_effect_timing_duration.html
--- a/layout/style/test/moz.build
+++ b/layout/style/test/moz.build
@@ -28,17 +28,16 @@ HostSimplePrograms([
 MOCHITEST_MANIFESTS += [
     'mochitest.ini',
 ]
 XPCSHELL_TESTS_MANIFESTS += ['xpcshell.ini']
 BROWSER_CHROME_MANIFESTS += ['browser.ini']
 MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']
 
 TEST_HARNESS_FILES.testing.mochitest.tests.layout.style.test.chrome += [
-    'chrome/additional_sheets_helper.html',
     'chrome/moz_document_helper.html',
 ]
 
 TEST_HARNESS_FILES.testing.mochitest.tests.layout.style.test['css-visited'] += [
     '/layout/reftests/css-visited/border-1-ref.html',
     '/layout/reftests/css-visited/border-1.html',
     '/layout/reftests/css-visited/border-2-ref.html',
     '/layout/reftests/css-visited/border-2a.html',
rename from layout/style/test/chrome/test_addSheet.html
rename to layout/style/test/test_addSheet.html
--- a/layout/style/test/chrome/test_addSheet.html
+++ b/layout/style/test/test_addSheet.html
@@ -1,43 +1,43 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for addSheet</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1024707">Mozilla Bug 1024707</a>
 
-<iframe id="iframe1" src="http://mochi.test:8888/tests/layout/style/test/chrome/additional_sheets_helper.html"></iframe>
-<iframe id="iframe2" src="http://mochi.test:8888/tests/layout/style/test/chrome/additional_sheets_helper.html"></iframe>
+<iframe id="iframe1" src="additional_sheets_helper.html"></iframe>
+<iframe id="iframe2" src="additional_sheets_helper.html"></iframe>
 
 <pre id="test">
 <script type="application/javascript; version=1.8">
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
-let IO = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+let gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
+  .getService(SpecialPowers.Ci.nsIIOService);
 
-let service = Cc["@mozilla.org/content/style-sheet-service;1"]
-                .getService(Ci.nsIStyleSheetService);
+let gSSService = SpecialPowers.Cc["@mozilla.org/content/style-sheet-service;1"]
+  .getService(SpecialPowers.Ci.nsIStyleSheetService);
 
 function test(win, sheet) {
     let cs = win.getComputedStyle(win.document.body, null);
     is(cs.getPropertyValue('color'), "rgb(0, 0, 0)", "should have default color");
-    var windowUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindowUtils);
-    windowUtils.addSheet(sheet, Ci.nsIDOMWindowUtils.USER_SHEET);
+    var windowUtils = SpecialPowers.wrap(win)
+      .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+      .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
+    windowUtils.addSheet(sheet, SpecialPowers.Ci.nsIDOMWindowUtils.USER_SHEET);
     is(cs.getPropertyValue('color'), "rgb(255, 0, 0)", "should have changed color to red");
 }
 
 function run() {
-    var uri = IO.newURI("data:text/css,body{color:red;}", null, null);
-    let sheet = service.preloadSheet(uri, Ci.nsIStyleSheetService.USER_SHEET);
+    var uri = gIOService.newURI("data:text/css,body{color:red;}", null, null);
+    let sheet = gSSService.preloadSheet(uri, SpecialPowers.Ci.nsIStyleSheetService.USER_SHEET);
 
     test(document.getElementById("iframe1").contentWindow, sheet);
     test(document.getElementById("iframe2").contentWindow, sheet);
 
     SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
rename from layout/style/test/chrome/test_additional_sheets.html
rename to layout/style/test/test_additional_sheets.html
--- a/layout/style/test/chrome/test_additional_sheets.html
+++ b/layout/style/test/test_additional_sheets.html
@@ -1,26 +1,26 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for additional sheets</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737003">Mozilla Bug 737003</a>
-<iframe id="iframe" src="http://mochi.test:8888/tests/layout/style/test/chrome/additional_sheets_helper.html"></iframe>
+<iframe id="iframe" src="additional_sheets_helper.html"></iframe>
 <pre id="test">
 <script type="application/javascript; version=1.8">
 
-
+var gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
+  .getService(SpecialPowers.Ci.nsIIOService)
 
-var gIOService = Components.classes["@mozilla.org/network/io-service;1"]
-  .getService(Components.interfaces.nsIIOService)
+var gSSService = SpecialPowers.Cc["@mozilla.org/content/style-sheet-service;1"]
+  .getService(SpecialPowers.Ci.nsIStyleSheetService);
 
 function getUri(style)
 {
   return "data:text/css," + style;
 }
 
 function getStyle(color, swapped)
 {
@@ -56,26 +56,28 @@ function removeAgentSheet(win, style)
 function removeAuthorSheet(win, style)
 {
   removeSheet(win, style, "AUTHOR_SHEET");
 }
 
 function loadSheet(win, style, type)
 {
   var uri = gIOService.newURI(getUri(style), null, null);
-  var windowUtils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-    .getInterface(Components.interfaces.nsIDOMWindowUtils);
+  var windowUtils = SpecialPowers.wrap(win)
+    .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+    .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
   windowUtils.loadSheet(uri, windowUtils[type]);
 }
 
 function removeSheet(win, style, type)
 {
   var uri = gIOService.newURI(getUri(style), null, null);
-  var windowUtils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-    .getInterface(Components.interfaces.nsIDOMWindowUtils);
+  var windowUtils = SpecialPowers.wrap(win)
+    .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+    .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
   windowUtils.removeSheet(uri, windowUtils[type]);
 }
 
 function loadAndRegisterUserSheet(win, style)
 {
   loadAndRegisterSheet(win, style, "USER_SHEET");
 }
 
@@ -101,34 +103,26 @@ function unregisterAgentSheet(win, style
 
 function unregisterAuthorSheet(win, style)
 {
   unregisterSheet(win, style, "AUTHOR_SHEET");
 }
 
 function loadAndRegisterSheet(win, style, type)
 {
-  var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
-    .getService(Components.interfaces.nsIStyleSheetService);
-  var ios = Components.classes["@mozilla.org/network/io-service;1"]
-    .getService(Components.interfaces.nsIIOService);
-  uri = ios.newURI(getUri(style), null, null);
-  sss.loadAndRegisterSheet(uri, sss[type]);
-  is (sss.sheetRegistered(uri, sss[type]), true);
+  uri = gIOService.newURI(getUri(style), null, null);
+  gSSService.loadAndRegisterSheet(uri, gSSService[type]);
+  is(gSSService.sheetRegistered(uri, gSSService[type]), true);
 }
 
 function unregisterSheet(win, style, type)
 {
-  var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
-    .getService(Components.interfaces.nsIStyleSheetService);
-  var ios = Components.classes["@mozilla.org/network/io-service;1"]
-    .getService(Components.interfaces.nsIIOService);
-  var uri = ios.newURI(getUri(style), null, null);
-  sss.unregisterSheet(uri, sss[type]);
-  is (sss.sheetRegistered(uri, sss[type]), false);
+  var uri = gIOService.newURI(getUri(style), null, null);
+  gSSService.unregisterSheet(uri, gSSService[type]);
+  is(gSSService.sheetRegistered(uri, gSSService[type]), false);
 }
 
 function setDocSheet(win, style)
 {
   var subdoc = win.document;
   var headID = subdoc.getElementsByTagName("head")[0];
   var cssNode = subdoc.createElement('style');
   cssNode.type = 'text/css';
@@ -297,20 +291,22 @@ function run()
 
   testStyleVsStyle(win, additionalAuthor, agent,
                      {AB:{rr:0, ii:1, ri:1, ir:0}, BA:{rr:0, ii:1, ri:1, ir:0}});
 
   testStyleVsStyle(win, additionalAuthor, additionalUser,
                    {AB:{rr:0, ii:1, ri:1, ir:0}, BA:{rr:0, ii:1, ri:1, ir:0}});
 
   // Bug 1228542
-  loadAndRegisterAuthorSheet(win, getStyle('rgb(255, 0, 0)'));
+  var url = getStyle('rgb(255, 0, 0)');
+  loadAndRegisterAuthorSheet(win, url);
   // Avoiding security exception...
   (new win.Function("document.open()"))();
   (new win.Function("document.close()"))();
+  unregisterAuthorSheet(win, url);
 
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
--- a/media/mtransport/test/transport_unittests.cpp
+++ b/media/mtransport/test/transport_unittests.cpp
@@ -957,30 +957,42 @@ class TransportTest : public MtransportT
   nsCOMPtr<nsIEventTarget> target_;
 };
 
 
 TEST_F(TransportTest, TestNoDtlsVerificationSettings) {
   ConnectSocketExpectFail();
 }
 
+static void DisableChaCha(TransportTestPeer* peer) {
+  // On ARM, ChaCha20Poly1305 might be preferred; disable it for the tests that
+  // want to check the cipher suite.  It doesn't matter which peer disables the
+  // suite, disabling on either side has the same effect.
+  std::vector<uint16_t> chachaSuites;
+  chachaSuites.push_back(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
+  chachaSuites.push_back(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
+  peer->SetCipherSuiteChanges(std::vector<uint16_t>(), chachaSuites);
+}
+
 TEST_F(TransportTest, TestConnect) {
   SetDtlsPeer();
+  DisableChaCha(p1_);
   ConnectSocket();
 
   // check that we got the right suite
   ASSERT_EQ(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
 
   // no SRTP on this one
   ASSERT_EQ(0, p1_->srtpCipher());
 }
 
 TEST_F(TransportTest, TestConnectSrtp) {
   SetupSrtp();
   SetDtlsPeer();
+  DisableChaCha(p2_);
   ConnectSocket();
 
   ASSERT_EQ(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
 
   // SRTP is on
   ASSERT_EQ(SRTP_AES128_CM_HMAC_SHA1_80, p1_->srtpCipher());
 }
 
--- a/mobile/android/b2gdroid/moz.configure
+++ b/mobile/android/b2gdroid/moz.configure
@@ -1,7 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-include('../../../toolkit/moz.configure')
+include('../../../b2g/common.configure')
--- a/mobile/android/base/java/org/mozilla/gecko/gfx/DynamicToolbarAnimator.java
+++ b/mobile/android/base/java/org/mozilla/gecko/gfx/DynamicToolbarAnimator.java
@@ -433,16 +433,24 @@ public class DynamicToolbarAnimator {
         mToolbarTranslation = FloatUtils.clamp(mToolbarTranslation - translation, 0, mMaxTranslation);
         mLayerViewTranslation = FloatUtils.clamp(mLayerViewTranslation - translation, 0, mMaxTranslation);
 
         if (oldToolbarTranslation == mToolbarTranslation &&
             oldLayerViewTranslation == mLayerViewTranslation) {
             return false;
         }
 
+        if (mToolbarTranslation == mMaxTranslation) {
+            Log.v(LOGTAG, "Toolbar at maximum translation, calling shiftLayerView(" + mMaxTranslation + ")");
+            shiftLayerView(mMaxTranslation);
+        } else if (mToolbarTranslation == 0) {
+            Log.v(LOGTAG, "Toolbar at minimum translation, calling shiftLayerView(0)");
+            shiftLayerView(0);
+        }
+
         fireListeners();
         mTarget.getView().requestRender();
         return true;
     }
 
     public PointF getVisibleEndOfLayerView() {
         return new PointF(mTarget.getView().getWidth(),
             mTarget.getView().getHeight() - mMaxTranslation + mLayerViewTranslation);
--- a/mobile/android/tests/browser/robocop/robocop_input.html
+++ b/mobile/android/tests/browser/robocop/robocop_input.html
@@ -1,61 +1,134 @@
 <!DOCTYPE html>
 <html>
   <head>
     <title>Robocop Input</title>
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
   </head>
   <body>
     <p>Input: <input id="input" type="text"></p>
+    <p>Text area: <textarea id="text-area"></textarea></p>
+    <p>Content editable: <div id="content-editable" contentEditable="true"></div></p>
+    <p>Design mode: <iframe id="design-mode" src="data:text/html;charset=utf-8,<html><body></body></html>"></iframe></p>
     <p>Resetting input: <input id="resetting-input" type="text"></p>
     <p>Hiding input: <input id="hiding-input" type="text"></p>
     <script type="application/javascript;version=1.8" src="robocop_head.js"></script>
     <script type="application/javascript;version=1.8">
       let input = document.getElementById("input");
+      let textArea = document.getElementById("text-area");
+      let contentEditable = document.getElementById("content-editable");
+
+      let designMode = document.getElementById("design-mode");
+      designMode.contentDocument.designMode = "on";
+
+      // Spatial navigation interferes with design-mode key event tests.
+      SpecialPowers.setBoolPref("snav.enabled", false);
 
       // An input that resets the editor on every input by resetting the value property.
       let resetting_input = document.getElementById("resetting-input");
       resetting_input.addEventListener('input', function() {
         this.value = this.value;
       });
 
       // An input that hides on input.
       let hiding_input = document.getElementById("hiding-input");
       hiding_input.addEventListener('keydown', function(e) {
         if (e.key === "!") { // '!' key event as sent by testInputConnection.java.
           this.value = "";
           this.style.display = "none";
         }
       });
 
+      let getEditor, setValue, setSelection;
+
       let test = {
         focus_input: function(val) {
-          input.value = val;
+          getEditor = function() {
+            return SpecialPowers.wrap(input).QueryInterface(
+                SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+          };
+          setValue = function(val) {
+            input.value = val;
+          };
+          setSelection = function(pos) {
+            input.setSelectionRange(pos, pos);
+          };
+          setValue(val);
           input.focus();
         },
 
+        focus_text_area: function(val) {
+          getEditor = function() {
+            return SpecialPowers.wrap(textArea).QueryInterface(
+                SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+          };
+          setValue = function(val) {
+            textArea.value = val;
+          };
+          setSelection = function(pos) {
+            textArea.setSelectionRange(pos, pos);
+          };
+          setValue(val);
+          textArea.focus();
+        },
+
+        focus_content_editable: function(val) {
+          getEditor = function() {
+            return SpecialPowers.wrap(window).QueryInterface(
+                SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(
+                SpecialPowers.Ci.nsIWebNavigation).QueryInterface(
+                SpecialPowers.Ci.nsIDocShell).editor;
+          };
+          setValue = function(val) {
+            contentEditable.innerHTML = val;
+          };
+          setSelection = function(pos) {
+            window.getSelection().collapse(contentEditable.firstChild, pos);
+          };
+          setValue(val);
+          contentEditable.focus();
+        },
+
+        focus_design_mode: function(val) {
+          getEditor = function() {
+            return SpecialPowers.wrap(designMode.contentWindow).QueryInterface(
+                SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(
+                SpecialPowers.Ci.nsIWebNavigation).QueryInterface(
+                SpecialPowers.Ci.nsIDocShell).editor;
+          };
+          setValue = function(val) {
+            designMode.contentDocument.body.innerHTML = val;
+          };
+          setSelection = function(pos) {
+            designMode.contentWindow.getSelection().collapse(
+                designMode.contentDocument.body.firstChild, pos);
+          };
+          setValue(val);
+          designMode.contentWindow.focus();
+          designMode.contentDocument.body.focus();
+        },
+
         test_reflush_changes: function() {
-          let inputEditable = SpecialPowers.wrap(input).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
-          let inputIme = inputEditable.editor.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
+          let inputIme = getEditor().QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
           do_check_true(inputIme.composing);
 
           // Ending the composition then setting the input value triggers the bug.
           inputIme.forceCompositionEnd();
-          input.value = "good"; // Value that testInputConnection.java expects.
+          setValue("good"); // Value that testInputConnection.java expects.
+          setSelection(4);
         },
 
         test_set_selection: function() {
-          let inputEditable = SpecialPowers.wrap(input).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
-          let inputIme = inputEditable.editor.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
+          let inputIme = getEditor().QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
           do_check_true(inputIme.composing);
 
           // Ending the composition then setting the selection triggers the bug.
           inputIme.forceCompositionEnd();
-          input.setSelectionRange(3, 3); // Offsets that testInputConnection.java expects.
+          setSelection(3); // Offsets that testInputConnection.java expects.
         },
 
         focus_resetting_input: function(val) {
           resetting_input.value = val;
           resetting_input.focus();
         },
 
         focus_hiding_input: function(val) {
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java
@@ -38,16 +38,34 @@ public class testInputConnection extends
         mToolbar.assertTitle(url);
 
         // First run tests inside the normal input field.
         getJS().syncCall("focus_input", INITIAL_TEXT);
         mGeckoView.mTextInput
             .waitForInputConnection()
             .testInputConnection(new BasicInputConnectionTest());
 
+        // Then switch focus to the text area and rerun tests.
+        getJS().syncCall("focus_text_area", INITIAL_TEXT);
+        mGeckoView.mTextInput
+            .waitForInputConnection()
+            .testInputConnection(new BasicInputConnectionTest());
+
+        // Then switch focus to the content editable and rerun tests.
+        getJS().syncCall("focus_content_editable", INITIAL_TEXT);
+        mGeckoView.mTextInput
+            .waitForInputConnection()
+            .testInputConnection(new BasicInputConnectionTest());
+
+        // Then switch focus to the design mode document and rerun tests.
+        getJS().syncCall("focus_design_mode", INITIAL_TEXT);
+        mGeckoView.mTextInput
+            .waitForInputConnection()
+            .testInputConnection(new BasicInputConnectionTest());
+
         // Then switch focus to the resetting input field, and run tests there.
         getJS().syncCall("focus_resetting_input", "");
         mGeckoView.mTextInput
             .waitForInputConnection()
             .testInputConnection(new ResettingInputConnectionTest());
 
         // Then switch focus to the hiding input field, and run tests there.
         getJS().syncCall("focus_hiding_input", "");
@@ -55,19 +73,23 @@ public class testInputConnection extends
             .waitForInputConnection()
             .testInputConnection(new HidingInputConnectionTest());
 
         getJS().syncCall("finish_test");
     }
 
     private class BasicInputConnectionTest extends InputConnectionTest {
         @Override
-        public void test(InputConnection ic, EditorInfo info) {
-            // Test initial text provided by the hash in the test page URL
-            assertText("Initial text matches URL hash", ic, INITIAL_TEXT);
+        public void test(final InputConnection ic, EditorInfo info) {
+            waitFor("focus change", new Condition() {
+                @Override
+                public boolean isSatisfied() {
+                    return INITIAL_TEXT.equals(getText(ic));
+                }
+            });
 
             // Test setSelection
             ic.setSelection(0, 3);
             assertSelection("Can set selection to range", ic, 0, 3);
             ic.setSelection(-3, 6);
             // Test both forms of assert
             assertTextAndSelection("Can handle invalid range", ic, INITIAL_TEXT, 0, 3);
             ic.setSelection(3, 3);
@@ -253,16 +275,20 @@ public class testInputConnection extends
             processGeckoEvents(ic);
             assertTextAndSelectionAt("Can reset composing text (resetting)", ic, "baz", 3);
 
             ic.finishComposingText();
             assertTextAndSelectionAt("Can finish composing text (resetting)", ic, "baz", 3);
 
             ic.deleteSurroundingText(3, 0);
             assertTextAndSelectionAt("Can clear text", ic, "", 0);
+
+            // Make sure we don't leave behind stale events for the following test.
+            processGeckoEvents(ic);
+            processInputConnectionEvents();
         }
     }
 
     /**
      * HidingInputConnectionTest performs tests on the hiding input in
      * robocop_input.html. Any test that uses the normal input should be put in
      * BasicInputConnectionTest.
      */
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -718,23 +718,16 @@ pref("gfx.canvas.azure.backends", "skia"
 // Accelerated cg canvas where available (10.7+)
 pref("gfx.canvas.azure.accelerated", true);
 #else
 pref("gfx.canvas.azure.backends", "cairo");
 pref("gfx.content.azure.backends", "cairo");
 #endif
 #endif
 
-#ifdef MOZ_WIDGET_GTK2
-pref("gfx.content.azure.backends", "cairo");
-#endif
-#ifdef ANDROID
-pref("gfx.content.azure.backends", "cairo");
-#endif
-
 pref("gfx.work-around-driver-bugs", true);
 pref("gfx.prefer-mesa-llvmpipe", false);
 
 pref("gfx.draw-color-bars", false);
 
 pref("gfx.logging.texture-usage.enabled", false);
 pref("gfx.logging.peak-texture-usage.enabled", false);
 
--- a/moz.configure
+++ b/moz.configure
@@ -116,17 +116,17 @@ perl_version_check('5.006')
 check_prog('DOXYGEN', ('doxygen',), allow_missing=True)
 check_prog('TAR', ('gnutar', 'gtar', 'tar'))
 check_prog('UNZIP', ('unzip',))
 check_prog('XARGS', ('xargs',))
 check_prog('ZIP', ('zip',))
 
 @depends(target)
 def mac_programs(target):
-    if target.os == 'Darwin':
+    if target.kernel == 'Darwin':
         check_prog('DSYMUTIL', ('dsymutil', 'llvm-dsymutil'), allow_missing=True)
         check_prog('GENISOIMAGE', ('genisoimage',), allow_missing=True)
 
 @depends(target)
 def linux_programs(target):
     if target.os == 'GNU' and target.kernel == 'Linux':
         check_prog('RPMBUILD', ('rpmbuild',), allow_missing=True)
 
--- a/old-configure.in
+++ b/old-configure.in
@@ -91,50 +91,25 @@ dnl ====================================
 _topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd -P`
 _objdir=`pwd -P`
 
 MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P`
 DIST="$MOZ_BUILD_ROOT/dist"
 
 MOZ_DEFAULT_COMPILER
 
-MOZ_ARG_WITH_STRING(l10n-base,
-[  --with-l10n-base=DIR    path to l10n repositories],
-    L10NBASEDIR=$withval)
-if test -n "$L10NBASEDIR"; then
-    if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
-        AC_MSG_ERROR([--with-l10n-base must specify a path])
-    elif test -d "$L10NBASEDIR"; then
-        L10NBASEDIR=`cd "$L10NBASEDIR" && pwd -P`
-    else
-        AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
-    fi
-fi
-AC_SUBST(L10NBASEDIR)
-
-if test -n "$MOZTTDIR" -a ! -d "$MOZTTDIR" ; then
-    AC_MSG_ERROR([MOZTTDIR '$MOZTTDIR' isn't a valid directory])
-fi
-
-AC_SUBST(MOZTTDIR)
-if test -n "$MOZTTDIR" ; then
-    AC_DEFINE(PACKAGE_MOZTT)
-fi
-
-MOZ_ARG_WITH_STRING(gonk,
-[  --with-gonk=DIR
-               location of gonk dir],
-    gonkdir=$withval)
-
 MOZ_ARG_WITH_STRING(gonk-toolchain-prefix,
 [  --with-gonk-toolchain-prefix=DIR
                           prefix to gonk toolchain commands],
     gonk_toolchain_prefix=$withval)
 
 if test -n "$gonkdir" ; then
+    dnl export for js/src/configure. We can't pass the option down normally,
+    dnl because it's a `--enable-project=b2g`-only option.
+    export gonkdir
     kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
     android_source="$gonkdir"
     ANDROID_SOURCE="$android_source"
     ANDROID_NDK="${ANDROID_SOURCE}/ndk"
     dnl Default to ICS
     ANDROID_VERSION=15
     if test -n "${PLATFORM_SDK_VERSION}"; then
         ANDROID_VERSION="${PLATFORM_SDK_VERSION}"
@@ -162,17 +137,16 @@ if test -n "$gonkdir" ; then
         GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/ -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
         MOZ_B2G_BT=1
         MOZ_B2G_BT_BLUEZ=1
         MOZ_NFC=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_RTSP=1
-        MOZ_FMP4=1
         MOZ_SECUREELEMENT=1
         ;;
     17|18)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
         if test -d "$gonkdir/external/bluetooth/bluez"; then
             GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
             MOZ_B2G_BT=1
             MOZ_B2G_BT_BLUEZ=1
@@ -184,17 +158,16 @@ if test -n "$gonkdir" ; then
         MOZ_RTSP=1
         MOZ_NFC=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_OMX_ENCODER=1
         AC_SUBST(MOZ_OMX_ENCODER)
         AC_DEFINE(MOZ_OMX_ENCODER)
-        MOZ_FMP4=1
         MOZ_SECUREELEMENT=1
         ;;
     19)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
         MOZ_B2G_CAMERA=1
         if test -d "$gonkdir/system/bluetoothd"; then
             MOZ_B2G_BT=1
             MOZ_B2G_BT_DAEMON=1
@@ -203,27 +176,25 @@ if test -n "$gonkdir" ; then
         MOZ_RTSP=1
         MOZ_OMX_DECODER=1
         MOZ_OMX_ENCODER=1
         AC_DEFINE(MOZ_OMX_ENCODER)
         MOZ_AUDIO_OFFLOAD=1
         MOZ_SECUREELEMENT=1
         AC_SUBST(MOZ_AUDIO_OFFLOAD)
         AC_DEFINE(MOZ_AUDIO_OFFLOAD)
-        MOZ_FMP4=1
         ;;
     21|22)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
         MOZ_AUDIO_OFFLOAD=1
         MOZ_OMX_DECODER=1
         MOZ_OMX_ENCODER=1
         AC_DEFINE(MOZ_OMX_ENCODER)
         AC_SUBST(MOZ_AUDIO_OFFLOAD)
         AC_DEFINE(MOZ_AUDIO_OFFLOAD)
-        MOZ_FMP4=1
         MOZ_B2G_CAMERA=1
         if test -d "$gonkdir/system/bluetoothd"; then
             MOZ_B2G_BT=1
             MOZ_B2G_BT_DAEMON=1
         fi
         MOZ_NFC=1
         MOZ_RTSP=1
         ;;
@@ -832,20 +803,16 @@ LIB_SUFFIX=a
 IMPORT_LIB_SUFFIX=
 DIRENT_INO=d_ino
 MOZ_USER_DIR=".mozilla"
 
 MOZ_FIX_LINK_PATHS="-Wl,-rpath-link,${DIST}/bin -Wl,-rpath-link,${prefix}/lib"
 
 MOZ_FS_LAYOUT=unix
 
-USE_DEPENDENT_LIBS=1
-
-_PLATFORM_DEFAULT_TOOLKIT=cairo-gtk3
-
 dnl Configure platform-specific CPU architecture compiler options.
 dnl ==============================================================
 if test "$COMPILE_ENVIRONMENT"; then
     MOZ_ARCH_OPTS
 else
     if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
         dnl Default Android builds to ARMv7.
         MOZ_ARCH=armv7-a
@@ -1383,17 +1350,17 @@ case "$host" in
     if test -n "$_WIN32_MSVC"; then
         HOST_AR=lib
         HOST_AR_FLAGS='-NOLOGO -OUT:$@'
         HOST_CFLAGS="$HOST_CFLAGS -TC -nologo"
         HOST_RANLIB='echo ranlib'
     else
         HOST_CFLAGS="$HOST_CFLAGS -mwindows"
     fi
-    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -DNO_X11 -D_CRT_SECURE_NO_WARNINGS"
+    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
     HOST_BIN_SUFFIX=.exe
 
     case "${host_cpu}" in
     i*86)
         if test -n "$_WIN32_MSVC"; then
             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X86"
         fi
@@ -1403,17 +1370,17 @@ case "$host" in
             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X64"
         fi
         HOST_CFLAGS="$HOST_CFLAGS -D_AMD64_"
         ;;
     esac
     ;;
 
 *-darwin*)
-    HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX -DXP_MACOSX -DNO_X11"
+    HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX -DXP_MACOSX"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     ;;
 
 *-linux*|*-kfreebsd*-gnu|*-gnu*)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     ;;
 
@@ -1479,22 +1446,20 @@ case "$target" in
                                    ac_cv_ios_target="yes",
                                    ac_cv_ios_target="no")])
     if test "$ac_cv_ios_target" = "yes" -a -z $MOZ_IOS; then
        AC_MSG_ERROR([targeting iOS but not using an iOS SDK?])
     fi
     if test -n "$MOZ_IOS"; then
         AC_DEFINE(XP_IOS)
         AC_DEFINE(XP_DARWIN)
-        _PLATFORM_DEFAULT_TOOLKIT='cairo-uikit'
         direct_nspr_config=1
     else
         AC_DEFINE(XP_MACOSX)
         AC_DEFINE(XP_DARWIN)
-        _PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
         # The ExceptionHandling framework is needed for Objective-C exception
         # logging code in nsObjCExceptions.h. Currently we only use that in debug
         # builds.
         MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling";
     fi
 
     if test "x$lto_is_enabled" = "xyes"; then
         echo "Skipping -dead_strip because lto is enabled."
@@ -1533,24 +1498,21 @@ case "$target" in
     fi
     LDFLAGS=$_SAVE_LDFLAGS
 
     MOZ_FIX_LINK_PATHS="-Wl,-executable_path,${DIST}/bin"
     ;;
 
 *-android*|*-linuxandroid*)
     AC_DEFINE(NO_PW_GECOS)
-    no_x=yes
     if test -n "$gonkdir"; then
-        _PLATFORM_DEFAULT_TOOLKIT=cairo-gonk
         _PLATFORM_HAVE_RIL=1
         MOZ_B2G_FM=1
         MOZ_SYNTH_PICO=1
     else
-        _PLATFORM_DEFAULT_TOOLKIT=cairo-android
         if test "$COMPILE_ENVIRONMENT"; then
             MOZ_LINKER=1
         fi
     fi
 
     MOZ_GFX_OPTIMIZE_MOBILE=1
     MOZ_OPTIMIZE_FLAGS="-Os -fno-reorder-functions"
     if test -z "$CLANG_CC"; then
@@ -1803,32 +1765,19 @@ case "$target" in
     AC_DEFINE(WIN32)
     AC_DEFINE(XP_WIN)
     AC_DEFINE(XP_WIN32)
     AC_DEFINE(HW_THREADS)
     AC_DEFINE(STDC_HEADERS)
     AC_DEFINE(WIN32_LEAN_AND_MEAN)
     dnl See http://support.microsoft.com/kb/143208 to use STL
     AC_DEFINE(NOMINMAX)
-    _PLATFORM_DEFAULT_TOOLKIT='cairo-windows'
     BIN_SUFFIX='.exe'
     MOZ_USER_DIR="Mozilla"
 
-    dnl set NO_X11 defines here as the general check is skipped on win32
-    no_x=yes
-    AC_DEFINE(NO_X11)
-
-    case "$host" in
-    *-mingw*)
-        if test -n "$L10NBASEDIR"; then
-            L10NBASEDIR=`cd $L10NBASEDIR && pwd -W`
-        fi
-        ;;
-    esac
-
     case "$host_os" in
     cygwin*|msvc*|mks*)
         AC_MSG_ERROR([Using a Cygwin build environment is unsupported. Configure cannot check for presence of necessary headers. Please upgrade to MozillaBuild; see https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
         ;;
     esac
 
     case "$target" in
     i*86-*)
@@ -2118,52 +2067,52 @@ AC_CHECK_LIB(socket, socket)
 XLDFLAGS="$X_LIBS"
 XLIBS="$X_EXTRA_LIBS"
 
 dnl ========================================================
 dnl Checks for X libraries.
 dnl Ordering is important.
 dnl Xt is dependent upon SM as of X11R6
 dnl ========================================================
-if test "$no_x" = "yes"; then
-    AC_DEFINE(NO_X11)
-else
+if test -n "$MOZ_X11"; then
     AC_DEFINE_UNQUOTED(FUNCPROTO,15)
     XLIBS="-lX11 $XLIBS"
     _SAVE_LDFLAGS="$LDFLAGS"
     LDFLAGS="$XLDFLAGS $LDFLAGS"
     AC_CHECK_LIB(X11, XDrawLines, [X11_LIBS="-lX11"],
         [MISSING_X="$MISSING_X -lX11"], $XLIBS)
     AC_CHECK_LIB(Xext, XextAddDisplay, [XEXT_LIBS="-lXext"],
         [MISSING_X="$MISSING_X -lXext"], $XLIBS)
 
+    if test "$MOZ_WIDGET_TOOLKIT" != qt; then
     AC_CHECK_LIB(Xt, XtFree, [ XT_LIBS="-lXt"], [
         unset ac_cv_lib_Xt_XtFree
         AC_CHECK_LIB(ICE, IceFlush, [XT_LIBS="-lICE $XT_LIBS"],, $XT_LIBS $XLIBS)
         AC_CHECK_LIB(SM, SmcCloseConnection, [XT_LIBS="-lSM $XT_LIBS"],, $XT_LIBS $XLIBS)
         AC_CHECK_LIB(Xt, XtFree, [ XT_LIBS="-lXt $XT_LIBS"],
             [MISSING_X="$MISSING_X -lXt"], $X_PRE_LIBS $XT_LIBS $XLIBS)
         ])
+    fi
 
     dnl ========================================================
     dnl = Check for XShm
     dnl ========================================================
     AC_CHECK_LIB(Xext, XShmCreateImage, _HAVE_XSHM_XEXT=1,,
         $XLIBS $XEXT_LIBS)
 
     dnl ========================================================
     dnl = Check for Xss
     dnl ========================================================
     MOZ_CHECK_HEADER(X11/extensions/scrnsaver.h,
         AC_CHECK_LIB(Xss, XScreenSaverQueryInfo,
             [XSS_LIBS="-lXss $XEXT_LIBS $XLIBS"
              AC_DEFINE(HAVE_LIBXSS)],, $XEXT_LIBS $XLIBS))
 
     LDFLAGS="$_SAVE_LDFLAGS"
-fi # $no_x
+fi # $MOZ_X11
 
 AC_SUBST_LIST(XCFLAGS)
 AC_SUBST_LIST(XLDFLAGS)
 AC_SUBST_LIST(XLIBS)
 AC_SUBST_LIST(XEXT_LIBS)
 AC_SUBST_LIST(XT_LIBS)
 AC_SUBST_LIST(XSS_LIBS)
 
@@ -2702,20 +2651,16 @@ dnl are defined in build/autoconf/altopt
 
 dnl ========================================================
 dnl =
 dnl = Check for external package dependencies
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(External Packages)
 
-MOZ_ARG_WITH_STRING(libxul-sdk,
-[  --with-libxul-sdk=PFX   Use the libXUL SDK at <PFX>],
-  AC_MSG_ERROR([--with-libxul-sdk is not supported anymore.]))
-
 case "$OS_TARGET" in
 WINNT|Darwin|Android)
   MOZ_FOLD_LIBS=1
   ;;
 *)
   MOZ_FOLD_LIBS=
   ;;
 esac
@@ -3075,23 +3020,16 @@ if test "$MOZ_IOS"; then
    MOZ_AUTH_EXTENSION=
 fi
 MOZ_RAW=
 MOZ_VORBIS=
 MOZ_TREMOR=
 MOZ_SAMPLE_TYPE_FLOAT32=
 MOZ_SAMPLE_TYPE_S16=
 MOZ_DIRECTSHOW=
-MOZ_WMF=
-if test -n "$MOZ_FMP4"; then
-  MOZ_FMP4=1
-else
-  MOZ_FMP4=
-fi
-MOZ_FFMPEG=
 MOZ_WEBRTC=1
 MOZ_PEERCONNECTION=
 MOZ_SRTP=
 MOZ_WEBRTC_SIGNALING=
 MOZ_WEBRTC_ASSERT_ALWAYS=1
 MOZ_WEBRTC_HARDWARE_AEC_NS=
 MOZ_SCTP=
 MOZ_ANDROID_OMX=
@@ -3125,17 +3063,16 @@ MOZ_UI_LOCALE=en-US
 MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 if test "$MOZ_IOS"; then
    NS_PRINTING=
 fi
-MOZ_PDF_PRINTING=
 MOZ_NO_SMART_CARDS=
 NSS_DISABLE_DBM=
 NECKO_COOKIES=1
 NECKO_PROTOCOLS_DEFAULT="about app data file ftp http res viewsource websocket wyciwyg device"
 if test -n "$MOZ_RTSP"; then
   NECKO_PROTOCOLS_DEFAULT="$NECKO_PROTOCOLS_DEFAULT rtsp"
 fi
 USE_ARM_KUSER=
@@ -3417,201 +3354,84 @@ fi
 
 dnl ========================================================
 dnl =
 dnl = Toolkit Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Toolkit Options)
 
-    dnl ========================================================
-    dnl = Select the default toolkit
-    dnl ========================================================
-    MOZ_ARG_ENABLE_STRING(default-toolkit,
-    [  --enable-default-toolkit=TK
-                          Select default toolkit
-                          Platform specific defaults:
-                            Mac OS X - cairo-cocoa
-                            Win32 - cairo-windows
-                            * - cairo-gtk2
-                            * - cairo-gtk3
-                            * - cairo-qt],
-    [ _DEFAULT_TOOLKIT=$enableval ],
-    [ _DEFAULT_TOOLKIT=$_PLATFORM_DEFAULT_TOOLKIT])
-
-    if test "$_DEFAULT_TOOLKIT" = "cairo-windows" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-gtk3" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-qt" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-uikit" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-android" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-gonk"
-    then
-        dnl nglayout only supports building with one toolkit,
-        dnl so ignore everything after the first comma (",").
-        MOZ_WIDGET_TOOLKIT=`echo "$_DEFAULT_TOOLKIT" | sed -e "s/,.*$//"`
-    else
-        AC_MSG_ERROR([You must specify a default toolkit (perhaps $_PLATFORM_DEFAULT_TOOLKIT).])
-    fi
-
-MOZ_ARG_WITHOUT_BOOL(x,
-[  --without-x              Build without X11],
-    WITHOUT_X11=1)
-
 dnl ========================================================
 dnl = Enable the toolkit as needed                         =
 dnl ========================================================
 
-MOZ_WIDGET_GTK=
-
 case "$MOZ_WIDGET_TOOLKIT" in
 
-cairo-windows)
-    MOZ_WIDGET_TOOLKIT=windows
-    MOZ_PDF_PRINTING=1
-    MOZ_INSTRUMENT_EVENT_LOOP=1
-    ;;
-
-cairo-gtk3)
-    MOZ_WIDGET_TOOLKIT=gtk3
-    MOZ_ENABLE_GTK=1
-    MOZ_ENABLE_GTK3=1
-    MOZ_ENABLE_XREMOTE=1
-    MOZ_GL_DEFAULT_PROVIDER=GLX
-
-    AC_DEFINE(MOZ_X11)
-    MOZ_X11=1
-    USE_FC_FREETYPE=1
-
-    MOZ_WIDGET_GTK=3
-    AC_DEFINE_UNQUOTED(MOZ_WIDGET_GTK,$MOZ_WIDGET_GTK)
-    MOZ_PDF_PRINTING=1
-    MOZ_INSTRUMENT_EVENT_LOOP=1
-    ;;
-
-cairo-gtk2|cairo-gtk2-x11)
-    MOZ_WIDGET_TOOLKIT=gtk2
-    MOZ_ENABLE_GTK=1
-    MOZ_ENABLE_GTK2=1
-    MOZ_ENABLE_XREMOTE=1
-    MOZ_GL_DEFAULT_PROVIDER=GLX
-
-    AC_DEFINE(MOZ_X11)
-    MOZ_X11=1
-    USE_FC_FREETYPE=1
-
-    AC_DEFINE(MOZ_WIDGET_GTK2)
-    MOZ_WIDGET_GTK=2
-    AC_DEFINE_UNQUOTED(MOZ_WIDGET_GTK,$MOZ_WIDGET_GTK)
-    MOZ_PDF_PRINTING=1
-    MOZ_INSTRUMENT_EVENT_LOOP=1
-    ;;
-
-cairo-qt)
-    MOZ_WIDGET_TOOLKIT=qt
+qt)
     MOZ_ENABLE_QT=1
-    if test -z "$WITHOUT_X11"; then
-      MOZ_ENABLE_XREMOTE=1
-      MOZ_GL_DEFAULT_PROVIDER=GLX
-      MOZ_X11=1
-      AC_DEFINE(MOZ_X11)
-      XT_LIBS=
-    fi
-
-    USE_FC_FREETYPE=1
-    AC_DEFINE(MOZ_WIDGET_QT)
-    MOZ_PDF_PRINTING=1
+
     AC_DEFINE(QT_NO_KEYWORDS)
     ;;
 
-cairo-cocoa)
-    MOZ_WIDGET_TOOLKIT=cocoa
-    AC_DEFINE(MOZ_WIDGET_COCOA)
+cocoa)
     LDFLAGS="$LDFLAGS -framework Cocoa -lobjc"
     # Use -Wl as a trick to avoid -framework and framework names from
     # being separated by AC_SUBST_LIST.
     TK_LIBS='-Wl,-framework,CoreLocation -Wl,-framework,QuartzCore -Wl,-framework,Carbon -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,AddressBook -Wl,-framework,OpenGL'
-    TK_CFLAGS="-DNO_X11"
+    TK_CFLAGS=""
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
     MOZ_USER_DIR="Mozilla"
     MOZ_FS_LAYOUT=bundle
-    MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
-cairo-uikit)
-    MOZ_WIDGET_TOOLKIT=uikit
-    AC_DEFINE(MOZ_WIDGET_UIKIT)
+uikit)
     LDFLAGS="$LDFLAGS -framework UIKit -lobjc"
-    TK_CFLAGS="-DNO_X11"
+    TK_CFLAGS=""
     TK_LIBS='-Wl,-framework,Foundation -Wl,-framework,CoreFoundation -Wl,-framework,CoreGraphics -Wl,-framework,CoreText -Wl,-framework,AVFoundation -Wl,-framework,AudioToolbox -Wl,-framework,CoreMedia -Wl,-framework,CoreVideo -Wl,-framework,OpenGLES -Wl,-framework,QuartzCore'
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
     MOZ_USER_DIR="Mozilla"
     MOZ_FS_LAYOUT=bundle
     ;;
 
-cairo-android)
-    AC_DEFINE(MOZ_WIDGET_ANDROID)
-    MOZ_WIDGET_TOOLKIT=android
-    MOZ_PDF_PRINTING=1
-    MOZ_INSTRUMENT_EVENT_LOOP=1
-    ;;
-
-cairo-gonk)
-    AC_DEFINE(MOZ_WIDGET_GONK)
-    AC_DEFINE(MOZ_TOUCH)
-    MOZ_WIDGET_TOOLKIT=gonk
-    MOZ_PDF_PRINTING=1
-    MOZ_TOUCH=1
-    MOZ_INSTRUMENT_EVENT_LOOP=1
+esac
+
+dnl there are a lot of tests on MOZ_ENABLE_GTK below, that are more convenient
+dnl to keep that way than testing against MOZ_WIDGET_TOOLKIT
+case "$MOZ_WIDGET_TOOLKIT" in
+gtk*)
+    MOZ_ENABLE_GTK=1
     ;;
-
 esac
 
-AC_SUBST(MOZ_PDF_PRINTING)
-if test "$MOZ_PDF_PRINTING"; then
-   PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
-   AC_DEFINE(MOZ_PDF_PRINTING)
-fi
-
-if test "$MOZ_ENABLE_XREMOTE"; then
-    AC_DEFINE(MOZ_ENABLE_XREMOTE)
-fi
-
-if test "$MOZ_INSTRUMENT_EVENT_LOOP"; then
-   AC_DEFINE(MOZ_INSTRUMENT_EVENT_LOOP)
-fi
-
 if test "$COMPILE_ENVIRONMENT"; then
-  if test "$MOZ_ENABLE_GTK3"; then
+  if test "$MOZ_WIDGET_TOOLKIT" = gtk3; then
     PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
     MOZ_GTK3_CFLAGS="-I${_topsrcdir}/widget/gtk/compat-gtk3 $MOZ_GTK3_CFLAGS"
     TK_CFLAGS=$MOZ_GTK3_CFLAGS
     TK_LIBS=$MOZ_GTK3_LIBS
     AC_DEFINE_UNQUOTED(GDK_VERSION_MIN_REQUIRED,$GDK_VERSION_MIN_REQUIRED)
     AC_DEFINE_UNQUOTED(GDK_VERSION_MAX_ALLOWED,$GDK_VERSION_MIN_REQUIRED)
     GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32
   fi
-  if test "$MOZ_ENABLE_GTK2"; then
+  if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then
     GLIB_VERSION_MAX_ALLOWED=$GLIB_VERSION_MIN_REQUIRED
   fi
   if test "$MOZ_ENABLE_GTK"; then
     if test "$MOZ_X11"; then
       GDK_PACKAGES=gdk-x11-2.0
     fi
     AC_DEFINE_UNQUOTED(GLIB_VERSION_MIN_REQUIRED,$GLIB_VERSION_MIN_REQUIRED)
     AC_DEFINE_UNQUOTED(GLIB_VERSION_MAX_ALLOWED,$GLIB_VERSION_MAX_ALLOWED)
 
     PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 >= $GLIB_VERSION gobject-2.0 $GDK_PACKAGES)
     MOZ_GTK2_CFLAGS="-I${_topsrcdir}/widget/gtk/compat $MOZ_GTK2_CFLAGS"
   fi
-  if test "$MOZ_ENABLE_GTK2"; then
+  if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then
     TK_CFLAGS=$MOZ_GTK2_CFLAGS
     TK_LIBS=$MOZ_GTK2_LIBS
   fi
 fi # COMPILE_ENVIRONMENT
 
 AC_SUBST(MOZ_FS_LAYOUT)
 
 dnl ========================================================
@@ -3838,33 +3658,26 @@ then
     TK_CFLAGS=$MOZ_QT_CFLAGS
     TK_LIBS=$MOZ_QT_LIBS
 fi
 
 AC_SUBST(GTK_CONFIG)
 AC_SUBST_LIST(TK_CFLAGS)
 AC_SUBST_LIST(TK_LIBS)
 
-AC_SUBST(MOZ_ENABLE_GTK2)
-AC_SUBST(MOZ_ENABLE_GTK3)
-AC_SUBST(MOZ_ENABLE_GTK)
 AC_SUBST(MOZ_ENABLE_QT)
 AC_SUBST(MOZ_ENABLE_QTNETWORK)
 AC_SUBST(MOZ_ENABLE_QMSYSTEM2)
 AC_SUBST(MOZ_ENABLE_QTMOBILITY)
-AC_SUBST(MOZ_ENABLE_XREMOTE)
-AC_SUBST(MOZ_WIDGET_GTK)
 AC_SUBST_LIST(MOZ_QT_CFLAGS)
 AC_SUBST_LIST(MOZ_QT_LIBS)
 
 AC_SUBST(MOC)
 AC_SUBST(RCC)
 
-AC_SUBST(MOZ_X11)
-
 dnl ========================================================
 dnl =
 dnl = Components & Features
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Components and Features)
 
 dnl ========================================================
@@ -3959,17 +3772,17 @@ then
     dnl ========================================================
     MOZ_ARG_DISABLE_BOOL(gio,
     [  --disable-gio           Disable GIO support],
         MOZ_ENABLE_GIO=,
         MOZ_ENABLE_GIO=force)
 
     if test "$MOZ_ENABLE_GIO" -a "$MOZ_ENABLE_GTK"
     then
-        if test "$MOZ_ENABLE_GTK2"
+        if test "$MOZ_WIDGET_TOOLKIT" = gtk2
         then
             PKG_CHECK_MODULES(_GTKCHECK, gtk+-2.0 >= 2.14, ,
                               [AC_MSG_ERROR([* * * Could not find gtk+-2.0 > 2.14. Required for build with gio.])])
         fi
         PKG_CHECK_MODULES(MOZ_GIO, gio-2.0 >= $GIO_VERSION,[
             MOZ_GIO_LIBS=`echo $MOZ_GIO_LIBS | sed 's/-llinc\>//'`
             MOZ_ENABLE_GIO=1
             AC_DEFINE(MOZ_ENABLE_GIO)
@@ -4459,23 +4272,18 @@ AC_CACHE_CHECK([__attribute__ ((aligned 
 if test "${ac_cv_c_attribute_aligned}" != "0"; then
   AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX],
                      [${ac_cv_c_attribute_aligned}],[Maximum supported data alignment])
 fi
 
 dnl ========================================================
 dnl = Apple platform decoder support
 dnl ========================================================
-if test "$MOZ_WIDGET_TOOLKIT" = "cocoa" || test "$MOZ_WIDGET_TOOLKIT" = "uikit"; then
-  MOZ_APPLEMEDIA=1
-fi
-
 if test "$COMPILE_ENVIRONMENT"; then
 if test -n "$MOZ_APPLEMEDIA"; then
-  AC_DEFINE(MOZ_APPLEMEDIA)
   # hack in frameworks for fmp4 - see bug 1029974
   # We load VideoToolbox and CoreMedia dynamically, so they don't appear here.
   LDFLAGS="$LDFLAGS -framework AudioToolbox"
   dnl Verify CoreMedia is available.
   AC_CHECK_HEADER([CoreMedia/CoreMedia.h], [],
     [AC_MSG_ERROR([MacOS X 10.7 SDK or later is required])])
 fi
 fi # COMPILE_ENVIRONMENT
@@ -4493,124 +4301,29 @@ MOZ_ARG_DISABLE_BOOL(directshow,
     MOZ_DIRECTSHOW=,
     MOZ_DIRECTSHOW=1)
 
 if test -n "$MOZ_DIRECTSHOW"; then
     AC_DEFINE(MOZ_DIRECTSHOW)
 fi;
 
 dnl ========================================================
-dnl = Windows Media Foundation support
-dnl ========================================================
-if test "$OS_ARCH" = "WINNT"; then
-    dnl Enable Windows Media Foundation support by default.
-    dnl Note our minimum SDK version is Windows 7 SDK, so we are (currently)
-    dnl guaranteed to have a recent-enough SDK to build WMF.
-    MOZ_WMF=1
-fi
-
-MOZ_ARG_DISABLE_BOOL(wmf,
-[  --disable-wmf  Disable support for Windows Media Foundation],
-    MOZ_WMF=,
-    MOZ_WMF=1)
-
-if test -n "$MOZ_WMF"; then
-    AC_DEFINE(MOZ_WMF)
-fi;
-
-dnl ========================================================
-dnl FFmpeg H264/AAC Decoding Support
-dnl ========================================================
-case "$OS_TARGET" in
-WINNT|Android)
-    ;;
-*)
-    MOZ_FFMPEG=1
-    ;;
-esac
-
-MOZ_ARG_DISABLE_BOOL(ffmpeg,
-[  --disable-ffmpeg         Disable FFmpeg for fragmented H264/AAC decoding],
-    MOZ_FFMPEG=,
-    MOZ_FFMPEG=1
-)
-
-if test -n "$MOZ_FFMPEG"; then
-    AC_DEFINE(MOZ_FFMPEG)
-fi;
-
-dnl ========================================================
 dnl = Built-in fragmented MP4 support.
 dnl ========================================================
 
-if test "$OS_TARGET" = Android -a -z "$gonkdir"; then
-    MOZ_FMP4=1
-fi
-
-if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG" -o -n "$MOZ_APPLEMEDIA"; then
-    dnl Enable fragmented MP4 parser on Windows by default.
-    dnl We will also need to enable it on other platforms as we implement
-    dnl platform decoder support there too.
-    MOZ_FMP4=1
-fi
-
-MOZ_ARG_DISABLE_BOOL(fmp4,
-[  --disable-fmp4  Disable support for in built Fragmented MP4 parsing],
-    MOZ_FMP4=,
-    MOZ_FMP4=1)
-
-if test -n "$MOZ_FFMPEG" -a -z "$MOZ_FMP4"; then
-    AC_MSG_ERROR([Fragmented MP4 support must be enabled if using FFMPEG])
-fi
-
-if test -n "$MOZ_FMP4"; then
-    AC_DEFINE(MOZ_FMP4)
-    MOZ_EME=1
-fi;
-
 if test x"$MOZ_WIDGET_TOOLKIT" = x"gonk" -a -n "$MOZ_FMP4" -a -n "$ANDROID_VERSION"; then
     # we now know for sure that $ANDROID_VERSION is not an empty string!
     if test "$ANDROID_VERSION" -ge "18"; then
         MOZ_GONK_MEDIACODEC=1
         AC_SUBST(MOZ_GONK_MEDIACODEC)
     fi
 fi
 
 
 dnl ========================================================
-dnl = EME support
-dnl ========================================================
-
-MOZ_ARG_ENABLE_STRING(eme,
-[  --enable-eme[=adobe]  Enable support for Encrypted Media Extensions  ],
-    MOZ_EME_ARGS=$enableval)
-
-if test "$MOZ_EME_ARGS"; then
-    if test "$MOZ_EME_ARGS" = "no"; then
-        dnl EME explicitly disabled with --disable-eme
-        MOZ_EME=
-    elif test "$MOZ_EME_ARGS" = "yes"; then
-        dnl EME explicitly enabled with --enable-eme
-        MOZ_EME=1
-    else
-        dnl EME explicitly enabled with --enable-eme=<args>
-        MOZ_EME=1
-        MOZ_EME_MODULES=`echo $MOZ_EME_ARGS | sed -e 's/,/ /g'`
-    fi
-fi
-
-AC_SUBST_SET(MOZ_EME_MODULES)
-if test -n "$MOZ_EME"; then
-    if test -z "$MOZ_FMP4"; then
-        AC_MSG_ERROR([Encrypted Media Extension support requires Fragmented MP4 support])
-    fi
-    AC_DEFINE(MOZ_EME)
-fi
-
-dnl ========================================================
 dnl = Enable media plugin support
 dnl ========================================================
 if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
   dnl Enable support on android by default
   MOZ_ANDROID_OMX=1
 fi
 
 MOZ_ARG_ENABLE_BOOL(android-omx,
@@ -6153,34 +5866,16 @@ dnl = Disable zipwriter
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(zipwriter,
 [  --disable-zipwriter     Disable zipwriter component],
     MOZ_ZIPWRITER=,
     MOZ_ZIPWRITER=1 )
 AC_SUBST(MOZ_ZIPWRITER)
 
 dnl ========================================================
-dnl GL provider
-dnl ========================================================
-MOZ_GL_PROVIDER=
-MOZ_ARG_WITH_STRING(gl-provider,
-[  --with-gl-provider=ID
-                          Set GL provider backend type],
-[ val=`echo $withval`
-    MOZ_GL_PROVIDER="$val"])
-
-if test -n "$MOZ_GL_PROVIDER"; then
-MOZ_GL_DEFAULT_PROVIDER=$MOZ_GL_PROVIDER
-AC_SUBST(MOZ_GL_PROVIDER)
-AC_DEFINE_UNQUOTED(MOZ_GL_PROVIDER, GLContextProvider$MOZ_GL_PROVIDER)
-fi
-AC_SUBST(MOZ_GL_DEFAULT_PROVIDER)
-AC_DEFINE_UNQUOTED(GL_PROVIDER_$MOZ_GL_DEFAULT_PROVIDER)
-
-dnl ========================================================
 dnl = faststripe theme
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(faststripe,
 [  --enable-faststripe     Use faststripe theme],
     MOZ_THEME_FASTSTRIPE=1,
     MOZ_THEME_FASTSTRIPE= )
 AC_SUBST(MOZ_THEME_FASTSTRIPE)
 
@@ -7460,17 +7155,16 @@ if test "$MOZ_TREE_CAIRO"; then
     fi
     AC_SUBST(MOZ_ENABLE_CAIRO_FT)
     AC_SUBST(MOZ_ENABLE_DWRITE_FONT)
     AC_SUBST(MOZ_ENABLE_D2D_SURFACE)
     AC_SUBST(MOZ_ENABLE_D3D9_LAYER)
     AC_SUBST(MOZ_ENABLE_D3D10_LAYER)
 
     AC_SUBST(PS_SURFACE_FEATURE)
-    AC_SUBST(PDF_SURFACE_FEATURE)
     AC_SUBST(SVG_SURFACE_FEATURE)
     AC_SUBST(XLIB_SURFACE_FEATURE)
     AC_SUBST(XLIB_XRENDER_SURFACE_FEATURE)
     AC_SUBST(QUARTZ_SURFACE_FEATURE)
     AC_SUBST(QUARTZ_IMAGE_SURFACE_FEATURE)
     AC_SUBST(WIN32_SURFACE_FEATURE)
     AC_SUBST(OS2_SURFACE_FEATURE)
     AC_SUBST(DIRECTFB_SURFACE_FEATURE)
@@ -7741,17 +7435,16 @@ AC_SUBST(AS_DASH_C_FLAG)
 AC_SUBST(LD)
 AC_SUBST(RC)
 AC_SUBST(RCFLAGS)
 AC_SUBST(MC)
 AC_SUBST(WINDRES)
 AC_SUBST(IMPLIB)
 AC_SUBST(FILTER)
 AC_SUBST(BIN_FLAGS)
-AC_SUBST(MOZ_WIDGET_TOOLKIT)
 AC_SUBST(MOZ_AUTH_EXTENSION)
 AC_SUBST(MOZ_PREF_EXTENSIONS)
 AC_SUBST(MOZ_DEBUG)
 AC_SUBST(MOZ_DEBUG_SYMBOLS)
 AC_SUBST(MOZ_DEBUG_LDFLAGS)
 AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST_SET(MOZ_EXTENSIONS)
 AC_SUBST(MOZ_ENABLE_PROFILER_SPS)
@@ -7826,18 +7519,16 @@ AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(STRIP_FLAGS)
 AC_SUBST(USE_ELF_HACK)
 AC_SUBST(INCREMENTAL_LINKER)
 AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
 AC_SUBST(MOZ_COMPONENT_NSPR_LIBS)
 
 AC_SUBST(MOZ_FIX_LINK_PATHS)
 
-AC_SUBST(USE_DEPENDENT_LIBS)
-
 AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
 AC_SUBST(MOZ_LINKER_EXTRACT)
 
 AC_SUBST(MOZ_ADDON_SIGNING)
 AC_SUBST(MOZ_REQUIRE_SIGNING)
 
 if test -n "$MOZ_BINARY_EXTENSIONS"; then
   AC_DEFINE(MOZ_BINARY_EXTENSIONS)
@@ -8168,35 +7859,29 @@ AC_SUBST(CC_VERSION)
 AC_SUBST(CXX_VERSION)
 AC_SUBST(MSMANIFEST_TOOL)
 AC_SUBST(NS_ENABLE_TSF)
 AC_SUBST(WIN32_CONSOLE_EXE_LDFLAGS)
 AC_SUBST(WIN32_GUI_EXE_LDFLAGS)
 
 AC_SUBST(MOZ_VORBIS)
 AC_SUBST(MOZ_TREMOR)
-AC_SUBST(MOZ_WMF)
-AC_SUBST(MOZ_FFMPEG)
 AC_SUBST(MOZ_FFVPX)
 AC_SUBST_LIST(FFVPX_ASFLAGS)
-AC_SUBST(MOZ_FMP4)
-AC_SUBST(MOZ_EME)
 AC_SUBST(MOZ_DIRECTSHOW)
 AC_SUBST(MOZ_ANDROID_OMX)
-AC_SUBST(MOZ_APPLEMEDIA)
 AC_SUBST(MOZ_OMX_PLUGIN)
 AC_SUBST(MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE)
 AC_SUBST(MOZ_VPX_ERROR_CONCEALMENT)
 AC_SUBST(VPX_USE_YASM)
 AC_SUBST_LIST(VPX_ASFLAGS)
 AC_SUBST(VPX_AS_CONVERSION)
 AC_SUBST(VPX_X86_ASM)
 AC_SUBST(VPX_ARM_ASM)
 AC_SUBST(VPX_NEED_OBJ_INT_EXTRACT)
-AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
 AC_SUBST(MOZ_CODE_COVERAGE)
 AC_SUBST(LIBJPEG_TURBO_USE_YASM)
 AC_SUBST_LIST(LIBJPEG_TURBO_ASFLAGS)
 AC_SUBST(MOZ_LIBAV_FFT)
 AC_SUBST_LIST(LIBAV_FFT_ASFLAGS)
 AC_SUBST(MOZ_DEVTOOLS)
 
 AC_SUBST(MOZ_PACKAGE_JSSHELL)
@@ -8214,19 +7899,16 @@ AC_SUBST(JS_BINARY)
 
 AC_SUBST(NSS_EXTRA_SYMBOLS_FILE)
 
 if test -n "$COMPILE_ENVIRONMENT"; then
 AC_CHECK_FUNCS(posix_fadvise posix_fallocate)
 
 dnl Check for missing components
 if test "$MOZ_X11"; then
-    if test "$WITHOUT_X11"; then
-        AC_MSG_ERROR([--without-x specified and MOZ_X11 still defined])
-    fi
     dnl ====================================================
     dnl = Check if X headers exist
     dnl ====================================================
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS $XCFLAGS"
     AC_TRY_COMPILE([
         #include <stdio.h>
         #include <stdlib.h>
--- a/python/mozbuild/mozbuild/configure/options.py
+++ b/python/mozbuild/mozbuild/configure/options.py
@@ -214,20 +214,16 @@ class Option(object):
             if has_choices and not all(d in choices for d in self.default):
                 raise InvalidOptionError(
                     'The `default` value must be one of %s' %
                     ', '.join("'%s'" % c for c in choices))
         elif has_choices:
             maxargs = self.maxargs
             if len(choices) < maxargs and maxargs != sys.maxint:
                 raise InvalidOptionError('Not enough `choices` for `nargs`')
-            if self.minargs == 0:
-                raise InvalidOptionError(
-                    '%s is not a valid `nargs` when `choices` are given'
-                    % str(nargs))
         self.choices = choices
         self.help = help
 
     @staticmethod
     def split_option(option):
         '''Split a flag or variable into a prefix, a name and values
 
         Variables come in the form NAME=values (no prefix).
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -36,16 +36,17 @@ from mozbuild.base import (
     ObjdirMismatchException,
 )
 
 from mozpack.manifests import (
     InstallManifest,
 )
 
 from mozbuild.backend import backends
+from mozbuild.shellutil import quote as shell_quote
 
 
 BUILD_WHAT_HELP = '''
 What to build. Can be a top-level make target or a relative directory. If
 multiple options are provided, they will be built serially. Takes dependency
 information from `topsrcdir/build/dumbmake-dependencies` to build additional
 targets as needed. BUILDING ONLY PARTS OF THE TREE CAN RESULT IN BAD TREE
 STATE. USE AT YOUR OWN RISK.
@@ -546,23 +547,27 @@ class Build(MachCommandBase):
                 # Ignore Exceptions in case we can't find config.status (such
                 # as when doing OSX Universal builds)
                 pass
 
         return status
 
     @Command('configure', category='build',
         description='Configure the tree (run configure and config.status).')
-    def configure(self):
+    @CommandArgument('options', default=None, nargs=argparse.REMAINDER,
+                     help='Configure options')
+    def configure(self, options=None):
         def on_line(line):
             self.log(logging.INFO, 'build_output', {'line': line}, '{line}')
 
+        options = ' '.join(shell_quote(o) for o in options or ())
         status = self._run_make(srcdir=True, filename='client.mk',
             target='configure', line_handler=on_line, log=False,
-            print_directory=False, allow_parallel=False, ensure_exit_code=False)
+            print_directory=False, allow_parallel=False, ensure_exit_code=False,
+            append_env={b'CONFIGURE_ARGS': options.encode('utf-8')})
 
         if not status:
             print('Configure complete!')
             print('Be sure to run |mach build| to pick up any changes');
 
         return status
 
     @Command('resource-usage', category='post-build',
--- a/python/mozbuild/mozbuild/test/configure/test_options.py
+++ b/python/mozbuild/mozbuild/test/configure/test_options.py
@@ -154,28 +154,19 @@ class TestOption(unittest.TestCase):
             self.assertEquals(opt.option,
                               option.replace('-enable-', '-disable-')
                                     .replace('-with-', '-without-'))
 
         self.assertEquals(Option(env='FOO').option, 'FOO')
 
     def test_option_choices(self):
         with self.assertRaises(InvalidOptionError):
-            Option('--option', nargs=0, choices=('a', 'b'))
-
-        with self.assertRaises(InvalidOptionError):
             Option('--option', nargs=3, choices=('a', 'b'))
 
         with self.assertRaises(InvalidOptionError):
-            Option('--option', nargs='?', choices=('a', 'b'))
-
-        with self.assertRaises(InvalidOptionError):
-            Option('--option', nargs='*', choices=('a', 'b'))
-
-        with self.assertRaises(InvalidOptionError):
             Option('--without-option', nargs=1, choices=('a', 'b'))
 
         with self.assertRaises(InvalidOptionError):
             Option('--without-option', nargs='+', choices=('a', 'b'))
 
         with self.assertRaises(InvalidOptionError):
             Option('--without-option', default='c', choices=('a', 'b'))
 
--- a/security/certverifier/ExtendedValidation.cpp
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -643,16 +643,30 @@ static struct nsMyTrustedEVInfo myTruste
       0x83, 0xA7, 0xD4, 0xA3, 0x2D, 0xB7, 0x68, 0xC4, 0x40, 0x8E },
     "MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBT"
     "LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAg"
     "BgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=",
     "BETA",
     nullptr
   },
   {
+    // CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL
+    "1.2.616.1.113527.2.5.1.1",
+    "Certum EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xB6, 0x76, 0xF2, 0xED, 0xDA, 0xE8, 0x77, 0x5C, 0xD3, 0x6C, 0xB0,