Merge m-c to inbound. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 26 Aug 2015 14:33:07 -0400
changeset 292094 13cd9ed4b792b79ab7b18d3b008482c6078382d7
parent 292093 4d45f860006cbfac37911d101b847ee176254067 (current diff)
parent 291998 fea87cbeaa6b64510dff835549ed906fe405d558 (diff)
child 292095 0d8d4b4178e4ae9777133cc78e26947c11429fb7
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound. a=merge
browser/base/content/test/plugins/browser_pluginplaypreview.js
browser/base/content/test/plugins/browser_pluginplaypreview2.js
browser/base/content/test/plugins/browser_pluginplaypreview3.js
browser/base/content/test/plugins/plugin_test_w_src.html
dom/plugins/base/nsPluginPlayPreviewInfo.cpp
dom/plugins/base/nsPluginPlayPreviewInfo.h
testing/web-platform/meta/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html.ini
testing/web-platform/mozilla/meta/service-workers/service-worker/registration.https.html.ini
toolkit/themes/osx/global/toolbar/toolbar-background-inactive.png
toolkit/themes/osx/global/toolbar/toolbar-background.gif
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -113,43 +113,43 @@ nsCoreUtils::DispatchClickEvent(nsITreeB
   DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY,
                      tcContent, tcFrame, presShell, rootWidget);
 
   DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY,
                      tcContent, tcFrame, presShell, rootWidget);
 }
 
 void
-nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
+nsCoreUtils::DispatchMouseEvent(EventMessage aMessage, int32_t aX, int32_t aY,
                                 nsIContent *aContent, nsIFrame *aFrame,
                                 nsIPresShell *aPresShell, nsIWidget *aRootWidget)
 {
-  WidgetMouseEvent event(true, aEventType, aRootWidget,
+  WidgetMouseEvent event(true, aMessage, aRootWidget,
                          WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
 
   event.refPoint = LayoutDeviceIntPoint(aX, aY);
 
   event.clickCount = 1;
   event.button = WidgetMouseEvent::eLeftButton;
   event.time = PR_IntervalNow();
   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
 
   nsEventStatus status = nsEventStatus_eIgnore;
   aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
 }
 
 void
-nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
+nsCoreUtils::DispatchTouchEvent(EventMessage aMessage, int32_t aX, int32_t aY,
                                 nsIContent* aContent, nsIFrame* aFrame,
                                 nsIPresShell* aPresShell, nsIWidget* aRootWidget)
 {
   if (!dom::TouchEvent::PrefEnabled())
     return;
 
-  WidgetTouchEvent event(true, aEventType, aRootWidget);
+  WidgetTouchEvent event(true, aMessage, aRootWidget);
 
   event.time = PR_IntervalNow();
 
   // XXX: Touch has an identifier of -1 to hint that it is synthesized.
   nsRefPtr<dom::Touch> t = new dom::Touch(-1, LayoutDeviceIntPoint(aX, aY),
                                           nsIntPoint(1, 1), 0.0f, 1.0f);
   t->SetTarget(aContent);
   event.touches.AppendElement(t);
--- a/accessible/base/nsCoreUtils.h
+++ b/accessible/base/nsCoreUtils.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsCoreUtils_h_
 #define nsCoreUtils_h_
 
+#include "mozilla/EventForwards.h"
 #include "nsIContent.h"
 #include "nsIDocument.h" // for GetShell()
 #include "nsIPresShell.h"
 
 #include "nsPoint.h"
 #include "nsTArray.h"
 
 class nsRange;
@@ -44,40 +45,42 @@ public:
    */
   static void DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
                                  int32_t aRowIndex, nsITreeColumn *aColumn,
                                  const nsAString& aPseudoElt = EmptyString());
 
   /**
    * Send mouse event to the given element.
    *
-   * @param aEventType   [in] an event type (see BasicEvents.h for constants)
+   * @param aMessage     [in] an event message (see EventForwards.h)
    * @param aX           [in] x coordinate in dev pixels
    * @param aY           [in] y coordinate in dev pixels
    * @param aContent     [in] the element
    * @param aFrame       [in] frame of the element
    * @param aPresShell   [in] the presshell for the element
    * @param aRootWidget  [in] the root widget of the element
    */
-  static void DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
+  static void DispatchMouseEvent(mozilla::EventMessage aMessage,
+                                 int32_t aX, int32_t aY,
                                  nsIContent *aContent, nsIFrame *aFrame,
                                  nsIPresShell *aPresShell, nsIWidget *aRootWidget);
 
   /**
    * Send a touch event with a single touch point to the given element.
    *
-   * @param aEventType   [in] an event type (see BasicEvents.h for constants)
+   * @param aMessage     [in] an event message (see EventForwards.h)
    * @param aX           [in] x coordinate in dev pixels
    * @param aY           [in] y coordinate in dev pixels
    * @param aContent     [in] the element
    * @param aFrame       [in] frame of the element
    * @param aPresShell   [in] the presshell for the element
    * @param aRootWidget  [in] the root widget of the element
    */
-  static void DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
+  static void DispatchTouchEvent(mozilla::EventMessage aMessage,
+                                 int32_t aX, int32_t aY,
                                  nsIContent* aContent, nsIFrame* aFrame,
                                  nsIPresShell* aPresShell, nsIWidget* aRootWidget);
 
   /**
    * Return an accesskey registered on the given element by
    * EventStateManager or 0 if there is no registered accesskey.
    *
    * @param aContent - the given element.
--- a/accessible/windows/ia2/moz.build
+++ b/accessible/windows/ia2/moz.build
@@ -42,11 +42,14 @@ LOCAL_INCLUDES += [
     '/accessible/windows',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -57,9 +57,12 @@ LOCAL_INCLUDES += [
     '/accessible/xul',
     '/dom/base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
--- a/accessible/windows/sdn/moz.build
+++ b/accessible/windows/sdn/moz.build
@@ -16,9 +16,12 @@ LOCAL_INCLUDES += [
     '/accessible/html',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
--- a/b2g/app/moz.build
+++ b/b2g/app/moz.build
@@ -70,16 +70,19 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
 
 DISABLE_STL_WRAPPING = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     OS_LIBS += [
         'version',
     ]
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 JS_PREFERENCE_FILES += [
     'b2g.js',
 ]
 
 DIST_FILES += [
   'ua-update.json.in',
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -79,9 +79,12 @@ DISABLE_STL_WRAPPING = True
 if CONFIG['MOZ_LINKER']:
     OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
 if CONFIG['HAVE_CLOCK_MONOTONIC']:
     OS_LIBS += CONFIG['REALTIME_LIBS']
 
 JAR_MANIFESTS += ['jar.mn']
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7561,16 +7561,26 @@ var TabContextMenu = {
     let bookmarkAllTabs = document.getElementById("context_bookmarkAllTabs");
     bookmarkAllTabs.hidden = this.contextTab.pinned;
     if (!bookmarkAllTabs.hidden)
       PlacesCommandHook.updateBookmarkAllTabsCommand();
 
     // Hide "Move to Group" if it's a pinned tab.
     document.getElementById("context_tabViewMenu").hidden =
       (this.contextTab.pinned || !TabView.firstUseExperienced);
+
+    // Adjust the state of the toggle mute menu item.
+    let toggleMute = document.getElementById("context_toggleMuteTab");
+    if (this.contextTab.hasAttribute("muted")) {
+      toggleMute.label = gNavigatorBundle.getString("unmuteTab.label");
+      toggleMute.accessKey = gNavigatorBundle.getString("unmuteTab.accesskey");
+    } else {
+      toggleMute.label = gNavigatorBundle.getString("muteTab.label");
+      toggleMute.accessKey = gNavigatorBundle.getString("muteTab.accesskey");
+    }
   }
 };
 
 XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
                                   "resource:///modules/devtools/gDevTools.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "gDevToolsBrowser",
                                   "resource:///modules/devtools/gDevTools.jsm");
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -78,16 +78,17 @@
 #undef FULL_BROWSER_WINDOW
 
   <popupset id="mainPopupSet">
     <menupopup id="tabContextMenu"
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
       <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
+      <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/>
       <menuseparator/>
       <menuitem id="context_pinTab" label="&pinTab.label;"
                 accesskey="&pinTab.accesskey;"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true"
                 accesskey="&unpinTab.accesskey;"
                 oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
       <menu id="context_tabViewMenu" label="&moveToGroup.label;"
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -71,16 +71,37 @@ function* test_mute_tab(tab, icon, expec
 }
 
 function get_tab_attributes(tab) {
   const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
   let {attributes} = JSON.parse(ss.getTabState(tab));
   return attributes;
 }
 
+function* test_muting_using_menu(tab, expectMuted) {
+  // Show the popup menu
+  let contextMenu = document.getElementById("tabContextMenu");
+  let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(tab, {type: "contextmenu", button: 2});
+  yield popupShownPromise;
+
+  // Check the menu
+  let expectedLabel = expectMuted ? "Unmute Tab" : "Mute Tab";
+  let toggleMute = document.getElementById("context_toggleMuteTab");
+  is(toggleMute.label, expectedLabel, "Correct label expected");
+  is(toggleMute.accessKey, "M", "Correct accessKey expected");
+
+  // Click on the menu and wait for the tab to be muted.
+  let mutedPromise = get_wait_for_mute_promise(tab, !expectMuted);
+  let popupHiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
+  EventUtils.synthesizeMouseAtCenter(toggleMute, {});
+  yield popupHiddenPromise;
+  yield mutedPromise;
+}
+
 function* test_playing_icon_on_tab(tab, browser, isPinned) {
   let icon = document.getAnonymousElementByAttribute(tab, "anonid",
                                                      isPinned ? "overlay-icon" : "soundplaying-icon");
 
   yield ContentTask.spawn(browser, {}, function* () {
     let audio = content.document.querySelector("audio");
     audio.play();
   });
@@ -115,16 +136,22 @@ function* test_playing_icon_on_tab(tab, 
      !tab.hasAttribute("soundplaying"), "Tab should still be muted but not playing");
 
   yield test_tooltip(icon, "Unmute tab");
 
   yield test_mute_tab(tab, icon, false);
 
   ok(!tab.hasAttribute("muted") &&
      !tab.hasAttribute("soundplaying"), "Tab should not be be muted or playing");
+
+  // Make sure it's possible to mute using the context menu.
+  yield test_muting_using_menu(tab, false);
+
+  // Make sure it's possible to unmute using the context menu.
+  yield test_muting_using_menu(tab, true);
 }
 
 function* test_swapped_browser(oldTab, newBrowser, isPlaying) {
   ok(oldTab.hasAttribute("muted"), "Expected the correct muted attribute on the old tab");
   is(oldTab.hasAttribute("soundplaying"), isPlaying, "Expected the correct soundplaying attribute on the old tab");
 
   let newTab = gBrowser.getTabForBrowser(newBrowser);
   let AttrChangePromise = BrowserTestUtils.waitForEvent(newTab, "TabAttrModified", false, event => {
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -29,17 +29,16 @@ support-files =
   plugin_overlayed.html
   plugin_positioned.html
   plugin_small.html
   plugin_small_2.html
   plugin_syncRemoved.html
   plugin_test.html
   plugin_test2.html
   plugin_test3.html
-  plugin_test_w_src.html
   plugin_two_types.html
   plugin_unknown.html
   plugin_crashCommentAndURL.html
   plugin_zoom.html
 
 [browser_bug743421.js]
 [browser_bug744745.js]
 [browser_bug787619.js]
@@ -71,17 +70,11 @@ skip-if = (os == 'win' && os_version == 
 [browser_plugin_reloading.js]
 [browser_blocklist_content.js]
 skip-if = !e10s
 [browser_globalplugin_crashinfobar.js]
 skip-if = !crashreporter
 [browser_pluginCrashCommentAndURL.js]
 skip-if = !crashreporter
 [browser_pageInfo_plugins.js]
-[browser_pluginplaypreview.js]
-skip-if = e10s # bug 1148827
-[browser_pluginplaypreview2.js]
-skip-if = e10s # bug 1148827
-[browser_pluginplaypreview3.js]
-skip-if = e10s # bug 1148827
 [browser_pluginCrashReportNonDeterminism.js]
 skip-if = !crashreporter || os == 'linux' # Bug 1152811
 
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_pluginplaypreview.js
+++ /dev/null
@@ -1,317 +0,0 @@
-var rootDir = getRootDirectory(gTestPath);
-const gTestRoot = rootDir;
-
-var gTestBrowser = null;
-var gNextTest = null;
-var gNextTestSkip = 0;
-var gPlayPreviewPluginActualEvents = 0;
-var gPlayPreviewPluginExpectedEvents = 1;
-
-var gPlayPreviewRegistration = null;
-
-function registerPlayPreview(mimeType, targetUrl) {
-
-  function StreamConverterFactory() {}
-  StreamConverterFactory.prototype = {
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
-    _targetConstructor: null,
-
-    register: function register(targetConstructor) {
-      this._targetConstructor = targetConstructor;
-      var proto = targetConstructor.prototype;
-      var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-      registrar.registerFactory(proto.classID, proto.classDescription,
-                                proto.contractID, this);
-    },
-
-    unregister: function unregister() {
-      var proto = this._targetConstructor.prototype;
-      var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-      registrar.unregisterFactory(proto.classID, this);
-      this._targetConstructor = null;
-    },
-
-    // nsIFactory
-    createInstance: function createInstance(aOuter, iid) {
-      if (aOuter !== null)
-        throw Cr.NS_ERROR_NO_AGGREGATION;
-      return (new (this._targetConstructor)).QueryInterface(iid);
-    },
-
-    // nsIFactory
-    lockFactory: function lockFactory(lock) {
-      // No longer used as of gecko 1.7.
-      throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-    }
-  };
-
-  function OverlayStreamConverter() {}
-  OverlayStreamConverter.prototype = {
-    QueryInterface: XPCOMUtils.generateQI([
-        Ci.nsISupports,
-        Ci.nsIStreamConverter,
-        Ci.nsIStreamListener,
-        Ci.nsIRequestObserver
-    ]),
-
-    classID: Components.ID('{4c6030f7-e20a-264f-0f9b-ada3a9e97384}'),
-    classDescription: 'overlay-test-data Component',
-    contractID: '@mozilla.org/streamconv;1?from=application/x-moz-playpreview&to=*/*',
-
-    // nsIStreamConverter::convert
-    convert: function(aFromStream, aFromType, aToType, aCtxt) {
-      throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-    },
-
-    // nsIStreamConverter::asyncConvertData
-    asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
-      var isValidRequest = false;
-      try {
-        var request = aCtxt;
-        request.QueryInterface(Ci.nsIChannel);
-        var spec = request.URI.spec;
-        var expectedSpec = 'data:application/x-moz-playpreview;,' + mimeType;
-        isValidRequest = (spec == expectedSpec);
-      } catch (e) { }
-      if (!isValidRequest)
-        throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-
-      // Store the listener passed to us
-      this.listener = aListener;
-    },
-
-    // nsIStreamListener::onDataAvailable
-    onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
-      // Do nothing since all the data loading is handled by the viewer.
-      ok(false, "onDataAvailable should not be called");
-    },
-
-    // nsIRequestObserver::onStartRequest
-    onStartRequest: function(aRequest, aContext) {
-
-      // Setup the request so we can use it below.
-      aRequest.QueryInterface(Ci.nsIChannel);
-      // Cancel the request so the viewer can handle it.
-      aRequest.cancel(Cr.NS_BINDING_ABORTED);
-
-      // Create a new channel that is viewer loaded as a resource.
-      var ioService = Services.io;
-      var channel = ioService.newChannel2(targetUrl,
-                                          null,
-                                          null,
-                                          null,      // aLoadingNode
-                                          Services.scriptSecurityManager.getSystemPrincipal(),
-                                          null,      // aTriggeringPrincipal
-                                          Ci.nsILoadInfo.SEC_NORMAL,
-                                          Ci.nsIContentPolicy.TYPE_OTHER);
-      channel.asyncOpen(this.listener, aContext);
-    },
-
-    // nsIRequestObserver::onStopRequest
-    onStopRequest: function(aRequest, aContext, aStatusCode) {
-      // Do nothing.
-    }
-  };
-
-  var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-  ph.registerPlayPreviewMimeType(mimeType, true); // ignoring CTP rules
-
-  var factory = new StreamConverterFactory();
-  factory.register(OverlayStreamConverter);
-
-  return (gPlayPreviewRegistration = {
-    unregister: function() {
-      ph.unregisterPlayPreviewMimeType(mimeType);
-      factory.unregister();
-      gPlayPreviewRegistration = null;
-    }
-  });
-}
-
-function unregisterPlayPreview() {
-  gPlayPreviewRegistration.unregister();
-}
-
-Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-
-function test() {
-  waitForExplicitFinish();
-  registerCleanupFunction(function() {
-    if (gPlayPreviewRegistration)
-      gPlayPreviewRegistration.unregister();
-    Services.prefs.clearUserPref("plugins.click_to_play");
-  });
-
-  var newTab = gBrowser.addTab();
-  gBrowser.selectedTab = newTab;
-  gTestBrowser = gBrowser.selectedBrowser;
-  gTestBrowser.addEventListener("load", pageLoad, true);
-  gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
-
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
-  registerPlayPreview('application/x-test', 'about:');
-  prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
-}
-
-function finishTest() {
-  gTestBrowser.removeEventListener("load", pageLoad, true);
-  gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
-  gBrowser.removeCurrentTab();
-  window.focus();
-  finish();
-}
-
-function handleBindingAttached(evt) {
-  if (evt.target instanceof Ci.nsIObjectLoadingContent &&
-      evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
-    gPlayPreviewPluginActualEvents++;
-}
-
-function pageLoad() {
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we then go on to test the states
-
-  // iframe might triggers load event as well, making sure we skip some to let
-  // all iframes on the page be loaded as well
-  if (gNextTestSkip) {
-    gNextTestSkip--;
-    return;
-  }
-  executeSoon(gNextTest);
-}
-
-function prepareTest(nextTest, url, skip) {
-  gNextTest = nextTest;
-  gNextTestSkip = skip;
-  gTestBrowser.contentWindow.location = url;
-}
-
-// Tests a page with normal play preview registration (1/2)
-function test1a() {
-  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
-  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
-
-  var pluginInfo = getTestPlugin();
-  ok(pluginInfo, "Should have a test plugin");
-
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
-
-  var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
-  ok(overlay, "Test 1a, the overlay div is expected");
-
-  var iframe = overlay.getElementsByClassName("previewPluginContentFrame")[0];
-  ok(iframe && iframe.localName == "iframe", "Test 1a, the overlay iframe is expected");
-  var iframeHref = iframe.contentWindow.location.href;
-  ok(iframeHref == "about:", "Test 1a, the overlay about: content is expected");
-
-  var rect = iframe.getBoundingClientRect();
-  ok(rect.width == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being replaced by actual plugin");
-  ok(rect.height == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being replaced by actual plugin");
-
-  var e = overlay.ownerDocument.createEvent("CustomEvent");
-  e.initCustomEvent("MozPlayPlugin", true, true, null);
-  overlay.dispatchEvent(e);
-  var condition = function() objLoadingContent.activated;
-  waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin to stop play preview");
-}
-
-// Tests that activating via MozPlayPlugin through the notification works (part 2/2)
-function test1b() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
-
-  is(gPlayPreviewPluginActualEvents, gPlayPreviewPluginExpectedEvents,
-     "There should be exactly one PluginPlayPreview event");
-
-  unregisterPlayPreview();
-
-  prepareTest(test2, gTestRoot + "plugin_test.html");
-}
-
-// Tests a page with a working plugin in it -- the mime type was just unregistered.
-function test2() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 2, Plugin should be activated");
-
-  registerPlayPreview('application/x-unknown', 'about:');
-
-  prepareTest(test3, gTestRoot + "plugin_test.html");
-}
-
-// Tests a page with a working plugin in it -- diffent play preview type is reserved.
-function test3() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 3, Plugin should be activated");
-
-  unregisterPlayPreview();
-
-  registerPlayPreview('application/x-test', 'about:');
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
-  prepareTest(test4a, gTestRoot + "plugin_test.html", 1);
-}
-
-// Test a fallback to the click-to-play
-function test4a() {
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 4a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 4a, Plugin should not be activated");
-
-  var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
-  ok(overlay, "Test 4a, the overlay div is expected");
-
-  var e = overlay.ownerDocument.createEvent("CustomEvent");
-  e.initCustomEvent("MozPlayPlugin", true, true, true);
-  overlay.dispatchEvent(e);
-  var condition = function() objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY;
-  waitForCondition(condition, test4b, "Test 4a, Waited too long for plugin to stop play preview");
-}
-
-function test4b() {
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 4b, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 4b, Plugin should not be activated");
-
-  prepareTest(test5a, gTestRoot + "plugin_test.html", 1);
-}
-
-// Test a bypass of the click-to-play
-function test5a() {
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 5a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 5a, Plugin should not be activated");
-
-  var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
-  ok(overlay, "Test 5a, the overlay div is expected");
-
-  var e = overlay.ownerDocument.createEvent("CustomEvent");
-  e.initCustomEvent("MozPlayPlugin", true, true, false);
-  overlay.dispatchEvent(e);
-  var condition = function() objLoadingContent.activated;
-  waitForCondition(condition, test5b, "Test 5a, Waited too long for plugin to stop play preview");
-}
-
-function test5b() {
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 5b, Plugin should be activated");
-
-  finishTest();
-}
-
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_pluginplaypreview2.js
+++ /dev/null
@@ -1,171 +0,0 @@
-var rootDir = getRootDirectory(gTestPath);
-const gTestRoot = rootDir;
-
-var gTestBrowser = null;
-var gNextTest = null;
-var gNextTestSkip = 0;
-var gPlayPreviewPluginActualEvents = 0;
-var gPlayPreviewPluginExpectedEvents = 1;
-
-var gPlayPreviewRegistration = null;
-
-function registerPlayPreview(mimeType, targetUrl) {
-  var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-  ph.registerPlayPreviewMimeType(mimeType, false, targetUrl);
-
-  return (gPlayPreviewRegistration = {
-    unregister: function() {
-      ph.unregisterPlayPreviewMimeType(mimeType);
-      gPlayPreviewRegistration = null;
-    }
-  });
-}
-
-function unregisterPlayPreview() {
-  gPlayPreviewRegistration.unregister();
-}
-
-Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-
-function test() {
-  waitForExplicitFinish();
-  registerCleanupFunction(function() {
-    if (gPlayPreviewRegistration)
-      gPlayPreviewRegistration.unregister();
-    Services.prefs.clearUserPref("plugins.click_to_play");
-  });
-
-  var newTab = gBrowser.addTab();
-  gBrowser.selectedTab = newTab;
-  gTestBrowser = gBrowser.selectedBrowser;
-  gTestBrowser.addEventListener("load", pageLoad, true);
-  gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
-
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
-
-  registerPlayPreview('application/x-test', 'about:');
-  prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
-}
-
-function finishTest() {
-  gTestBrowser.removeEventListener("load", pageLoad, true);
-  gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
-  gBrowser.removeCurrentTab();
-  window.focus();
-  finish();
-}
-
-function handleBindingAttached(evt) {
-  if (evt.target instanceof Ci.nsIObjectLoadingContent &&
-      evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
-    gPlayPreviewPluginActualEvents++;
-}
-
-function pageLoad() {
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we then go on to test the states
-
-  // iframe might triggers load event as well, making sure we skip some to let
-  // all iframes on the page be loaded as well
-  if (gNextTestSkip) {
-    gNextTestSkip--;
-    return;
-  }
-  executeSoon(gNextTest);
-}
-
-function prepareTest(nextTest, url, skip) {
-  gNextTest = nextTest;
-  gNextTestSkip = skip;
-  gTestBrowser.contentWindow.location = url;
-}
-
-// Tests a page with normal play preview registration (1/2)
-function test1a() {
-  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
-  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
-
-  var pluginInfo = getTestPlugin();
-  ok(pluginInfo, "Should have a test plugin");
-
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
-
-  var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
-  ok(overlay, "Test 1a, the overlay div is expected");
-
-  var iframe = overlay.getElementsByClassName("previewPluginContentFrame")[0];
-  ok(iframe && iframe.localName == "iframe", "Test 1a, the overlay iframe is expected");
-  var iframeHref = iframe.contentWindow.location.href;
-  ok(iframeHref == "about:", "Test 1a, the overlay about: content is expected");
-
-  var rect = iframe.getBoundingClientRect();
-  ok(rect.width == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being replaced by actual plugin");
-  ok(rect.height == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being replaced by actual plugin");
-
-  var e = overlay.ownerDocument.createEvent("CustomEvent");
-  e.initCustomEvent("MozPlayPlugin", true, true, null);
-  overlay.dispatchEvent(e);
-  var condition = function() objLoadingContent.activated;
-  waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin to stop play preview");
-}
-
-// Tests that activating via MozPlayPlugin through the notification works (part 2/2)
-function test1b() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
-
-  is(gPlayPreviewPluginActualEvents, gPlayPreviewPluginExpectedEvents,
-     "There should be exactly one PluginPlayPreview event");
-
-  unregisterPlayPreview();
-
-  prepareTest(test2, gTestRoot + "plugin_test.html");
-}
-
-// Tests a page with a working plugin in it -- the mime type was just unregistered.
-function test2() {
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 2, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 2, Plugin should not be activated");
-
-  registerPlayPreview('application/x-unknown', 'about:');
-
-  prepareTest(test3, gTestRoot + "plugin_test.html");
-}
-
-// Tests a page with a working plugin in it -- diffent play preview type is reserved.
-function test3() {
-  var doc = gTestBrowser.contentDocument;
-  var plugin = doc.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 3, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 3, Plugin should not be activated");
-
-  unregisterPlayPreview();
-
-  registerPlayPreview('application/x-test', 'about:');
-  Services.prefs.setBoolPref("plugins.click_to_play", false);
-  var plugin = getTestPlugin();
-  plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
-  prepareTest(test4, gTestRoot + "plugin_test.html");
-}
-
-// Tests a page with a working plugin in it -- click-to-play is off
-function test4() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 4, Plugin should be activated");
-
-  finishTest();
-}
-
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_pluginplaypreview3.js
+++ /dev/null
@@ -1,130 +0,0 @@
-var rootDir = getRootDirectory(gTestPath);
-const gTestRoot = rootDir;
-
-var gTestBrowser = null;
-var gNextTest = null;
-var gNextTestSkip = 0;
-
-var gPlayPreviewRegistration = null;
-
-var gTestPluginType = 'application/x-test';
-var gTestPluginPreviewUrl = 'about:';
-
-function registerPlayPreview(whitelist) {
-  var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-  ph.registerPlayPreviewMimeType(gTestPluginType, true,
-                                 gTestPluginPreviewUrl, whitelist);
-
-  return (gPlayPreviewRegistration = {
-    unregister: function() {
-      ph.unregisterPlayPreviewMimeType(gTestPluginType);
-      gPlayPreviewRegistration = null;
-    }
-  });
-}
-
-function unregisterPlayPreview() {
-  gPlayPreviewRegistration.unregister();
-}
-
-Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-
-function test() {
-  waitForExplicitFinish();
-  registerCleanupFunction(function() {
-    if (gPlayPreviewRegistration) {
-      gPlayPreviewRegistration.unregister();
-    }
-  });
-
-  var newTab = gBrowser.addTab();
-  gBrowser.selectedTab = newTab;
-  gTestBrowser = gBrowser.selectedBrowser;
-  gTestBrowser.addEventListener("load", pageLoad, true);
-
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
-
-  registerPlayPreview('@*plugin_test.html');
-  prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
-}
-
-function finishTest() {
-  gTestBrowser.removeEventListener("load", pageLoad, true);
-  gBrowser.removeCurrentTab();
-  window.focus();
-  finish();
-}
-
-function pageLoad() {
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we then go on to test the states
-
-  // iframe might triggers load event as well, making sure we skip some to let
-  // all iframes on the page be loaded as well
-  if (gNextTestSkip) {
-    gNextTestSkip--;
-    return;
-  }
-  executeSoon(gNextTest);
-}
-
-function prepareTest(nextTest, url, skip) {
-  gNextTest = nextTest;
-  gNextTestSkip = skip;
-  gTestBrowser.contentWindow.location = url;
-}
-
-// Tests plugin on a whitelisted page.
-function test1a() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
-  ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
-
-  unregisterPlayPreview();
-
-  registerPlayPreview('@*plugin_wrong.html');
-  var plugin = getTestPlugin();
-  plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
-  prepareTest(test1b, gTestRoot + "plugin_test.html");
-}
-
-// Tests plugin on a non-whitelisted page.
-function test1b() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
-
-  unregisterPlayPreview();
-
-  registerPlayPreview('*browser_pluginplaypreview3.js');
-  var plugin = getTestPlugin();
-  plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
-  prepareTest(test2a, gTestRoot + "plugin_test_w_src.html");
-}
-
-// Tests plugin with whitelisted src/data.
-function test2a() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!objLoadingContent.activated, "Test 2a, Plugin should not be activated");
-
-  unregisterPlayPreview();
-
-  registerPlayPreview('*plugin_test_w_src.html');
-  var plugin = getTestPlugin();
-  plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
-  prepareTest(test2b, gTestRoot + "plugin_test_w_src.html");
-}
-
-// Tests plugin with non-whitelisted src/data.
-function test2b() {
-  var plugin = gTestBrowser.contentDocument.getElementById("test");
-  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "Test 2b, Plugin should be activated");
-
-  finishTest();
-}
-
deleted file mode 100644
--- a/browser/base/content/test/plugins/plugin_test_w_src.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body>
-<embed id="test" src="browser_pluginplaypreview3.js" style="width: 200px; height: 200px" type="application/x-test">
-</body>
-</html>
--- a/browser/components/places/tests/browser/browser.ini
+++ b/browser/components/places/tests/browser/browser.ini
@@ -15,23 +15,24 @@ support-files =
 [browser_0_library_left_pane_migration.js]
 [browser_410196_paste_into_tags.js]
 [browser_416459_cut.js]
 [browser_423515.js]
 [browser_425884.js]
 [browser_435851_copy_query.js]
 [browser_475045.js]
 [browser_555547.js]
+[browser_bookmarklet_windowOpen.js]
+support-files =
+  pageopeningwindow.html
 [browser_bookmarkProperties_addFolderDefaultButton.js]
 [browser_bookmarkProperties_addKeywordForThisSearch.js]
 [browser_bookmarkProperties_readOnlyRoot.js]
-[browser_bookmarklet_windowOpen.js]
-support-files =
-  pageopeningwindow.html
 [browser_bookmarksProperties.js]
+skip-if = (os == 'win' && os_version == "6.2") # Bug 1178709
 [browser_drag_bookmarks_on_toolbar.js]
 skip-if = e10s # Bug ?????? - test fails - "Number of dragged items should be the same. - Got 0, expected 1"
 [browser_forgetthissite_single.js]
 [browser_history_sidebar_search.js]
 skip-if = e10s && (os == 'linux' || os == 'mac') # Bug 1116457
 [browser_library_batch_delete.js]
 [browser_library_commands.js]
 [browser_library_downloads.js]
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -766,8 +766,13 @@ e10s.offerPopup.noThanks.accesskey = N
 e10s.postActivationInfobar.message = You're now helping to test multi-process in %S! Please report problems you find.
 e10s.postActivationInfobar.learnMore.label = Learn More
 e10s.postActivationInfobar.learnMore.accesskey = L
 e10s.accessibilityNotice.mainMessage = Multi-process does not yet support accessibility features. Multi-process will be disabled if you restart %S. Would you like to restart?
 e10s.accessibilityNotice.disableAndRestart.label = Disable and Restart
 e10s.accessibilityNotice.disableAndRestart.accesskey = R
 e10s.accessibilityNotice.dontDisable.label = Don't Disable
 e10s.accessibilityNotice.dontDisable.accesskey = D
+
+muteTab.label = Mute Tab
+muteTab.accesskey = M
+unmuteTab.label = Unmute Tab
+unmuteTab.accesskey = M
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -306,18 +306,16 @@ PluginContent.prototype = {
       case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED:
         return "PluginOutdated";
       case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
         return "PluginClickToPlay";
       case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
         return "PluginVulnerableUpdatable";
       case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
         return "PluginVulnerableNoUpdate";
-      case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
-        return "PluginPlayPreview";
       default:
         // Not all states map to a handler
         return null;
     }
   },
 
   handleEvent: function (event) {
     let eventType = event.type;
@@ -412,20 +410,16 @@ PluginContent.prototype = {
             eventType == "PluginVulnerableNoUpdate") {
           let vulnerabilityString = gNavigatorBundle.GetStringFromName(eventType);
           let vulnerabilityText = this.getPluginUI(plugin, "vulnerabilityStatus");
           vulnerabilityText.textContent = vulnerabilityString;
         }
         shouldShowNotification = true;
         break;
 
-      case "PluginPlayPreview":
-        this._handlePlayPreviewEvent(plugin);
-        break;
-
       case "PluginDisabled":
         let manageLink = this.getPluginUI(plugin, "managePluginsLink");
         this.addLinkClickCallback(manageLink, "forwardCallback", "managePlugins");
         shouldShowNotification = true;
         break;
 
       case "PluginInstantiated":
         shouldShowNotification = true;
@@ -526,45 +520,28 @@ PluginContent.prototype = {
     let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
     let principal = objLoadingContent.ownerDocument.defaultView.top.document.nodePrincipal;
     let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
 
     let isFallbackTypeValid =
       objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
       objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
 
-    if (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) {
-      // checking if play preview is subject to CTP rules
-      let playPreviewInfo = pluginHost.getPlayPreviewInfo(objLoadingContent.actualType);
-      isFallbackTypeValid = !playPreviewInfo.ignoreCTP;
-    }
-
     return !objLoadingContent.activated &&
            pluginPermission != Ci.nsIPermissionManager.DENY_ACTION &&
            isFallbackTypeValid;
   },
 
   hideClickToPlayOverlay: function (plugin) {
     let overlay = this.getPluginUI(plugin, "main");
     if (overlay) {
       overlay.classList.remove("visible");
     }
   },
 
-  stopPlayPreview: function (plugin, playPlugin) {
-    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-    if (objLoadingContent.activated)
-      return;
-
-    if (playPlugin)
-      objLoadingContent.playPlugin();
-    else
-      objLoadingContent.cancelPlayPreview();
-  },
-
   // Forward a link click callback to the chrome process.
   forwardCallback: function (name) {
     this.global.sendAsyncMessage("PluginContent:LinkClickCallback", { name: name });
   },
 
   submitReport: function submitReport(plugin) {
     if (!AppConstants.MOZ_CRASHREPORTER) {
       return;
@@ -636,59 +613,16 @@ PluginContent.prototype = {
         event.button == 0 &&
         event.isTrusted) {
       this._showClickToPlayNotification(plugin, true);
     event.stopPropagation();
     event.preventDefault();
     }
   },
 
-  _handlePlayPreviewEvent: function (plugin) {
-    let doc = plugin.ownerDocument;
-    let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-    let pluginInfo = this._getPluginInfo(plugin);
-    let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype);
-
-    let previewContent = this.getPluginUI(plugin, "previewPluginContent");
-    let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
-    if (!iframe) {
-      // lazy initialization of the iframe
-      iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
-      iframe.className = "previewPluginContentFrame";
-      previewContent.appendChild(iframe);
-
-      // Force a style flush, so that we ensure our binding is attached.
-      plugin.clientTop;
-    }
-    iframe.src = playPreviewInfo.redirectURL;
-
-    // MozPlayPlugin event can be dispatched from the extension chrome
-    // code to replace the preview content with the native plugin
-    let playPluginHandler = (event) => {
-      if (!event.isTrusted)
-        return;
-
-      previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
-
-      let playPlugin = !event.detail;
-      this.stopPlayPreview(plugin, playPlugin);
-
-      // cleaning up: removes overlay iframe from the DOM
-      let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
-      if (iframe)
-        previewContent.removeChild(iframe);
-    };
-
-    previewContent.addEventListener("MozPlayPlugin", playPluginHandler, true);
-
-    if (!playPreviewInfo.ignoreCTP) {
-      this._showClickToPlayNotification(plugin, false);
-    }
-  },
-
   reshowClickToPlayNotification: function () {
     let contentWindow = this.global.content;
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
     let plugins = cwu.plugins;
     for (let plugin of plugins) {
       let overlay = this.getPluginUI(plugin, "main");
       if (overlay)
--- a/build/autoconf/icu.m4
+++ b/build/autoconf/icu.m4
@@ -286,16 +286,17 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA
           ICU_CFLAGS="$ICU_CFLAGS -DU_STATIC_IMPLEMENTATION"
           if test "$GNU_CC"; then
             ICU_CFLAGS="$ICU_CFLAGS -fvisibility=hidden"
             ICU_CXXFLAGS="$ICU_CXXFLAGS -fvisibility=hidden"
           fi
         fi
 
         (export AR="$AR"
+         export RANLIB="$RANLIB"
          export CC="$CC"
          export CXX="$CXX"
          export LD="$LD"
          export ARFLAGS="$ARFLAGS"
          export CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS"
          export CFLAGS="$ICU_CFLAGS"
          export CXXFLAGS="$ICU_CXXFLAGS"
          export LDFLAGS="$ICU_LDFLAGS $LDFLAGS"
--- a/docshell/build/moz.build
+++ b/docshell/build/moz.build
@@ -20,9 +20,12 @@ LOCAL_INCLUDES += [
     '/uriloader/prefetch',
 ]
 
 if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
     LOCAL_INCLUDES += ['/uriloader/exthandler/mac']
 
 FINAL_LIBRARY = 'xul'
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
--- a/dom/apps/moz.build
+++ b/dom/apps/moz.build
@@ -46,15 +46,18 @@ EXTRA_PP_JS_MODULES += [
     'AppsUtils.jsm',
     'ImportExport.jsm',
     'InterAppCommService.jsm',
     'OperatorApps.jsm',
     'ScriptPreloader.jsm',
     'Webapps.jsm',
 ]
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/js/xpconnect/wrappers',
 ]
--- a/dom/archivereader/moz.build
+++ b/dom/archivereader/moz.build
@@ -16,16 +16,19 @@ EXPORTS.mozilla.dom.archivereader += [
 UNIFIED_SOURCES += [
     'ArchiveEvent.cpp',
     'ArchiveReader.cpp',
     'ArchiveRequest.cpp',
     'ArchiveZipEvent.cpp',
     'ArchiveZipFile.cpp',
 ]
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
 ]
 
 FINAL_LIBRARY = 'xul'
 
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -828,16 +828,18 @@ nsIContent::PreHandleEvent(EventChainPre
               eventType.EqualsLiteral("reset") ||
               eventType.EqualsLiteral("resize") ||
               eventType.EqualsLiteral("scroll") ||
               eventType.EqualsLiteral("selectstart")) {
             stopEvent = true;
           }
         }
         break;
+      default:
+        break;
     }
 
     if (stopEvent) {
       // If we do stop propagation, we still want to propagate
       // the event to chrome (nsPIDOMWindow::GetParentTarget()).
       // The load event is special in that we don't ever propagate it
       // to chrome.
       nsCOMPtr<nsPIDOMWindow> win = OwnerDoc()->GetWindow();
--- a/dom/base/StructuredCloneHelper.cpp
+++ b/dom/base/StructuredCloneHelper.cpp
@@ -127,17 +127,16 @@ StructuredCloneHelperInternal::~Structur
   MOZ_ASSERT(mShutdownCalled);
 #endif
 }
 
 void
 StructuredCloneHelperInternal::Shutdown()
 {
 #ifdef DEBUG
-  MOZ_ASSERT(!mShutdownCalled, "Shutdown already called!");
   mShutdownCalled = true;
 #endif
 
   mBuffer = nullptr;
 }
 
 bool
 StructuredCloneHelperInternal::Write(JSContext* aCx,
@@ -165,17 +164,16 @@ StructuredCloneHelperInternal::Write(JSC
 bool
 StructuredCloneHelperInternal::Read(JSContext* aCx,
                                     JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(mBuffer, "Read() without Write() is not allowed.");
   MOZ_ASSERT(!mShutdownCalled, "This method cannot be called after Shutdown.");
 
   bool ok = mBuffer->read(aCx, aValue, &gCallbacks, this);
-  mBuffer = nullptr;
   return ok;
 }
 
 bool
 StructuredCloneHelperInternal::ReadTransferCallback(JSContext* aCx,
                                                     JSStructuredCloneReader* aReader,
                                                     uint32_t aTag,
                                                     void* aContent,
@@ -249,36 +247,52 @@ StructuredCloneHelper::Read(nsISupports*
   mozilla::AutoRestore<nsISupports*> guard(mParent);
   mParent = aParent;
 
   if (!StructuredCloneHelperInternal::Read(aCx, aValue)) {
     JS_ClearPendingException(aCx);
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
   }
 
-  mBlobImplArray.Clear();
+  // If we are tranferring something, we cannot call 'Read()' more than once.
+  if (mSupportsTransferring) {
+    mBlobImplArray.Clear();
+    Shutdown();
+  }
 }
 
 void
 StructuredCloneHelper::ReadFromBuffer(nsISupports* aParent,
                                       JSContext* aCx,
                                       uint64_t* aBuffer,
                                       size_t aBufferLength,
                                       JS::MutableHandle<JS::Value> aValue,
                                       ErrorResult& aRv)
 {
+  ReadFromBuffer(aParent, aCx, aBuffer, aBufferLength,
+                 JS_STRUCTURED_CLONE_VERSION, aValue, aRv);
+}
+
+void
+StructuredCloneHelper::ReadFromBuffer(nsISupports* aParent,
+                                      JSContext* aCx,
+                                      uint64_t* aBuffer,
+                                      size_t aBufferLength,
+                                      uint32_t aAlgorithmVersion,
+                                      JS::MutableHandle<JS::Value> aValue,
+                                      ErrorResult& aRv)
+{
   MOZ_ASSERT(!mBuffer, "ReadFromBuffer() must be called without a Write().");
   MOZ_ASSERT(aBuffer);
 
   mozilla::AutoRestore<nsISupports*> guard(mParent);
   mParent = aParent;
 
-  if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength,
-                              JS_STRUCTURED_CLONE_VERSION, aValue,
-                              &gCallbacks, this)) {
+  if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength, aAlgorithmVersion,
+                              aValue, &gCallbacks, this)) {
     JS_ClearPendingException(aCx);
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
   }
 }
 
 void
 StructuredCloneHelper::MoveBufferDataToArray(FallibleTArray<uint8_t>& aArray,
                                              ErrorResult& aRv)
--- a/dom/base/StructuredCloneHelper.h
+++ b/dom/base/StructuredCloneHelper.h
@@ -155,20 +155,34 @@ public:
   // and/or the PortIdentifiers.
   void ReadFromBuffer(nsISupports* aParent,
                       JSContext* aCx,
                       uint64_t* aBuffer,
                       size_t aBufferLength,
                       JS::MutableHandle<JS::Value> aValue,
                       ErrorResult &aRv);
 
+  void ReadFromBuffer(nsISupports* aParent,
+                      JSContext* aCx,
+                      uint64_t* aBuffer,
+                      size_t aBufferLength,
+                      uint32_t aAlgorithmVersion,
+                      JS::MutableHandle<JS::Value> aValue,
+                      ErrorResult &aRv);
+
   // Use this method to free a buffer generated by MoveToBuffer().
   void FreeBuffer(uint64_t* aBuffer,
                   size_t aBufferLength);
 
+  bool HasClonedDOMObjects() const
+  {
+    return !mBlobImplArray.IsEmpty() ||
+           !mClonedImages.IsEmpty();
+  }
+
   nsTArray<nsRefPtr<BlobImpl>>& BlobImpls()
   {
     MOZ_ASSERT(mSupportsCloning, "Blobs cannot be taken/set if cloning is not supported.");
     return mBlobImplArray;
   }
 
   const nsTArray<nsRefPtr<MessagePortBase>>& GetTransferredPorts() const
   {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -661,39 +661,39 @@ nsContentUtils::InitializeModifierString
   sMetaText = new nsString(metaModifier);
   sOSText = new nsString(osModifier);
   sAltText = new nsString(altModifier);
   sControlText = new nsString(controlModifier);
   sModifierSeparator = new nsString(modifierSeparator);  
 }
 
 // Because of SVG/SMIL we have several atoms mapped to the same
-// id, but we can rely on ID_TO_EVENT to map id to only one atom.
+// id, but we can rely on MESSAGE_TO_EVENT to map id to only one atom.
 static bool
 ShouldAddEventToStringEventTable(const EventNameMapping& aMapping)
 {
-  switch(aMapping.mId) {
-#define ID_TO_EVENT(name_, id_, type_, struct_) \
-  case id_: return nsGkAtoms::on##name_ == aMapping.mAtom;
+  switch(aMapping.mMessage) {
+#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
+  case message_: return nsGkAtoms::on##name_ == aMapping.mAtom;
 #include "mozilla/EventNameList.h"
-#undef ID_TO_EVENT
+#undef MESSAGE_TO_EVENT
   default:
     break;
   }
   return false;
 }
 
 bool
 nsContentUtils::InitializeEventTable() {
   NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
   NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");
 
   static const EventNameMapping eventArray[] = {
-#define EVENT(name_,  _id, _type, _class)          \
-    { nsGkAtoms::on##name_, _id, _type, _class },
+#define EVENT(name_,  _message, _type, _class)          \
+    { nsGkAtoms::on##name_, _type, _message, _class },
 #define WINDOW_ONLY_EVENT EVENT
 #define NON_IDL_EVENT EVENT
 #include "mozilla/EventNameList.h"
 #undef WINDOW_ONLY_EVENT
 #undef NON_IDL_EVENT
 #undef EVENT
     { nullptr }
   };
@@ -719,19 +719,19 @@ nsContentUtils::InitializeEventTable() {
 
 void
 nsContentUtils::InitializeTouchEventTable()
 {
   static bool sEventTableInitialized = false;
   if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
     sEventTableInitialized = true;
     static const EventNameMapping touchEventArray[] = {
-#define EVENT(name_,  _id, _type, _class)
-#define TOUCH_EVENT(name_,  _id, _type, _class)      \
-      { nsGkAtoms::on##name_, _id, _type, _class },
+#define EVENT(name_,  _message, _type, _class)
+#define TOUCH_EVENT(name_,  _message, _type, _class)      \
+      { nsGkAtoms::on##name_, _type, _message, _class },
 #include "mozilla/EventNameList.h"
 #undef TOUCH_EVENT
 #undef EVENT
       { nullptr }
     };
     // Subtract one from the length because of the trailing null
     for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
       sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]);
@@ -3650,23 +3650,23 @@ nsContentUtils::IsEventAttributeName(nsI
   if (name[0] != 'o' || name[1] != 'n')
     return false;
 
   EventNameMapping mapping;
   return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
 }
 
 // static
-uint32_t
-nsContentUtils::GetEventId(nsIAtom* aName)
+EventMessage
+nsContentUtils::GetEventMessage(nsIAtom* aName)
 {
   if (aName) {
     EventNameMapping mapping;
     if (sAtomEventTable->Get(aName, &mapping)) {
-      return mapping.mId;
+      return mapping.mMessage;
     }
   }
 
   return NS_USER_DEFINED_EVENT;
 }
 
 // static
 mozilla::EventClassID
@@ -3675,41 +3675,42 @@ nsContentUtils::GetEventClassID(const ns
   EventNameMapping mapping;
   if (sStringEventTable->Get(aName, &mapping))
     return mapping.mEventClassID;
 
   return eBasicEventClass;
 }
 
 nsIAtom*
-nsContentUtils::GetEventIdAndAtom(const nsAString& aName,
-                                  mozilla::EventClassID aEventClassID,
-                                  uint32_t* aEventID)
+nsContentUtils::GetEventMessageAndAtom(const nsAString& aName,
+                                       mozilla::EventClassID aEventClassID,
+                                       EventMessage* aEventMessage)
 {
   EventNameMapping mapping;
   if (sStringEventTable->Get(aName, &mapping)) {
-    *aEventID = mapping.mEventClassID == aEventClassID ? mapping.mId :
-                                                         NS_USER_DEFINED_EVENT;
+    *aEventMessage =
+      mapping.mEventClassID == aEventClassID ? mapping.mMessage :
+                                               NS_USER_DEFINED_EVENT;
     return mapping.mAtom;
   }
 
   // If we have cached lots of user defined event names, clear some of them.
   if (sUserDefinedEvents->Count() > 127) {
     while (sUserDefinedEvents->Count() > 64) {
       nsIAtom* first = sUserDefinedEvents->ObjectAt(0);
       sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
       sUserDefinedEvents->RemoveObjectAt(0);
     }
   }
 
-  *aEventID = NS_USER_DEFINED_EVENT;
+  *aEventMessage = NS_USER_DEFINED_EVENT;
   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aName);
   sUserDefinedEvents->AppendObject(atom);
   mapping.mAtom = atom;
-  mapping.mId = NS_USER_DEFINED_EVENT;
+  mapping.mMessage = NS_USER_DEFINED_EVENT;
   mapping.mType = EventNameType_None;
   mapping.mEventClassID = eBasicEventClass;
   sStringEventTable->Put(aName, mapping);
   return mapping.mAtom;
 }
 
 static
 nsresult GetEventAndTarget(nsIDocument* aDoc, nsISupports* aTarget,
@@ -7701,17 +7702,17 @@ nsContentUtils::SendKeyEvent(nsIWidget* 
                              int32_t aModifiers,
                              uint32_t aAdditionalFlags,
                              bool* aDefaultActionTaken)
 {
   // get the widget to send the event to
   if (!aWidget)
     return NS_ERROR_FAILURE;
 
-  int32_t msg;
+  EventMessage msg;
   if (aType.EqualsLiteral("keydown"))
     msg = NS_KEY_DOWN;
   else if (aType.EqualsLiteral("keyup"))
     msg = NS_KEY_UP;
   else if (aType.EqualsLiteral("keypress"))
     msg = NS_KEY_PRESS;
   else
     return NS_ERROR_FAILURE;
@@ -7814,17 +7815,17 @@ nsContentUtils::SendMouseEvent(nsCOMPtr<
                                bool *aPreventDefault,
                                bool aIsSynthesized)
 {
   nsPoint offset;
   nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  int32_t msg;
+  EventMessage msg;
   bool contextMenuKey = false;
   if (aType.EqualsLiteral("mousedown"))
     msg = NS_MOUSE_BUTTON_DOWN;
   else if (aType.EqualsLiteral("mouseup"))
     msg = NS_MOUSE_BUTTON_UP;
   else if (aType.EqualsLiteral("mousemove"))
     msg = NS_MOUSE_MOVE;
   else if (aType.EqualsLiteral("mouseover"))
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -160,18 +160,18 @@ enum EventNameType {
   EventNameType_All = 0xFFFF
 };
 
 struct EventNameMapping
 {
   // This holds pointers to nsGkAtoms members, and is therefore safe as a
   // non-owning reference.
   nsIAtom* MOZ_NON_OWNING_REF mAtom;
-  uint32_t mId;
   int32_t  mType;
+  mozilla::EventMessage mMessage;
   mozilla::EventClassID mEventClassID;
 };
 
 struct nsShortcutCandidate {
   nsShortcutCandidate(uint32_t aCharCode, bool aIgnoreShift) :
     mCharCode(aCharCode), mIgnoreShift(aIgnoreShift)
   {
   }
@@ -1095,45 +1095,45 @@ public:
    * defined above.
    *
    * @param aName the event name to look up
    * @param aType the type of content
    */
   static bool IsEventAttributeName(nsIAtom* aName, int32_t aType);
 
   /**
-   * Return the event id for the event with the given name. The name is the
-   * event name with the 'on' prefix. Returns NS_USER_DEFINED_EVENT if the
+   * Return the event message for the event with the given name. The name is
+   * the event name with the 'on' prefix. Returns NS_USER_DEFINED_EVENT if the
    * event doesn't match a known event name.
    *
    * @param aName the event name to look up
    */
-  static uint32_t GetEventId(nsIAtom* aName);
+  static mozilla::EventMessage GetEventMessage(nsIAtom* aName);
 
   /**
    * Return the EventClassID for the event with the given name. The name is the
    * event name *without* the 'on' prefix. Returns eBasicEventClass if the event
    * is not known to be of any particular event class.
    *
    * @param aName the event name to look up
    */
   static mozilla::EventClassID GetEventClassID(const nsAString& aName);
 
   /**
-   * Return the event id and atom for the event with the given name.
+   * Return the event message and atom for the event with the given name.
    * The name is the event name *without* the 'on' prefix.
    * Returns NS_USER_DEFINED_EVENT on the aEventID if the
    * event doesn't match a known event name in the category.
    *
    * @param aName the event name to look up
    * @param aEventClassID only return event id for aEventClassID
    */
-  static nsIAtom* GetEventIdAndAtom(const nsAString& aName,
-                                    mozilla::EventClassID aEventClassID,
-                                    uint32_t* aEventID);
+  static nsIAtom* GetEventMessageAndAtom(const nsAString& aName,
+                                         mozilla::EventClassID aEventClassID,
+                                         mozilla::EventMessage* aEventMessage);
 
   /**
    * Used only during traversal of the XPCOM graph by the cycle
    * collector: push a pointer to the listener manager onto the
    * children deque, if it exists. Do nothing if there is no listener
    * manager.
    *
    * Crucially: does not perform any refcounting operations.
@@ -1691,26 +1691,22 @@ public:
    * Case insensitive comparison between two strings. However it only ignores
    * case for ASCII characters a-z.
    */
   static bool EqualsIgnoreASCIICase(const nsAString& aStr1,
                                     const nsAString& aStr2);
 
   /**
    * Convert ASCII A-Z to a-z.
-   * @return NS_OK on success, or NS_ERROR_OUT_OF_MEMORY if making the string
-   * writable needs to allocate memory and that allocation fails.
    */
   static void ASCIIToLower(nsAString& aStr);
   static void ASCIIToLower(const nsAString& aSource, nsAString& aDest);
 
   /**
    * Convert ASCII a-z to A-Z.
-   * @return NS_OK on success, or NS_ERROR_OUT_OF_MEMORY if making the string
-   * writable needs to allocate memory and that allocation fails.
    */
   static void ASCIIToUpper(nsAString& aStr);
   static void ASCIIToUpper(const nsAString& aSource, nsAString& aDest);
 
   /**
    * Return whether aStr contains an ASCII uppercase character.
    */
   static bool StringContainsASCIIUpper(const nsAString& aStr);
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -616,24 +616,28 @@ IsSelectionInsideRuby(nsISelection* aSel
     if (!IsInsideRuby(n)) {
       return false;
     }
   }
   return true;
 }
 
 bool
-nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPresShell* aPresShell,
-                                  nsISelection* aSelection, bool* aActionTaken)
+nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
+                                  int32_t aClipboardType,
+                                  nsIPresShell* aPresShell,
+                                  nsISelection* aSelection,
+                                  bool* aActionTaken)
 {
   if (aActionTaken) {
     *aActionTaken = false;
   }
 
-  NS_ASSERTION(aType == NS_CUT || aType == NS_COPY || aType == NS_PASTE,
+  NS_ASSERTION(aEventMessage == NS_CUT || aEventMessage == NS_COPY ||
+               aEventMessage == NS_PASTE,
                "Invalid clipboard event type");
 
   nsCOMPtr<nsIPresShell> presShell = aPresShell;
   if (!presShell)
     return false;
 
   nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
   if (!doc)
@@ -679,31 +683,32 @@ nsCopySupport::FireClipboardEvent(int32_
   const bool chromeShell =
     docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
 
   // next, fire the cut, copy or paste event
   bool doDefault = true;
   nsRefPtr<DataTransfer> clipboardData;
   if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
     clipboardData =
-      new DataTransfer(piWindow, aType, aType == NS_PASTE, aClipboardType);
+      new DataTransfer(piWindow, aEventMessage, aEventMessage == NS_PASTE,
+                       aClipboardType);
 
     nsEventStatus status = nsEventStatus_eIgnore;
-    InternalClipboardEvent evt(true, aType);
+    InternalClipboardEvent evt(true, aEventMessage);
     evt.clipboardData = clipboardData;
     EventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt,
                               nullptr, &status);
     // If the event was cancelled, don't do the clipboard operation
     doDefault = (status != nsEventStatus_eConsumeNoDefault);
   }
 
   // No need to do anything special during a paste. Either an event listener
   // took care of it and cancelled the event, or the caller will handle it.
   // Return true to indicate that the event wasn't cancelled.
-  if (aType == NS_PASTE) {
+  if (aEventMessage == NS_PASTE) {
     // Clear and mark the clipboardData as readonly. This prevents someone
     // from reading the clipboard contents after the paste event has fired.
     if (clipboardData) {
       clipboardData->ClearAll();
       clipboardData->SetReadOnly();
     }
 
     if (aActionTaken) {
@@ -733,17 +738,17 @@ nsCopySupport::FireClipboardEvent(int32_
     if (formControl) {
       if (formControl->GetType() == NS_FORM_INPUT_PASSWORD) {
         return false;
       }
     }
 
     // when cutting non-editable content, do nothing
     // XXX this is probably the wrong editable flag to check
-    if (aType != NS_CUT || content->IsEditable()) {
+    if (aEventMessage != NS_CUT || content->IsEditable()) {
       // get the data from the selection if any
       bool isCollapsed;
       sel->GetIsCollapsed(&isCollapsed);
       if (isCollapsed) {
         if (aActionTaken) {
           *aActionTaken = true;
         }
         return false;
--- a/dom/base/nsCopySupport.h
+++ b/dom/base/nsCopySupport.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsCopySupport_h__
 #define nsCopySupport_h__
 
-#include "nscore.h"
+#include "mozilla/EventForwards.h"
 
 class nsINode;
 class nsISelection;
 class nsIDocument;
 class nsIImageLoadingContent;
 class nsIContent;
 class nsITransferable;
 class nsACString;
@@ -59,17 +59,17 @@ class nsCopySupport
     /**
      * Returns true if a copy operation is currently permitted based on the
      * current focus and selection within the specified document.
      */
     static bool CanCopy(nsIDocument* aDocument);
 
     /**
      * Fires a cut, copy or paste event, on the given presshell, depending
-     * on the value of aType, which should be either NS_CUT, NS_COPY or
+     * on the value of aEventMessage, which should be either NS_CUT, NS_COPY or
      * NS_PASTE, and perform the default copy action if the event was not
      * cancelled.
      *
      * If aSelection is specified, then this selection is used as the target
      * of the operation. Otherwise, GetSelectionForCopy is used to retrieve
      * the current selection.
      *
      * This will fire a cut, copy or paste event at the node at the start
@@ -83,16 +83,16 @@ class nsCopySupport
      *
      * aClipboardType specifies which clipboard to use, from nsIClipboard.
      *
      * If aActionTaken is non-NULL, it will be set to true if an action was
      * taken, whether it be the default action or the default being prevented.
      *
      * If the event is cancelled or an error occurs, false will be returned.
      */
-    static bool FireClipboardEvent(int32_t aType,
+    static bool FireClipboardEvent(mozilla::EventMessage aEventMessage,
                                    int32_t aClipboardType,
                                    nsIPresShell* aPresShell,
                                    nsISelection* aSelection,
                                    bool* aActionTaken = nullptr);
 };
 
 #endif
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -695,17 +695,17 @@ nsDOMWindowUtils::SendPointerEventCommon
 
   // get the widget to send the event to
   nsPoint offset;
   nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
-  int32_t msg;
+  EventMessage msg;
   if (aType.EqualsLiteral("pointerdown")) {
     msg = NS_POINTER_DOWN;
   } else if (aType.EqualsLiteral("pointerup")) {
     msg = NS_POINTER_UP;
   } else if (aType.EqualsLiteral("pointermove")) {
     msg = NS_POINTER_MOVE;
   } else if (aType.EqualsLiteral("pointerover")) {
     msg = NS_POINTER_OVER;
@@ -974,17 +974,17 @@ nsDOMWindowUtils::SendTouchEventCommon(c
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   // get the widget to send the event to
   nsPoint offset;
   nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
   if (!widget) {
     return NS_ERROR_NULL_POINTER;
   }
-  int32_t msg;
+  EventMessage msg;
   if (aType.EqualsLiteral("touchstart")) {
     msg = NS_TOUCH_START;
   } else if (aType.EqualsLiteral("touchmove")) {
     msg = NS_TOUCH_MOVE;
   } else if (aType.EqualsLiteral("touchend")) {
     msg = NS_TOUCH_END;
   } else if (aType.EqualsLiteral("touchcancel")) {
     msg = NS_TOUCH_CANCEL;
@@ -1309,17 +1309,17 @@ nsDOMWindowUtils::SendSimpleGestureEvent
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   // get the widget to send the event to
   nsPoint offset;
   nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  int32_t msg;
+  EventMessage msg;
   if (aType.EqualsLiteral("MozSwipeGestureStart"))
     msg = NS_SIMPLE_GESTURE_SWIPE_START;
   else if (aType.EqualsLiteral("MozSwipeGestureUpdate"))
     msg = NS_SIMPLE_GESTURE_SWIPE_UPDATE;
   else if (aType.EqualsLiteral("MozSwipeGestureEnd"))
     msg = NS_SIMPLE_GESTURE_SWIPE_END;
   else if (aType.EqualsLiteral("MozSwipeGesture"))
     msg = NS_SIMPLE_GESTURE_SWIPE;
@@ -1936,32 +1936,47 @@ nsDOMWindowUtils::SendQueryContentEvent(
   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
-  if (aType != NS_QUERY_SELECTED_TEXT &&
-      aType != NS_QUERY_TEXT_CONTENT &&
-      aType != NS_QUERY_CARET_RECT &&
-      aType != NS_QUERY_TEXT_RECT &&
-      aType != NS_QUERY_EDITOR_RECT &&
-      aType != NS_QUERY_CHARACTER_AT_POINT) {
-    return NS_ERROR_INVALID_ARG;
+  EventMessage message;
+  switch (aType) {
+    case QUERY_SELECTED_TEXT:
+      message = NS_QUERY_SELECTED_TEXT;
+      break;
+    case QUERY_TEXT_CONTENT:
+      message = NS_QUERY_TEXT_CONTENT;
+      break;
+    case QUERY_CARET_RECT:
+      message = NS_QUERY_CARET_RECT;
+      break;
+    case QUERY_TEXT_RECT:
+      message = NS_QUERY_TEXT_RECT;
+      break;
+    case QUERY_EDITOR_RECT:
+      message = NS_QUERY_EDITOR_RECT;
+      break;
+    case QUERY_CHARACTER_AT_POINT:
+      message = NS_QUERY_CHARACTER_AT_POINT;
+      break;
+    default:
+      return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsIWidget> targetWidget = widget;
   LayoutDeviceIntPoint pt(aX, aY);
 
   bool useNativeLineBreak =
     !(aAdditionalFlags & QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
 
-  if (aType == QUERY_CHARACTER_AT_POINT) {
+  if (message == NS_QUERY_CHARACTER_AT_POINT) {
     // Looking for the widget at the point.
     WidgetQueryContentEvent dummyEvent(true, NS_QUERY_CONTENT_STATE, widget);
     dummyEvent.mUseNativeLineBreak = useNativeLineBreak;
     InitEvent(dummyEvent, &pt);
     nsIFrame* popupFrame =
       nsLayoutUtils::GetPopupFrameForEventCoordinates(presContext->GetRootPresContext(), &dummyEvent);
 
     nsIntRect widgetBounds;
@@ -1978,20 +1993,20 @@ nsDOMWindowUtils::SendQueryContentEvent(
     // Fire the event on the widget at the point
     if (popupFrame) {
       targetWidget = popupFrame->GetNearestWidget();
     }
   }
 
   pt += widget->WidgetToScreenOffset() - targetWidget->WidgetToScreenOffset();
 
-  WidgetQueryContentEvent queryEvent(true, aType, targetWidget);
+  WidgetQueryContentEvent queryEvent(true, message, targetWidget);
   InitEvent(queryEvent, &pt);
 
-  switch (aType) {
+  switch (message) {
     case NS_QUERY_TEXT_CONTENT:
       queryEvent.InitForQueryTextContent(aOffset, aLength, useNativeLineBreak);
       break;
     case NS_QUERY_CARET_RECT:
       queryEvent.InitForQueryCaretRect(aOffset, useNativeLineBreak);
       break;
     case NS_QUERY_TEXT_RECT:
       queryEvent.InitForQueryTextRect(aOffset, aLength, useNativeLineBreak);
@@ -2051,17 +2066,17 @@ nsDOMWindowUtils::SendContentCommandEven
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  int32_t msg;
+  EventMessage msg;
   if (aType.EqualsLiteral("cut"))
     msg = NS_CONTENT_COMMAND_CUT;
   else if (aType.EqualsLiteral("copy"))
     msg = NS_CONTENT_COMMAND_COPY;
   else if (aType.EqualsLiteral("paste"))
     msg = NS_CONTENT_COMMAND_PASTE;
   else if (aType.EqualsLiteral("delete"))
     msg = NS_CONTENT_COMMAND_DELETE;
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -92,35 +92,39 @@ PRLogModuleInfo* gFocusNavigationLog;
     MOZ_LOG(log, LogLevel::Debug, (format, tag.get()));             \
   }
 
 #define LOGCONTENT(format, content) LOGTAG(gFocusLog, format, content)
 #define LOGCONTENTNAVIGATION(format, content) LOGTAG(gFocusNavigationLog, format, content)
 
 struct nsDelayedBlurOrFocusEvent
 {
-  nsDelayedBlurOrFocusEvent(uint32_t aType,
+  nsDelayedBlurOrFocusEvent(EventMessage aEventMessage,
                             nsIPresShell* aPresShell,
                             nsIDocument* aDocument,
                             EventTarget* aTarget)
-   : mType(aType),
-     mPresShell(aPresShell),
-     mDocument(aDocument),
-     mTarget(aTarget) { }
+    : mPresShell(aPresShell)
+    , mDocument(aDocument)
+    , mTarget(aTarget)
+    , mEventMessage(aEventMessage)
+ {
+ }
 
   nsDelayedBlurOrFocusEvent(const nsDelayedBlurOrFocusEvent& aOther)
-   : mType(aOther.mType),
-     mPresShell(aOther.mPresShell),
-     mDocument(aOther.mDocument),
-     mTarget(aOther.mTarget) { }
-
-  uint32_t mType;
+    : mPresShell(aOther.mPresShell)
+    , mDocument(aOther.mDocument)
+    , mTarget(aOther.mTarget)
+    , mEventMessage(aOther.mEventMessage)
+  {
+  }
+
   nsCOMPtr<nsIPresShell> mPresShell;
   nsCOMPtr<nsIDocument> mDocument;
   nsCOMPtr<EventTarget> mTarget;
+  EventMessage mEventMessage;
 };
 
 inline void ImplCycleCollectionUnlink(nsDelayedBlurOrFocusEvent& aField)
 {
   aField.mPresShell = nullptr;
   aField.mDocument = nullptr;
   aField.mTarget = nullptr;
 }
@@ -1033,21 +1037,21 @@ nsFocusManager::FireDelayedEvents(nsIDoc
       if (!aDocument->GetInnerWindow() ||
           !aDocument->GetInnerWindow()->IsCurrentInnerWindow()) {
         // If the document was navigated away from or is defunct, don't bother
         // firing events on it. Note the symmetry between this condition and
         // the similar one in nsDocument.cpp:FireOrClearDelayedEvents.
         mDelayedBlurFocusEvents.RemoveElementAt(i);
         --i;
       } else if (!aDocument->EventHandlingSuppressed()) {
-        uint32_t type = mDelayedBlurFocusEvents[i].mType;
+        EventMessage message = mDelayedBlurFocusEvents[i].mEventMessage;
         nsCOMPtr<EventTarget> target = mDelayedBlurFocusEvents[i].mTarget;
         nsCOMPtr<nsIPresShell> presShell = mDelayedBlurFocusEvents[i].mPresShell;
         mDelayedBlurFocusEvents.RemoveElementAt(i);
-        SendFocusOrBlurEvent(type, presShell, aDocument, target, 0, false);
+        SendFocusOrBlurEvent(message, presShell, aDocument, target, 0, false);
         --i;
       }
     }
   }
 
   return NS_OK;
 }
 
@@ -1956,48 +1960,54 @@ nsFocusManager::Focus(nsPIDOMWindow* aWi
 
   if (clearFirstFocusEvent)
     mFirstFocusEvent = nullptr;
 }
 
 class FocusBlurEvent : public nsRunnable
 {
 public:
-  FocusBlurEvent(nsISupports* aTarget, uint32_t aType,
+  FocusBlurEvent(nsISupports* aTarget, EventMessage aEventMessage,
                  nsPresContext* aContext, bool aWindowRaised,
                  bool aIsRefocus)
-  : mTarget(aTarget), mType(aType), mContext(aContext),
-    mWindowRaised(aWindowRaised), mIsRefocus(aIsRefocus) {}
+    : mTarget(aTarget)
+    , mContext(aContext)
+    , mEventMessage(aEventMessage)
+    , mWindowRaised(aWindowRaised)
+    , mIsRefocus(aIsRefocus)
+  {
+  }
 
   NS_IMETHOD Run()
   {
-    InternalFocusEvent event(true, mType);
+    InternalFocusEvent event(true, mEventMessage);
     event.mFlags.mBubbles = false;
     event.fromRaise = mWindowRaised;
     event.isRefocus = mIsRefocus;
     return EventDispatcher::Dispatch(mTarget, mContext, &event);
   }
 
   nsCOMPtr<nsISupports>   mTarget;
-  uint32_t                mType;
   nsRefPtr<nsPresContext> mContext;
+  EventMessage            mEventMessage;
   bool                    mWindowRaised;
   bool                    mIsRefocus;
 };
 
 void
-nsFocusManager::SendFocusOrBlurEvent(uint32_t aType,
+nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage,
                                      nsIPresShell* aPresShell,
                                      nsIDocument* aDocument,
                                      nsISupports* aTarget,
                                      uint32_t aFocusMethod,
                                      bool aWindowRaised,
                                      bool aIsRefocus)
 {
-  NS_ASSERTION(aType == NS_FOCUS_CONTENT || aType == NS_BLUR_CONTENT,
+  NS_ASSERTION(aEventMessage == NS_FOCUS_CONTENT ||
+               aEventMessage == NS_BLUR_CONTENT,
                "Wrong event type for SendFocusOrBlurEvent");
 
   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
 
   nsCOMPtr<nsINode> n = do_QueryInterface(aTarget);
   if (!n) {
     nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aTarget);
     n = win ? win->GetExtantDoc() : nullptr;
@@ -2010,42 +2020,44 @@ nsFocusManager::SendFocusOrBlurEvent(uin
   if (aFocusMethod && !dontDispatchEvent &&
       aDocument && aDocument->EventHandlingSuppressed()) {
     // aFlags is always 0 when aWindowRaised is true so this won't be called
     // on a window raise.
     NS_ASSERTION(!aWindowRaised, "aWindowRaised should not be set");
 
     for (uint32_t i = mDelayedBlurFocusEvents.Length(); i > 0; --i) {
       // if this event was already queued, remove it and append it to the end
-      if (mDelayedBlurFocusEvents[i - 1].mType == aType &&
+      if (mDelayedBlurFocusEvents[i - 1].mEventMessage == aEventMessage &&
           mDelayedBlurFocusEvents[i - 1].mPresShell == aPresShell &&
           mDelayedBlurFocusEvents[i - 1].mDocument == aDocument &&
           mDelayedBlurFocusEvents[i - 1].mTarget == eventTarget) {
         mDelayedBlurFocusEvents.RemoveElementAt(i - 1);
       }
     }
 
     mDelayedBlurFocusEvents.AppendElement(
-      nsDelayedBlurOrFocusEvent(aType, aPresShell, aDocument, eventTarget));
+      nsDelayedBlurOrFocusEvent(aEventMessage, aPresShell,
+                                aDocument, eventTarget));
     return;
   }
 
 #ifdef ACCESSIBILITY
   nsAccessibilityService* accService = GetAccService();
   if (accService) {
-    if (aType == NS_FOCUS_CONTENT)
+    if (aEventMessage == NS_FOCUS_CONTENT) {
       accService->NotifyOfDOMFocus(aTarget);
-    else
+    } else {
       accService->NotifyOfDOMBlur(aTarget);
+    }
   }
 #endif
 
   if (!dontDispatchEvent) {
     nsContentUtils::AddScriptRunner(
-      new FocusBlurEvent(aTarget, aType, aPresShell->GetPresContext(),
+      new FocusBlurEvent(aTarget, aEventMessage, aPresShell->GetPresContext(),
                          aWindowRaised, aIsRefocus));
   }
 }
 
 void
 nsFocusManager::ScrollIntoView(nsIPresShell* aPresShell,
                                nsIContent* aContent,
                                uint32_t aFlags)
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -275,22 +275,22 @@ protected:
              bool aIsNewDocument,
              bool aFocusChanged,
              bool aWindowRaised,
              bool aAdjustWidget);
 
   /**
    * Fires a focus or blur event at aTarget.
    *
-   * aType should be either NS_FOCUS_CONTENT or NS_BLUR_CONTENT. For blur
-   * events, aFocusMethod should normally be non-zero.
+   * aEventMessage should be either NS_FOCUS_CONTENT or NS_BLUR_CONTENT.
+   * For blur events, aFocusMethod should normally be non-zero.
    *
    * aWindowRaised should only be true if called from WindowRaised.
    */
-  void SendFocusOrBlurEvent(uint32_t aType,
+  void SendFocusOrBlurEvent(mozilla::EventMessage aEventMessage,
                             nsIPresShell* aPresShell,
                             nsIDocument* aDocument,
                             nsISupports* aTarget,
                             uint32_t aFocusMethod,
                             bool aWindowRaised,
                             bool aIsRefocus = false);
 
   /**
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3039,17 +3039,17 @@ nsGlobalWindow::GetJSContextForEventHand
   return nullptr;
 }
 
 nsresult
 nsGlobalWindow::PreHandleEvent(EventChainPreVisitor& aVisitor)
 {
   NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
   static uint32_t count = 0;
-  uint32_t msg = aVisitor.mEvent->mMessage;
+  EventMessage msg = aVisitor.mEvent->mMessage;
 
   aVisitor.mCanHandle = true;
   aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
   if ((msg == NS_MOUSE_MOVE) && gEntropyCollector) {
     //Chances are this counter will overflow during the life of the
     //process, but that's OK for our case. Means we get a little
     //more entropy.
     if (count++ % 100 == 0) {
@@ -6613,17 +6613,16 @@ nsGlobalWindow::FinishFullscreenChange(b
 
     ErrorResult rv;
     mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"),
                                        this, rv);
     NS_WARN_IF_FALSE(!rv.Failed(), "Failed to lock the wakelock");
   } else if (mWakeLock && !mFullScreen) {
     ErrorResult rv;
     mWakeLock->Unlock(rv);
-    NS_WARN_IF_FALSE(!rv.Failed(), "Failed to unlock the wakelock.");
     mWakeLock = nullptr;
   }
 }
 
 bool
 nsGlobalWindow::FullScreen() const
 {
   MOZ_ASSERT(IsOuterWindow());
@@ -14528,17 +14527,17 @@ bool
 nsGlobalWindow::GetIsPrerendered()
 {
   nsIDocShell* docShell = GetDocShell();
   return docShell && docShell->GetIsPrerendered();
 }
 
 #ifdef MOZ_B2G
 void
-nsGlobalWindow::EnableNetworkEvent(uint32_t aType)
+nsGlobalWindow::EnableNetworkEvent(EventMessage aEventMessage)
 {
   MOZ_ASSERT(IsInnerWindow());
 
   nsCOMPtr<nsIPermissionManager> permMgr =
     services::GetPermissionManager();
   if (!permMgr) {
     NS_ERROR("No PermissionManager available!");
     return;
@@ -14553,55 +14552,59 @@ nsGlobalWindow::EnableNetworkEvent(uint3
   }
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (!os) {
     NS_ERROR("ObserverService should be available!");
     return;
   }
 
-  switch (aType) {
+  switch (aEventMessage) {
     case NS_NETWORK_UPLOAD_EVENT:
       if (!mNetworkUploadObserverEnabled) {
         mNetworkUploadObserverEnabled = true;
         os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC, false);
       }
       break;
     case NS_NETWORK_DOWNLOAD_EVENT:
       if (!mNetworkDownloadObserverEnabled) {
         mNetworkDownloadObserverEnabled = true;
         os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, false);
       }
       break;
-  }
-}
-
-void
-nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
+    default:
+      break;
+  }
+}
+
+void
+nsGlobalWindow::DisableNetworkEvent(EventMessage aEventMessage)
 {
   MOZ_ASSERT(IsInnerWindow());
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (!os) {
     return;
   }
 
-  switch (aType) {
+  switch (aEventMessage) {
     case NS_NETWORK_UPLOAD_EVENT:
       if (mNetworkUploadObserverEnabled) {
         mNetworkUploadObserverEnabled = false;
         os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC);
       }
       break;
     case NS_NETWORK_DOWNLOAD_EVENT:
       if (mNetworkDownloadObserverEnabled) {
         mNetworkDownloadObserverEnabled = false;
         os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC);
       }
       break;
+    default:
+      break;
   }
 }
 #endif // MOZ_B2G
 
 void
 nsGlobalWindow::RedefineProperty(JSContext* aCx, const char* aPropName,
                                  JS::Handle<JS::Value> aValue,
                                  ErrorResult& aError)
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -672,18 +672,19 @@ public:
   virtual void EnableDeviceSensor(uint32_t aType) override;
   virtual void DisableDeviceSensor(uint32_t aType) override;
 
   virtual void EnableTimeChangeNotifications() override;
   virtual void DisableTimeChangeNotifications() override;
 
 #ifdef MOZ_B2G
   // Inner windows only.
-  virtual void EnableNetworkEvent(uint32_t aType) override;
-  virtual void DisableNetworkEvent(uint32_t aType) override;
+  virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) override;
+  virtual void DisableNetworkEvent(
+                 mozilla::EventMessage aEventMessage) override;
 #endif // MOZ_B2G
 
   virtual nsresult SetArguments(nsIArray* aArguments) override;
 
   void MaybeForgiveSpamCount();
   bool IsClosedOrClosing() {
     return (mIsClosed ||
             mInClose ||
--- a/dom/base/nsGlobalWindowCommands.cpp
+++ b/dom/base/nsGlobalWindowCommands.cpp
@@ -515,23 +515,25 @@ nsClipboardCommand::DoCommand(const char
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
-  int32_t eventType = NS_COPY;
+  EventMessage eventMessage = NS_COPY;
   if (strcmp(aCommandName, "cmd_cut") == 0) {
-    eventType = NS_CUT;
+    eventMessage = NS_CUT;
   }
 
   bool actionTaken = false;
-  nsCopySupport::FireClipboardEvent(eventType, nsIClipboard::kGlobalClipboard, presShell, nullptr, &actionTaken);
+  nsCopySupport::FireClipboardEvent(eventMessage,
+                                    nsIClipboard::kGlobalClipboard,
+                                    presShell, nullptr, &actionTaken);
 
   if (!strcmp(aCommandName, "cmd_copyAndCollapseToEnd")) {
     dom::Selection *sel =
       presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
     NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE);
     sel->CollapseToEnd();
   }
 
--- a/dom/base/nsIObjectLoadingContent.idl
+++ b/dom/base/nsIObjectLoadingContent.idl
@@ -20,17 +20,17 @@ class nsNPAPIPluginInstance;
 
 /**
  * This interface represents a content node that loads objects.
  *
  * Please make sure to update the MozObjectLoadingContent WebIDL
  * interface to mirror this interface when changing it.
  */
 
-[scriptable, uuid(5efbd411-5bbe-4de1-9f3a-1c3459696eb2)]
+[scriptable, uuid(2eb3195e-3eea-4083-bb1d-d2d70fa35ccb)]
 interface nsIObjectLoadingContent : nsISupports
 {
   /**
    * See notes in nsObjectLoadingContent.h
    */
   const unsigned long TYPE_LOADING  = 0;
   const unsigned long TYPE_IMAGE    = 1;
   const unsigned long TYPE_PLUGIN   = 2;
@@ -60,18 +60,16 @@ interface nsIObjectLoadingContent : nsIS
   /// ** Furthermore, values >= PLUGIN_CLICK_TO_PLAY and
   ///    <= PLUGIN_VULNERABLE_NO_UPDATE are click-to-play types.
   // The plugin is disabled until the user clicks on it
   const unsigned long PLUGIN_CLICK_TO_PLAY        = 8;
   // The plugin is vulnerable (update available)
   const unsigned long PLUGIN_VULNERABLE_UPDATABLE = 9;
   // The plugin is vulnerable (no update available)
   const unsigned long PLUGIN_VULNERABLE_NO_UPDATE = 10;
-  // The plugin is in play preview mode
-  const unsigned long PLUGIN_PLAY_PREVIEW         = 11;
 
   /**
    * The actual mime type (the one we got back from the network
    * request) for the element.
    */
   readonly attribute ACString actualType;
 
   /**
@@ -123,33 +121,32 @@ interface nsIObjectLoadingContent : nsIS
    */
   [noscript] void pluginDestroyed();
   [noscript] void pluginCrashed(in nsIPluginTag pluginTag,
                                 in AString pluginDumpID,
                                 in AString browserDumpID,
                                 in boolean submittedCrashReport);
 
   /**
-   * This method will play a plugin that has been stopped by the
-   * click-to-play plugins or play-preview features.
+   * This method will play a plugin that has been stopped by click-to-play.
    */
   void playPlugin();
 
   /**
    * Forces a re-evaluation and reload of the tag, optionally invalidating its
    * click-to-play state.  This can be used when the MIME type that provides a
    * type has changed, for instance, to force the tag to re-evalulate the
    * handler to use.
    */
   void reload(in boolean aClearActivation);
 
   /**
    * This attribute will return true if the current content type has been
    * activated, either explicitly or by passing checks that would have it be
-   * click-to-play or play-preview.
+   * click-to-play.
    */
   readonly attribute boolean activated;
 
   [noscript] void stopPluginInstance();
 
   [noscript] void syncStartPluginInstance();
   [noscript] void asyncStartPluginInstance();
 
@@ -180,20 +177,15 @@ interface nsIObjectLoadingContent : nsIS
 
   /**
    * If this object currently owns a running plugin, regardless of whether or
    * not one is pending spawn/despawn.
    */
   readonly attribute bool hasRunningPlugin;
 
   /**
-   * This method will disable the play-preview plugin state.
-   */
-  void cancelPlayPreview();
-
-  /**
    * If this plugin runs out-of-process, it has a runID to differentiate
    * between different times the plugin process has been instantiated.
    *
    * This throws NS_ERROR_NOT_IMPLEMENTED for in-process plugins.
    */
   readonly attribute unsigned long runID;
 };
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -710,17 +710,16 @@ nsObjectLoadingContent::nsObjectLoadingC
   : mType(eType_Loading)
   , mFallbackType(eFallbackAlternate)
   , mRunID(0)
   , mHasRunID(false)
   , mChannelLoaded(false)
   , mInstantiating(false)
   , mNetworkCreated(true)
   , mActivated(false)
-  , mPlayPreviewCanceled(false)
   , mIsStopping(false)
   , mIsLoading(false)
   , mScriptRequested(false) {}
 
 nsObjectLoadingContent::~nsObjectLoadingContent()
 {
   // Should have been unbound from the tree at this point, and
   // CheckPluginStopEvent keeps us alive
@@ -1401,18 +1400,16 @@ nsObjectLoadingContent::ObjectState() co
     case eType_Null:
       switch (mFallbackType) {
         case eFallbackSuppressed:
           return NS_EVENT_STATE_SUPPRESSED;
         case eFallbackUserDisabled:
           return NS_EVENT_STATE_USERDISABLED;
         case eFallbackClickToPlay:
           return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
-        case eFallbackPlayPreview:
-          return NS_EVENT_STATE_TYPE_PLAY_PREVIEW;
         case eFallbackDisabled:
           return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_DISABLED;
         case eFallbackBlocklisted:
           return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_BLOCKED;
         case eFallbackCrashed:
           return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_CRASHED;
         case eFallbackUnsupported: {
           // Check to see if plugins are blocked on this platform.
@@ -3117,32 +3114,31 @@ nsObjectLoadingContent::PlayPlugin()
   if (!nsContentUtils::IsCallerChrome())
     return NS_OK;
 
   if (!mActivated) {
     mActivated = true;
     LOG(("OBJLC [%p]: Activated by user", this));
   }
 
-  // If we're in a click-to-play or play preview state, we need to reload
+  // If we're in a click-to-play state, reload.
   // Fallback types >= eFallbackClickToPlay are plugin-replacement types, see
   // header
   if (mType == eType_Null && mFallbackType >= eFallbackClickToPlay) {
     return LoadObject(true, true);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::Reload(bool aClearActivation)
 {
   if (aClearActivation) {
     mActivated = false;
-    mPlayPreviewCanceled = false;
   }
 
   return LoadObject(true, true);
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::GetActivated(bool *aActivated)
 {
@@ -3173,32 +3169,16 @@ NS_IMETHODIMP
 nsObjectLoadingContent::GetHasRunningPlugin(bool *aHasPlugin)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
   *aHasPlugin = HasRunningPlugin();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsObjectLoadingContent::CancelPlayPreview()
-{
-  if (!nsContentUtils::IsCallerChrome())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  mPlayPreviewCanceled = true;
-
-  // If we're in play preview state already, reload
-  if (mType == eType_Null && mFallbackType == eFallbackPlayPreview) {
-    return LoadObject(true, true);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsObjectLoadingContent::GetRunID(uint32_t* aRunID)
 {
   if (NS_WARN_IF(!nsContentUtils::IsCallerChrome())) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   if (NS_WARN_IF(!aRunID)) {
     return NS_ERROR_INVALID_POINTER;
   }
@@ -3233,52 +3213,25 @@ nsObjectLoadingContent::ShouldPlay(Fallb
     // Plugins running OOP from the chrome process along with plugins running
     // OOP from the content process will hang. Let's prevent that situation.
     aReason = eFallbackDisabled;
     return false;
   }
 
   nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
 
-  nsCOMPtr<nsIPluginPlayPreviewInfo> playPreviewInfo;
-  bool isPlayPreviewSpecified = NS_SUCCEEDED(pluginHost->GetPlayPreviewInfo(
-    mContentType, getter_AddRefs(playPreviewInfo)));
-  if (isPlayPreviewSpecified) {
-    // Checking PlayPreview whitelist as well.
-    nsCString uriSpec, baseSpec;
-    if (mURI) {
-      mURI->GetSpec(uriSpec);
-    }
-    if (mBaseURI) {
-      mBaseURI->GetSpec(baseSpec);
-    }
-    playPreviewInfo->CheckWhitelist(baseSpec, uriSpec, &isPlayPreviewSpecified);
-  }
-  bool ignoreCTP = false;
-  if (isPlayPreviewSpecified) {
-    playPreviewInfo->GetIgnoreCTP(&ignoreCTP);
-  }
-  if (isPlayPreviewSpecified && !mPlayPreviewCanceled &&
-      ignoreCTP) {
-    // play preview in ignoreCTP mode is shown even if the native plugin
-    // is not present/installed
-    aReason = eFallbackPlayPreview;
-    return false;
-  }
   // at this point if it's not a plugin, we let it play/fallback
   if (!aIgnoreCurrentType && mType != eType_Plugin) {
     return true;
   }
 
   // Order of checks:
   // * Assume a default of click-to-play
   // * If globally disabled, per-site permissions cannot override.
   // * If blocklisted, override the reason with the blocklist reason
-  // * If not blocklisted but playPreview, override the reason with the
-  //   playPreview reason.
   // * Check per-site permissions and follow those if specified.
   // * Honor per-plugin disabled permission
   // * Blocklisted plugins are forced to CtP
   // * Check per-plugin permission and follow that.
 
   aReason = eFallbackClickToPlay;
 
   uint32_t enabledState = nsIPluginTag::STATE_DISABLED;
@@ -3304,22 +3257,16 @@ nsObjectLoadingContent::ShouldPlay(Fallb
 
   if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
     aReason = eFallbackVulnerableUpdatable;
   }
   else if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
     aReason = eFallbackVulnerableNoUpdate;
   }
 
-  if (aReason == eFallbackClickToPlay && isPlayPreviewSpecified &&
-      !mPlayPreviewCanceled && !ignoreCTP) {
-    // play preview in click-to-play mode is shown instead of standard CTP UI
-    aReason = eFallbackPlayPreview;
-  }
-
   // Check the permission manager for permission based on the principal of
   // the toplevel content.
 
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
   MOZ_ASSERT(thisContent);
   nsIDocument* ownerDoc = thisContent->OwnerDoc();
 
   nsCOMPtr<nsIDOMWindow> window = ownerDoc->GetWindow();
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -89,19 +89,16 @@ class nsObjectLoadingContent : public ns
       /// ** Furthermore, values >= eFallbackClickToPlay and
       ///    <= eFallbackVulnerableNoUpdate are click-to-play types.
       // The plugin is disabled until the user clicks on it
       eFallbackClickToPlay = nsIObjectLoadingContent::PLUGIN_CLICK_TO_PLAY,
       // The plugin is vulnerable (update available)
       eFallbackVulnerableUpdatable = nsIObjectLoadingContent::PLUGIN_VULNERABLE_UPDATABLE,
       // The plugin is vulnerable (no update available)
       eFallbackVulnerableNoUpdate = nsIObjectLoadingContent::PLUGIN_VULNERABLE_NO_UPDATE,
-      // The plugin is disabled and play preview content is displayed until
-      // the extension code enables it by sending the MozPlayPlugin event
-      eFallbackPlayPreview = nsIObjectLoadingContent::PLUGIN_PLAY_PREVIEW
     };
 
     nsObjectLoadingContent();
     virtual ~nsObjectLoadingContent();
 
     NS_DECL_NSIREQUESTOBSERVER
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIFRAMELOADEROWNER
@@ -220,20 +217,16 @@ class nsObjectLoadingContent : public ns
     uint32_t PluginFallbackType() const
     {
       return mFallbackType;
     }
     bool HasRunningPlugin() const
     {
       return !!mInstanceOwner;
     }
-    void CancelPlayPreview(mozilla::ErrorResult& aRv)
-    {
-      aRv = CancelPlayPreview();
-    }
     void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aRv)
     {
       aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
     }
     void LegacyCall(JSContext* aCx, JS::Handle<JS::Value> aThisVal,
                     const mozilla::dom::Sequence<JS::Value>& aArguments,
                     JS::MutableHandle<JS::Value> aRetval,
                     mozilla::ErrorResult& aRv);
@@ -617,26 +610,23 @@ class nsObjectLoadingContent : public ns
     // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
     // it may lose the flag.
     bool                        mNetworkCreated : 1;
 
     // Used to keep track of whether or not a plugin has been explicitly
     // activated by PlayPlugin(). (see ShouldPlay())
     bool                        mActivated : 1;
 
-    // Used to keep track of whether or not a plugin is blocked by play-preview.
-    bool                        mPlayPreviewCanceled : 1;
-
     // Protects DoStopPlugin from reentry (bug 724781).
     bool                        mIsStopping : 1;
 
     // Protects LoadObject from re-entry
     bool                        mIsLoading : 1;
 
-    // For plugin stand-in types (click-to-play, play preview, ...) tracks
+    // For plugin stand-in types (click-to-play) tracks
     // whether content js has tried to access the plugin script object.
     bool                        mScriptRequested : 1;
 
     nsWeakFrame                 mPrintFrame;
 
     nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
     nsTArray<mozilla::dom::MozPluginParameter> mCachedAttributes;
     nsTArray<mozilla::dom::MozPluginParameter> mCachedParameters;
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -57,18 +57,18 @@ enum PopupControlState {
 enum UIStateChangeType
 {
   UIStateChangeType_NoChange,
   UIStateChangeType_Set,
   UIStateChangeType_Clear
 };
 
 #define NS_PIDOMWINDOW_IID \
-{ 0x2aebbbd7, 0x154b, 0x4341, \
-  { 0x8d, 0x02, 0x7f, 0x70, 0xf8, 0x3e, 0xf7, 0xa1 } }
+{ 0x052e675a, 0xacd3, 0x48d1, \
+  { 0x8a, 0xcd, 0xbf, 0xff, 0xbd, 0x24, 0x4c, 0xed } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
@@ -638,25 +638,25 @@ public:
 
 #ifdef MOZ_B2G
   /**
    * Tell the window that it should start to listen to the network event of the
    * given aType.
    *
    * Inner windows only.
    */
-  virtual void EnableNetworkEvent(uint32_t aType) = 0;
+  virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) = 0;
 
   /**
    * Tell the window that it should stop to listen to the network event of the
    * given aType.
    *
    * Inner windows only.
    */
-  virtual void DisableNetworkEvent(uint32_t aType) = 0;
+  virtual void DisableNetworkEvent(mozilla::EventMessage aEventMessage) = 0;
 #endif // MOZ_B2G
 
   /**
    * Tell this window that there is an observer for gamepad input
    *
    * Inner windows only.
    */
   virtual void SetHasGamepadEventListener(bool aHasGamepad = true) = 0;
--- a/dom/base/nsScriptElement.cpp
+++ b/dom/base/nsScriptElement.cpp
@@ -54,20 +54,20 @@ nsScriptElement::ScriptEvaluated(nsresul
   if (!aIsInline) {
     nsCOMPtr<nsIContent> cont =
       do_QueryInterface((nsIScriptElement*) this);
 
     nsRefPtr<nsPresContext> presContext =
       nsContentUtils::GetContextForContent(cont);
 
     nsEventStatus status = nsEventStatus_eIgnore;
-    uint32_t type = NS_SUCCEEDED(aResult) ? NS_LOAD : NS_LOAD_ERROR;
-    WidgetEvent event(true, type);
+    EventMessage message = NS_SUCCEEDED(aResult) ? NS_LOAD : NS_LOAD_ERROR;
+    WidgetEvent event(true, message);
     // Load event doesn't bubble.
-    event.mFlags.mBubbles = (type != NS_LOAD);
+    event.mFlags.mBubbles = (message != NS_LOAD);
 
     EventDispatcher::Dispatch(cont, presContext, &event, nullptr, &status);
   }
 
   return rv;
 }
 
 void
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -631,52 +631,59 @@ nsScriptLoader::ProcessScriptElement(nsI
           SRICheck::IntegrityMetadata(integrity, mDocument, &sriMetadata);
         }
       }
 
       request = new nsScriptLoadRequest(aElement, version, ourCORSMode,
                                         sriMetadata);
       request->mURI = scriptURI;
       request->mIsInline = false;
-      request->mLoading = true;
+      request->mProgress = nsScriptLoadRequest::Progress_Loading;
       request->mReferrerPolicy = ourRefPolicy;
 
       // set aScriptFromHead to false so we don't treat non preloaded scripts as
       // blockers for full page load. See bug 792438.
       rv = StartLoad(request, type, false);
       if (NS_FAILED(rv)) {
         // Asynchronously report the load failure
         NS_DispatchToCurrentThread(
           NS_NewRunnableMethod(aElement,
                                &nsIScriptElement::FireErrorEvent));
         return false;
       }
     }
 
+    // Should still be in loading stage of script.
+    NS_ASSERTION(!request->InCompilingStage(),
+                 "Request should not yet be in compiling stage.");
+
     request->mJSVersion = version;
 
     if (aElement->GetScriptAsync()) {
       request->mIsAsync = true;
-      if (!request->mLoading) {
+      if (request->IsDoneLoading()) {
         mLoadedAsyncRequests.AppendElement(request);
         // The script is available already. Run it ASAP when the event
         // loop gets a chance to spin.
+
+        // KVKV TODO: Instead of processing immediately, try off-thread-parsing
+        // it and only schedule a ProcessRequest if that fails.
         ProcessPendingRequestsAsync();
       } else {
         mLoadingAsyncRequests.AppendElement(request);
       }
       return false;
     }
     if (!aElement->GetParserCreated()) {
       // Violate the HTML5 spec in order to make LABjs and the "order" plug-in
       // for RequireJS work with their Gecko-sniffed code path. See
       // http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
       request->mIsNonAsyncScriptInserted = true;
       mNonAsyncExternalScriptInsertedRequests.AppendElement(request);
-      if (!request->mLoading) {
+      if (request->IsDoneLoading()) {
         // The script is available already. Run it ASAP when the event
         // loop gets a chance to spin.
         ProcessPendingRequestsAsync();
       }
       return false;
     }
     // we now have a parser-inserted request that may or may not be still
     // loading
@@ -695,24 +702,24 @@ nsScriptLoader::ProcessScriptElement(nsI
     }
 
     if (aElement->GetParserCreated() == FROM_PARSER_XSLT) {
       // Need to maintain order for XSLT-inserted scripts
       NS_ASSERTION(!mParserBlockingRequest,
           "Parser-blocking scripts and XSLT scripts in the same doc!");
       request->mIsXSLT = true;
       mXSLTRequests.AppendElement(request);
-      if (!request->mLoading) {
+      if (request->IsDoneLoading()) {
         // The script is available already. Run it ASAP when the event
         // loop gets a chance to spin.
         ProcessPendingRequestsAsync();
       }
       return true;
     }
-    if (!request->mLoading && ReadyToExecuteScripts()) {
+    if (request->IsDoneLoading() && ReadyToExecuteScripts()) {
       // The request has already been loaded and there are no pending style
       // sheets. If the script comes from the network stream, cheat for
       // performance reasons and avoid a trip through the event loop.
       if (aElement->GetParserCreated() == FROM_PARSER_NETWORK) {
         return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK;
       }
       // Otherwise, we've got a document.written script, make a trip through
       // the event loop to hide the preload effects from the scripts on the
@@ -745,17 +752,17 @@ nsScriptLoader::ProcessScriptElement(nsI
   if (!CSPAllowsInlineScript(aElement, mDocument)) {
     return false;
   }
 
   // Inline scripts ignore ther CORS mode and are always CORS_NONE
   request = new nsScriptLoadRequest(aElement, version, CORS_NONE,
                                     SRIMetadata()); // SRI doesn't apply
   request->mJSVersion = version;
-  request->mLoading = false;
+  request->mProgress = nsScriptLoadRequest::Progress_DoneLoading;
   request->mIsInline = true;
   request->mURI = mDocument->GetDocumentURI();
   request->mLineNo = aElement->GetScriptLineNumber();
 
   if (aElement->GetParserCreated() == FROM_PARSER_XSLT &&
       (!ReadyToExecuteScripts() || !mXSLTRequests.isEmpty())) {
     // Need to maintain order for XSLT-inserted scripts
     NS_ASSERTION(!mParserBlockingRequest,
@@ -814,19 +821,21 @@ public:
   }
 
   NS_DECL_NSIRUNNABLE
 };
 
 } /* anonymous namespace */
 
 nsresult
-nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest, void **aOffThreadToken)
+nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest)
 {
-  nsresult rv = ProcessRequest(aRequest, aOffThreadToken);
+  MOZ_ASSERT(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling);
+  aRequest->mProgress = nsScriptLoadRequest::Progress_DoneCompiling;
+  nsresult rv = ProcessRequest(aRequest);
   mDocument->UnblockOnload(false);
   return rv;
 }
 
 NotifyOffThreadScriptLoadCompletedRunnable::~NotifyOffThreadScriptLoadCompletedRunnable()
 {
   if (MOZ_UNLIKELY(mRequest || mLoader) && !NS_IsMainThread()) {
     nsCOMPtr<nsIThread> mainThread;
@@ -848,24 +857,18 @@ NotifyOffThreadScriptLoadCompletedRunnab
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // We want these to be dropped on the main thread, once we return from this
   // function.
   nsRefPtr<nsScriptLoadRequest> request = mRequest.forget();
   nsRefPtr<nsScriptLoader> loader = mLoader.forget();
 
-  nsresult rv = loader->ProcessOffThreadRequest(request, &mToken);
-
-  if (mToken) {
-    // The result of the off thread parse was not actually needed to process
-    // the request (disappearing window, some other error, ...). Finish the
-    // request to avoid leaks in the JS engine.
-    JS::FinishOffThreadScript(nullptr, xpc::GetJSRuntime(), mToken);
-  }
+  request->mOffThreadToken = mToken;
+  nsresult rv = loader->ProcessOffThreadRequest(request);
 
   return rv;
 }
 
 static void
 OffThreadScriptLoaderCallback(void *aToken, void *aCallbackData)
 {
   nsRefPtr<NotifyOffThreadScriptLoadCompletedRunnable> aRunnable =
@@ -906,33 +909,48 @@ nsScriptLoader::AttemptAsyncScriptParse(
   if (!JS::CompileOffThread(cx, options,
                             aRequest->mScriptTextBuf, aRequest->mScriptTextLength,
                             OffThreadScriptLoaderCallback,
                             static_cast<void*>(runnable))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   mDocument->BlockOnload();
+  aRequest->mProgress = nsScriptLoadRequest::Progress_Compiling;
 
   unused << runnable.forget();
   return NS_OK;
 }
 
 nsresult
-nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadToken)
+nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
 {
   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
                "Processing requests when running scripts is unsafe.");
+  NS_ASSERTION(!aRequest->mOffThreadToken,
+               "Candidate for off-thread compile is already parsed off-thread");
+  NS_ASSERTION(!aRequest->InCompilingStage(),
+               "Candidate for off-thread compile is already in compiling stage.");
 
-  if (!aOffThreadToken) {
-    nsresult rv = AttemptAsyncScriptParse(aRequest);
-    if (rv != NS_ERROR_FAILURE)
-      return rv;
+  nsresult rv = AttemptAsyncScriptParse(aRequest);
+  if (rv != NS_ERROR_FAILURE) {
+    return rv;
   }
 
+  return ProcessRequest(aRequest);
+}
+
+nsresult
+nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
+{
+  NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
+               "Processing requests when running scripts is unsafe.");
+  NS_ASSERTION(aRequest->IsReadyToRun(),
+               "Processing a request that is not ready to run.");
+
   NS_ENSURE_ARG(aRequest);
   nsAutoString textData;
   const char16_t* scriptBuf = nullptr;
   size_t scriptLength = 0;
   JS::SourceBufferHolder::Ownership giveScriptOwnership =
     JS::SourceBufferHolder::NoOwnership;
 
   nsCOMPtr<nsIDocument> doc;
@@ -990,17 +1008,17 @@ nsScriptLoader::ProcessRequest(nsScriptL
   }
 
   nsresult rv = NS_OK;
   if (runScript) {
     if (doc) {
       doc->BeginEvaluatingExternalScript();
     }
     aRequest->mElement->BeginEvaluating();
-    rv = EvaluateScript(aRequest, srcBuf, aOffThreadToken);
+    rv = EvaluateScript(aRequest, srcBuf);
     aRequest->mElement->EndEvaluating();
     if (doc) {
       doc->EndEvaluatingExternalScript();
     }
 
     nsContentUtils::DispatchTrustedEvent(scriptElem->OwnerDoc(),
                                          scriptElem,
                                          NS_LITERAL_STRING("afterscriptexecute"),
@@ -1008,16 +1026,25 @@ nsScriptLoader::ProcessRequest(nsScriptL
   }
 
   FireScriptEvaluated(rv, aRequest);
 
   if (parserCreated) {
     mCurrentParserInsertedScript = oldParserInsertedScript;
   }
 
+  if (aRequest->mOffThreadToken) {
+    // The request was parsed off-main-thread, but the result of the off
+    // thread parse was not actually needed to process the request
+    // (disappearing window, some other error, ...). Finish the
+    // request to avoid leaks in the JS engine.
+    JS::FinishOffThreadScript(nullptr, xpc::GetJSRuntime(), aRequest->mOffThreadToken);
+    aRequest->mOffThreadToken = nullptr;
+  }
+
   return rv;
 }
 
 void
 nsScriptLoader::FireScriptAvailable(nsresult aResult,
                                     nsScriptLoadRequest* aRequest)
 {
   for (int32_t i = 0; i < mObservers.Count(); i++) {
@@ -1098,18 +1125,17 @@ nsScriptLoader::FillCompileOptionsForReq
                                               /* aAllowWrapping = */ true))) {
     MOZ_ASSERT(elementVal.isObject());
     aOptions->setElement(&elementVal.toObject());
   }
 }
 
 nsresult
 nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
-                               JS::SourceBufferHolder& aSrcBuf,
-                               void** aOffThreadToken)
+                               JS::SourceBufferHolder& aSrcBuf)
 {
   // We need a document to evaluate scripts.
   if (!mDocument) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIContent> scriptContent(do_QueryInterface(aRequest->mElement));
   nsIDocument* ownerDoc = scriptContent->OwnerDoc();
@@ -1164,17 +1190,17 @@ nsScriptLoader::EvaluateScript(nsScriptL
       // of the master document too.
       masterScriptUpdater.emplace(master->ScriptLoader(),
                                   aRequest->mElement);
     }
 
     JS::CompileOptions options(entryScript.cx());
     FillCompileOptionsForRequest(entryScript, aRequest, global, &options);
     rv = nsJSUtils::EvaluateString(entryScript.cx(), aSrcBuf, global, options,
-                                   aOffThreadToken);
+                                   aRequest->OffThreadTokenPtr());
   }
 
   context->SetProcessingScriptTag(oldProcessingScriptTag);
   return rv;
 }
 
 void
 nsScriptLoader::ProcessPendingRequestsAsync()
@@ -1186,49 +1212,50 @@ nsScriptLoader::ProcessPendingRequestsAs
     NS_DispatchToCurrentThread(ev);
   }
 }
 
 void
 nsScriptLoader::ProcessPendingRequests()
 {
   nsRefPtr<nsScriptLoadRequest> request;
+
   if (mParserBlockingRequest &&
-      !mParserBlockingRequest->mLoading &&
+      mParserBlockingRequest->IsReadyToRun() &&
       ReadyToExecuteScripts()) {
     request.swap(mParserBlockingRequest);
     UnblockParser(request);
     ProcessRequest(request);
     ContinueParserAsync(request);
   }
 
   while (ReadyToExecuteScripts() && 
          !mXSLTRequests.isEmpty() &&
-         !mXSLTRequests.getFirst()->mLoading) {
+         mXSLTRequests.getFirst()->IsReadyToRun()) {
     request = mXSLTRequests.StealFirst();
     ProcessRequest(request);
   }
 
   while (mEnabled && !mLoadedAsyncRequests.isEmpty()) {
     request = mLoadedAsyncRequests.StealFirst();
-    ProcessRequest(request);
+    CompileOffThreadOrProcessRequest(request);
   }
 
   while (mEnabled && !mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
-         !mNonAsyncExternalScriptInsertedRequests.getFirst()->mLoading) {
+         mNonAsyncExternalScriptInsertedRequests.getFirst()->IsReadyToRun()) {
     // Violate the HTML5 spec and execute these in the insertion order in
     // order to make LABjs and the "order" plug-in for RequireJS work with
     // their Gecko-sniffed code path. See
     // http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
     request = mNonAsyncExternalScriptInsertedRequests.StealFirst();
     ProcessRequest(request);
   }
 
   if (mDocumentParsingDone && mXSLTRequests.isEmpty()) {
-    while (!mDeferRequests.isEmpty() && !mDeferRequests.getFirst()->mLoading) {
+    while (!mDeferRequests.isEmpty() && mDeferRequests.getFirst()->IsReadyToRun()) {
       request = mDeferRequests.StealFirst();
       ProcessRequest(request);
     }
   }
 
   while (!mPendingChildLoaders.IsEmpty() && ReadyToExecuteScripts()) {
     nsRefPtr<nsScriptLoader> child = mPendingChildLoaders[0];
     mPendingChildLoaders.RemoveElementAt(0);
@@ -1431,20 +1458,26 @@ nsScriptLoader::OnStreamComplete(nsIStre
                                  nsresult aStatus,
                                  uint32_t aStringLen,
                                  const uint8_t* aString)
 {
   nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
   NS_ASSERTION(request, "null request in stream complete handler");
   NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
 
+  nsCOMPtr<nsIHttpChannel> httpChannel;
+  {
+    nsCOMPtr<nsIRequest> req;
+    aLoader->GetRequest(getter_AddRefs(req));
+    httpChannel = do_QueryInterface(req);
+  } // throw away req, we only need the channel
+
   nsresult rv = NS_ERROR_SRI_CORRUPT;
   if (request->mIntegrity.IsEmpty() ||
-      NS_SUCCEEDED(SRICheck::VerifyIntegrity(request->mIntegrity,
-                                             request->mURI,
+      NS_SUCCEEDED(SRICheck::VerifyIntegrity(request->mIntegrity, httpChannel,
                                              request->mCORSMode, aStringLen,
                                              aString, mDocument))) {
     rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen, aString);
   }
 
   if (NS_FAILED(rv)) {
     /*
      * Handle script not loading error because source was a tracking URL.
@@ -1587,17 +1620,17 @@ nsScriptLoader::PrepareLoadedRequest(nsS
                mLoadingAsyncRequests.Contains(aRequest) ||
                mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) ||
                mXSLTRequests.Contains(aRequest)  ||
                mPreloads.Contains(aRequest, PreloadRequestComparator()) ||
                mParserBlockingRequest,
                "aRequest should be pending!");
 
   // Mark this as loaded
-  aRequest->mLoading = false;
+  aRequest->mProgress = nsScriptLoadRequest::Progress_DoneLoading;
 
   // And if it's async, move it to the loaded list.  aRequest->mIsAsync really
   // _should_ be in a list, but the consequences if it's not are bad enough we
   // want to avoid trying to move it if it's not.
   if (aRequest->mIsAsync) {
     MOZ_ASSERT(aRequest->isInList());
     if (aRequest->isInList()) {
       nsRefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
@@ -1656,17 +1689,17 @@ nsScriptLoader::PreloadURI(nsIURI *aURI,
   }
 
   nsRefPtr<nsScriptLoadRequest> request =
     new nsScriptLoadRequest(nullptr, 0,
                             Element::StringToCORSMode(aCrossOrigin),
                             sriMetadata);
   request->mURI = aURI;
   request->mIsInline = false;
-  request->mLoading = true;
+  request->mProgress = nsScriptLoadRequest::Progress_Loading;
   request->mReferrerPolicy = aReferrerPolicy;
 
   nsresult rv = StartLoad(request, aType, aScriptFromHead);
   if (NS_FAILED(rv)) {
     return;
   }
 
   PreloadInfo *pi = mPreloads.AppendElement();
--- a/dom/base/nsScriptLoader.h
+++ b/dom/base/nsScriptLoader.h
@@ -55,24 +55,25 @@ class nsScriptLoadRequest final : public
   friend class nsScriptLoadRequestList;
 
 public:
   nsScriptLoadRequest(nsIScriptElement* aElement,
                       uint32_t aVersion,
                       mozilla::CORSMode aCORSMode,
                       const mozilla::dom::SRIMetadata &aIntegrity)
     : mElement(aElement),
-      mLoading(true),
+      mProgress(Progress_Loading),
       mIsInline(true),
       mHasSourceMapURL(false),
       mIsDefer(false),
       mIsAsync(false),
       mIsNonAsyncScriptInserted(false),
       mIsXSLT(false),
       mIsCanceled(false),
+      mOffThreadToken(nullptr),
       mScriptTextBuf(nullptr),
       mScriptTextLength(0),
       mJSVersion(aVersion),
       mLineNo(1),
       mCORSMode(aCORSMode),
       mIntegrity(aIntegrity),
       mReferrerPolicy(mozilla::net::RP_Default)
   {
@@ -99,28 +100,51 @@ public:
     mIsCanceled = true;
   }
 
   bool IsCanceled() const
   {
     return mIsCanceled;
   }
 
+  void** OffThreadTokenPtr()
+  {
+    return mOffThreadToken ?  &mOffThreadToken : nullptr;
+  }
+
+  enum Progress {
+    Progress_Loading,
+    Progress_DoneLoading,
+    Progress_Compiling,
+    Progress_DoneCompiling
+  };
+  bool IsReadyToRun() {
+    return mProgress == Progress_DoneLoading ||
+           mProgress == Progress_DoneCompiling;
+  }
+  bool IsDoneLoading() {
+    return mProgress == Progress_DoneLoading;
+  }
+  bool InCompilingStage() {
+    return (mProgress == Progress_Compiling) || (mProgress == Progress_DoneCompiling);
+  }
+
   using super::getNext;
   using super::isInList;
 
   nsCOMPtr<nsIScriptElement> mElement;
-  bool mLoading;          // Are we still waiting for a load to complete?
+  Progress mProgress;     // Are we still waiting for a load to complete?
   bool mIsInline;         // Is the script inline or loaded?
   bool mHasSourceMapURL;  // Does the HTTP header have a source map url?
   bool mIsDefer;          // True if we live in mDeferRequests.
   bool mIsAsync;          // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
   bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
   bool mIsXSLT;           // True if we live in mXSLTRequests.
   bool mIsCanceled;       // True if we have been explicitly canceled.
+  void* mOffThreadToken;  // Off-thread parsing token.
   nsString mSourceMapURL; // Holds source map url for loaded scripts
   char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
   size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
   uint32_t mJSVersion;
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIPrincipal> mOriginPrincipal;
   nsAutoCString mURL;   // Keep the URI's filename alive during off thread parsing.
   int32_t mLineNo;
@@ -380,18 +404,17 @@ public:
                           const nsAString& aIntegrity,
                           bool aScriptFromHead,
                           const mozilla::net::ReferrerPolicy aReferrerPolicy);
 
   /**
    * Process a request that was deferred so that the script could be compiled
    * off thread.
    */
-  nsresult ProcessOffThreadRequest(nsScriptLoadRequest *aRequest,
-                                   void **aOffThreadToken);
+  nsresult ProcessOffThreadRequest(nsScriptLoadRequest *aRequest);
 
   bool AddPendingChildLoader(nsScriptLoader* aChild) {
     return mPendingChildLoaders.AppendElement(aChild) != nullptr;
   }
 
 private:
   virtual ~nsScriptLoader();
 
@@ -441,25 +464,24 @@ private:
    * Return whether just this loader is ready to execute scripts.
    */
   bool SelfReadyToExecuteScripts()
   {
     return mEnabled && !mBlockerCount;
   }
 
   nsresult AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest);
-  nsresult ProcessRequest(nsScriptLoadRequest* aRequest,
-                          void **aOffThreadToken = nullptr);
+  nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
+  nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest);
   void FireScriptAvailable(nsresult aResult,
                            nsScriptLoadRequest* aRequest);
   void FireScriptEvaluated(nsresult aResult,
                            nsScriptLoadRequest* aRequest);
   nsresult EvaluateScript(nsScriptLoadRequest* aRequest,
-                          JS::SourceBufferHolder& aSrcBuf,
-                          void **aOffThreadToken);
+                          JS::SourceBufferHolder& aSrcBuf);
 
   already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
   void FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI &jsapi,
                                     nsScriptLoadRequest *aRequest,
                                     JS::Handle<JSObject *> aScopeChain,
                                     JS::CompileOptions *aOptions);
 
   nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -8,170 +8,220 @@
 
 #include "nsCOMPtr.h"
 #include "nsIGlobalObject.h"
 #include "nsIVariant.h"
 #include "nsIXPConnect.h"
 #include "nsServiceManagerUtils.h"
 #include "nsContentUtils.h"
 #include "jsapi.h"
-#include "jsfriendapi.h"
-#include "js/StructuredClone.h"
 #include "xpcpublic.h"
 
 #include "mozilla/Base64.h"
+#include "mozilla/dom/StructuredCloneHelper.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 NS_IMPL_ADDREF(nsStructuredCloneContainer)
 NS_IMPL_RELEASE(nsStructuredCloneContainer)
 
 NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
   NS_INTERFACE_MAP_ENTRY(nsIStructuredCloneContainer)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 nsStructuredCloneContainer::nsStructuredCloneContainer()
-  : mData(nullptr), mSize(0), mVersion(0)
+  : StructuredCloneHelper(CloningSupported, TransferringNotSupported)
+  , mState(eNotInitialized) , mData(nullptr), mSize(0), mVersion(0)
 {
 }
 
 nsStructuredCloneContainer::~nsStructuredCloneContainer()
 {
-  free(mData);
+  if (mData) {
+    free(mData);
+  }
 }
 
-nsresult
+NS_IMETHODIMP
 nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
                                           JSContext* aCx)
 {
-  NS_ENSURE_STATE(!mData);
-
-  uint64_t* jsBytes = nullptr;
-  bool success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
-                                           nullptr, nullptr,
-                                           JS::UndefinedHandleValue);
-  NS_ENSURE_STATE(success);
-  NS_ENSURE_STATE(jsBytes);
-
-  // Copy jsBytes into our own buffer.
-  mData = (uint64_t*) malloc(mSize);
-  if (!mData) {
-    mSize = 0;
-    mVersion = 0;
-
-    JS_ClearStructuredClone(jsBytes, mSize, nullptr, nullptr);
+  if (mState != eNotInitialized) {
     return NS_ERROR_FAILURE;
   }
-  else {
-    mVersion = JS_STRUCTURED_CLONE_VERSION;
+
+  ErrorResult rv;
+  Write(aCx, aData, rv);
+  if (NS_WARN_IF(rv.Failed())) {
+    return rv.StealNSResult();
   }
 
-  memcpy(mData, jsBytes, mSize);
-
-  JS_ClearStructuredClone(jsBytes, mSize, nullptr, nullptr);
+  mState = eInitializedFromJSVal;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
                                            uint32_t aFormatVersion,
-                                           JSContext *aCx)
+                                           JSContext* aCx)
 {
-  NS_ENSURE_STATE(!mData);
+  if (mState != eNotInitialized) {
+    return NS_ERROR_FAILURE;
+  }
 
   NS_ConvertUTF16toUTF8 data(aData);
 
   nsAutoCString binaryData;
   nsresult rv = Base64Decode(data, binaryData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Copy the string's data into our own buffer.
   mData = (uint64_t*) malloc(binaryData.Length());
   NS_ENSURE_STATE(mData);
   memcpy(mData, binaryData.get(), binaryData.Length());
 
   mSize = binaryData.Length();
   mVersion = aFormatVersion;
+
+  mState = eInitializedFromBase64;
   return NS_OK;
 }
 
 nsresult
 nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx,
                                                JS::MutableHandle<JS::Value> aValue)
 {
   aValue.setNull();
   JS::Rooted<JS::Value> jsStateObj(aCx);
-  bool hasTransferable = false;
-  bool success = JS_ReadStructuredClone(aCx, mData, mSize, mVersion,
-                                        &jsStateObj, nullptr, nullptr) &&
-                 JS_StructuredCloneHasTransferables(mData, mSize,
-                                                    &hasTransferable);
-  // We want to be sure that mData doesn't contain transferable objects
-  MOZ_ASSERT(!hasTransferable);
-  NS_ENSURE_STATE(success && !hasTransferable);
+
+  if (mState == eInitializedFromJSVal) {
+    ErrorResult rv;
+    Read(nullptr, aCx, &jsStateObj, rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      return rv.StealNSResult();
+    }
+  } else {
+    MOZ_ASSERT(mState == eInitializedFromBase64);
+    MOZ_ASSERT(mData);
+
+    ErrorResult rv;
+    ReadFromBuffer(nullptr, aCx, mData, mSize, mVersion, &jsStateObj, rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      return rv.StealNSResult();
+    }
+  }
 
   aValue.set(jsStateObj);
   return NS_OK;
 }
 
-nsresult
-nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
-                                                 nsIVariant **aData)
+NS_IMETHODIMP
+nsStructuredCloneContainer::DeserializeToVariant(JSContext* aCx,
+                                                 nsIVariant** aData)
 {
-  NS_ENSURE_STATE(mData);
   NS_ENSURE_ARG_POINTER(aData);
   *aData = nullptr;
 
+  if (mState == eNotInitialized) {
+    return NS_ERROR_FAILURE;
+  }
+
   // Deserialize to a JS::Value.
   JS::Rooted<JS::Value> jsStateObj(aCx);
   nsresult rv = DeserializeToJsval(aCx, &jsStateObj);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // Now wrap the JS::Value as an nsIVariant.
   nsCOMPtr<nsIVariant> varStateObj;
   nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
   NS_ENSURE_STATE(xpconnect);
   xpconnect->JSValToVariant(aCx, jsStateObj, getter_AddRefs(varStateObj));
   NS_ENSURE_STATE(varStateObj);
 
-  NS_ADDREF(*aData = varStateObj);
+  varStateObj.forget(aData);
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
 {
-  NS_ENSURE_STATE(mData);
   aOut.Truncate();
 
-  nsAutoCString binaryData(reinterpret_cast<char*>(mData), mSize);
+  if (mState == eNotInitialized) {
+    return NS_ERROR_FAILURE;
+  }
+
+  uint64_t* data;
+  size_t size;
+
+  if (mState == eInitializedFromJSVal) {
+    if (HasClonedDOMObjects()) {
+      return NS_ERROR_FAILURE;
+    }
+
+    data = BufferData();
+    size = BufferSize();
+  } else {
+    MOZ_ASSERT(mState == eInitializedFromBase64);
+    MOZ_ASSERT(mData);
+
+    data = mData;
+    size = mSize;
+  }
+
+  nsAutoCString binaryData(reinterpret_cast<char*>(data), size);
   nsAutoCString base64Data;
   nsresult rv = Base64Encode(binaryData, base64Data);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
-  aOut.Assign(NS_ConvertASCIItoUTF16(base64Data));
+  CopyASCIItoUTF16(base64Data, aOut);
   return NS_OK;
 }
 
-nsresult
-nsStructuredCloneContainer::GetSerializedNBytes(uint64_t *aSize)
+NS_IMETHODIMP
+nsStructuredCloneContainer::GetSerializedNBytes(uint64_t* aSize)
 {
-  NS_ENSURE_STATE(mData);
   NS_ENSURE_ARG_POINTER(aSize);
 
+  if (mState == eNotInitialized) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (mState == eInitializedFromJSVal) {
+    *aSize = BufferSize();
+    return NS_OK;
+  }
+
+  MOZ_ASSERT(mState == eInitializedFromBase64);
+
   // mSize is a size_t, while aSize is a uint64_t.  We rely on an implicit cast
   // here so that we'll get a compile error if a size_t-to-uint64_t cast is
   // narrowing.
   *aSize = mSize;
 
   return NS_OK;
 }
 
-nsresult
-nsStructuredCloneContainer::GetFormatVersion(uint32_t *aFormatVersion)
+NS_IMETHODIMP
+nsStructuredCloneContainer::GetFormatVersion(uint32_t* aFormatVersion)
 {
-  NS_ENSURE_STATE(mData);
   NS_ENSURE_ARG_POINTER(aFormatVersion);
+
+  if (mState == eNotInitialized) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (mState == eInitializedFromJSVal) {
+    *aFormatVersion = JS_STRUCTURED_CLONE_VERSION;
+    return NS_OK;
+  }
+
+  MOZ_ASSERT(mState == eInitializedFromBase64);
   *aFormatVersion = mVersion;
   return NS_OK;
 }
--- a/dom/base/nsStructuredCloneContainer.h
+++ b/dom/base/nsStructuredCloneContainer.h
@@ -4,38 +4,47 @@
  * 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 nsStructuredCloneContainer_h__
 #define nsStructuredCloneContainer_h__
 
 #include "nsIStructuredCloneContainer.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/StructuredCloneHelper.h"
 
 #define NS_STRUCTUREDCLONECONTAINER_CONTRACTID \
   "@mozilla.org/docshell/structured-clone-container;1"
 #define NS_STRUCTUREDCLONECONTAINER_CID \
 { /* 38bd0634-0fd4-46f0-b85f-13ced889eeec */       \
   0x38bd0634,                                      \
   0x0fd4,                                          \
   0x46f0,                                          \
   {0xb8, 0x5f, 0x13, 0xce, 0xd8, 0x89, 0xee, 0xec} \
 }
 
-class nsStructuredCloneContainer final : public nsIStructuredCloneContainer
+class nsStructuredCloneContainer final
+  : public nsIStructuredCloneContainer
+  , public mozilla::dom::StructuredCloneHelper
 {
   public:
     nsStructuredCloneContainer();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISTRUCTUREDCLONECONTAINER
 
   private:
     ~nsStructuredCloneContainer();
 
+    enum {
+      eNotInitialized = 0,
+      eInitializedFromJSVal,
+      eInitializedFromBase64,
+    } mState;
+
     uint64_t* mData;
 
     // This needs to be size_t rather than a PR-type so it matches the JS API.
     size_t mSize;
     uint32_t mVersion;
 };
 
 #endif
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -735,29 +735,31 @@ skip-if = buildapp == 'b2g' || buildapp 
 [test_html_colors_quirks.html]
 [test_html_colors_standards.html]
 [test_html_in_xhr.html]
 [test_htmlcopyencoder.html]
 [test_htmlcopyencoder.xhtml]
 [test_ipc_messagemanager_blob.html]
 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
 [test_meta_viewport0.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport1.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport2.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport3.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport4.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport5.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_meta_viewport6.html]
-skip-if = buildapp != 'b2g'     # meta-viewport tag support is only on b2g
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
+[test_meta_viewport7.html]
+skip-if = (os != 'b2g' && os != 'android')    # meta-viewport tag support is mobile-only
 [test_mozfiledataurl.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT
 [test_mozMatchesSelector.html]
 [test_mutationobservers.html]
 skip-if = buildapp == 'b2g' || e10s # b2g(bug 901385, showmodaldialog) b2g-debug(bug 901385, showmodaldialog) b2g-desktop(bug 901385, showmodaldialog)
 [test_nodelist_holes.html]
 [test_object.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs plugin support) b2g-debug(needs plugin support) b2g-desktop(needs plugin support)
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_meta_viewport7.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>meta viewport test</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <meta name="viewport" content="width=320">
+  <script src="viewport_helpers.js"></script>
+</head>
+<body>
+  <p>Dynamic viewport updates</p>
+  <script type="application/javascript;version=1.7">
+    "use strict";
+
+    SimpleTest.waitForExplicitFinish();
+
+    let tests = [];
+
+    tests.push(function test1() {
+      SpecialPowers.pushPrefEnv(scaleRatio(1.0),
+        function() {
+          updateViewport("width=device-width");
+          let info = getViewportInfo(800, 480);
+          is(info.defaultZoom, 1,    "initial zoom is 100%");
+          is(info.width,       800,  "width is the same as the displayWidth");
+          is(info.height,      480,  "height is the same as the displayHeight");
+          is(info.autoSize,    true, "width=device-width enables autoSize");
+          is(info.allowZoom,   true, "zooming is enabled by default");
+
+          info = getViewportInfo(900, 600);
+          is(info.width,       900,  "changing the displayWidth changes the width");
+          is(info.height,      600,  "changing the displayHeight changes the height");
+
+          nextTest();
+        });
+    });
+
+    tests.push(function test2() {
+      SpecialPowers.pushPrefEnv(scaleRatio(1.0),
+        function() {
+          updateViewport("width=320");
+          let info = getViewportInfo(800, 80);
+          is(info.defaultZoom, 2.5,   "initial zoom fits the displayWidth");
+          is(info.width,       320,   "width is set explicitly");
+          is(info.height,      40,   "height is at the absolute minimum");
+          is(info.autoSize,    false, "width=device-width enables autoSize");
+          is(info.allowZoom,   true,  "zooming is enabled by default");
+
+          info = getViewportInfo(480, 800);
+          is(info.defaultZoom, 1.5,   "initial zoom fits the new displayWidth");
+          is(info.width,       320,   "explicit width is unchanged");
+          is(info.height,      533,   "height changes proportional to displayHeight");
+
+          nextTest();
+        });
+    });
+
+    tests.push(function test3() {
+      SpecialPowers.pushPrefEnv(scaleRatio(1.0),
+        function() {
+          updateViewport("user-scalable=no");
+          let info = getViewportInfo(800, 480);
+          is(info.allowZoom,   false, "zooming is explicitly disabled");
+
+          nextTest();
+        });
+    });
+
+    tests.push(function test4() {
+      SpecialPowers.pushPrefEnv(scaleRatio(1.0),
+        function() {
+          updateViewport("user-scalable=yes");
+          let info = getViewportInfo(800, 480);
+          is(info.allowZoom,   true,  "zooming is explicitly allowed");
+
+          nextTest();
+        });
+    });
+
+    function getViewportInfo(aDisplayWidth, aDisplayHeight) {
+      let defaultZoom = {}, allowZoom = {}, minZoom = {}, maxZoom = {},
+          width = {}, height = {}, autoSize = {};
+
+      let cwu = SpecialPowers.getDOMWindowUtils(window);
+      cwu.getViewportInfo(aDisplayWidth, aDisplayHeight, defaultZoom, allowZoom,
+                          minZoom, maxZoom, width, height, autoSize);
+      return {
+        defaultZoom: defaultZoom.value,
+        minZoom: minZoom.value,
+        maxZoom: maxZoom.value,
+        width: width.value,
+        height: height.value,
+        autoSize: autoSize.value,
+        allowZoom: allowZoom.value
+      };
+    }
+
+    function updateViewport(content) {
+      let meta = document.querySelector("meta[name=viewport]");
+      meta.content = content;
+    }
+
+    function nextTest() {
+      if (tests.length) {
+        (tests.shift())();
+      } else {
+        SimpleTest.finish();
+      }
+    }
+    addEventListener("load", nextTest);
+  </script>
+</body>
+</html>
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -46,16 +46,17 @@ MSG_DEF(MSG_DOM_DECODING_FAILED, 0, JSEX
 MSG_DEF(MSG_NOT_FINITE, 1, JSEXN_TYPEERR, "{0} is not a finite floating-point value.")
 MSG_DEF(MSG_INVALID_VERSION, 0, JSEXN_TYPEERR, "0 (Zero) is not a valid database version.")
 MSG_DEF(MSG_INVALID_BYTESTRING, 2, JSEXN_TYPEERR, "Cannot convert string to ByteString because the character"
         " at index {0} has value {1} which is greater than 255.")
 MSG_DEF(MSG_NOT_DATE, 1, JSEXN_TYPEERR, "{0} is not a date.")
 MSG_DEF(MSG_INVALID_ADVANCE_COUNT, 0, JSEXN_TYPEERR, "0 (Zero) is not a valid advance count.")
 MSG_DEF(MSG_DEFINEPROPERTY_ON_GSP, 0, JSEXN_TYPEERR, "Not allowed to define a property on the named properties object.")
 MSG_DEF(MSG_INVALID_URL, 1, JSEXN_TYPEERR, "{0} is not a valid URL.")
+MSG_DEF(MSG_URL_HAS_CREDENTIALS, 1, JSEXN_TYPEERR, "{0} is an url with embedded credentials.")
 MSG_DEF(MSG_METADATA_NOT_CONFIGURED, 0, JSEXN_TYPEERR, "Either size or lastModified should be true.")
 MSG_DEF(MSG_INVALID_READ_SIZE, 0, JSEXN_TYPEERR, "0 (Zero) is not a valid read size.")
 MSG_DEF(MSG_HEADERS_IMMUTABLE, 0, JSEXN_TYPEERR, "Headers are immutable and cannot be modified.")
 MSG_DEF(MSG_INVALID_HEADER_NAME, 1, JSEXN_TYPEERR, "{0} is an invalid header name.")
 MSG_DEF(MSG_INVALID_HEADER_VALUE, 1, JSEXN_TYPEERR, "{0} is an invalid header value.")
 MSG_DEF(MSG_INVALID_HEADER_SEQUENCE, 0, JSEXN_TYPEERR, "Headers require name/value tuples when being initialized by a sequence.")
 MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, JSEXN_TYPEERR, "Permission denied to pass cross-origin object as {0}.")
 MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, JSEXN_TYPEERR, "Missing required {0}.")
--- a/dom/camera/CameraCommon.h
+++ b/dom/camera/CameraCommon.h
@@ -2,24 +2,16 @@
 /* vim: set ts=2 et sw=2 tw=40: */
 /* 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 DOM_CAMERA_CAMERACOMMON_H
 #define DOM_CAMERA_CAMERACOMMON_H
 
-#ifndef __func__
-#ifdef __FUNCTION__
-#define __func__ __FUNCTION__
-#else
-#define __func__ __FILE__
-#endif
-#endif
-
 #include "mozilla/Logging.h"
 
 extern PRLogModuleInfo* GetCameraLog();
 #define DOM_CAMERA_LOG( type, ... ) MOZ_LOG(GetCameraLog(), (mozilla::LogLevel)type, ( __VA_ARGS__ ))
 
 #define DOM_CAMERA_LOGA( ... )      DOM_CAMERA_LOG( mozilla::LogLevel::Error, __VA_ARGS__ )
 
 /**
--- a/dom/canvas/compiledtest/moz.build
+++ b/dom/canvas/compiledtest/moz.build
@@ -3,13 +3,16 @@
 # 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/.
 
 GeckoCppUnitTests([
     'TestWebGLElementArrayCache',
 ])
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../',
 ]
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -4,16 +4,17 @@
  * 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 nsDeviceStorage_h
 #define nsDeviceStorage_h
 
 class nsPIDOMWindow;
 #include "mozilla/Attributes.h"
+#include "mozilla/Logging.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
 
 #include "DOMRequest.h"
 #include "DOMCursor.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
@@ -37,21 +38,16 @@ class ErrorResult;
 namespace dom {
 class Blob;
 } // namespace dom
 } // namespace mozilla
 
 //#define DS_LOGGING 1
 
 #ifdef DS_LOGGING
-/* Polyfill __func__ on MSVC to pass to the log. */
-#ifdef _MSC_VER
-#define __func__ __FUNCTION__
-#endif
-
 #define DS_LOG_DEBUG(msg, ...)  printf_stderr("[%s:%d] " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
 #define DS_LOG_INFO DS_LOG_DEBUG
 #define DS_LOG_WARN DS_LOG_DEBUG
 #define DS_LOG_ERROR DS_LOG_DEBUG
 #else
 #define DS_LOG_DEBUG(msg, ...)
 #define DS_LOG_INFO(msg, ...)
 #define DS_LOG_WARN(msg, ...)
--- a/dom/events/AnimationEvent.cpp
+++ b/dom/events/AnimationEvent.cpp
@@ -10,17 +10,17 @@
 
 namespace mozilla {
 namespace dom {
 
 AnimationEvent::AnimationEvent(EventTarget* aOwner,
                                nsPresContext* aPresContext,
                                InternalAnimationEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalAnimationEvent(false, 0))
+          aEvent ? aEvent : new InternalAnimationEvent(false, NS_EVENT_NULL))
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
   }
--- a/dom/events/BeforeAfterKeyboardEvent.cpp
+++ b/dom/events/BeforeAfterKeyboardEvent.cpp
@@ -12,17 +12,18 @@ namespace mozilla {
 namespace dom {
 
 BeforeAfterKeyboardEvent::BeforeAfterKeyboardEvent(
                                        EventTarget* aOwner,
                                        nsPresContext* aPresContext,
                                        InternalBeforeAfterKeyboardEvent* aEvent)
   : KeyboardEvent(aOwner, aPresContext,
                   aEvent ? aEvent :
-                           new InternalBeforeAfterKeyboardEvent(false, 0,
+                           new InternalBeforeAfterKeyboardEvent(false,
+                                                                NS_EVENT_NULL,
                                                                 nullptr))
 {
   MOZ_ASSERT(mEvent->mClass == eBeforeAfterKeyboardEventClass,
              "event type mismatch eBeforeAfterKeyboardEventClass");
 
   if (!aEvent) {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
--- a/dom/events/ClipboardEvent.cpp
+++ b/dom/events/ClipboardEvent.cpp
@@ -11,17 +11,17 @@
 
 namespace mozilla {
 namespace dom {
 
 ClipboardEvent::ClipboardEvent(EventTarget* aOwner,
                                nsPresContext* aPresContext,
                                InternalClipboardEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalClipboardEvent(false, 0))
+          aEvent ? aEvent : new InternalClipboardEvent(false, NS_EVENT_NULL))
 {
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
   }
 }
--- a/dom/events/CompositionEvent.cpp
+++ b/dom/events/CompositionEvent.cpp
@@ -10,17 +10,18 @@
 
 namespace mozilla {
 namespace dom {
 
 CompositionEvent::CompositionEvent(EventTarget* aOwner,
                                    nsPresContext* aPresContext,
                                    WidgetCompositionEvent* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new WidgetCompositionEvent(false, 0, nullptr))
+            aEvent ? aEvent :
+                     new WidgetCompositionEvent(false, NS_EVENT_NULL, nullptr))
 {
   NS_ASSERTION(mEvent->mClass == eCompositionEventClass,
                "event type mismatch");
 
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -150,19 +150,19 @@ DataTransfer::Constructor(const GlobalOb
   nsAutoCString onEventType("on");
   AppendUTF16toUTF8(aEventType, onEventType);
   nsCOMPtr<nsIAtom> eventTypeAtom = do_GetAtom(onEventType);
   if (!eventTypeAtom) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
 
-  uint32_t eventType = nsContentUtils::GetEventId(eventTypeAtom);
+  EventMessage eventMessage = nsContentUtils::GetEventMessage(eventTypeAtom);
   nsRefPtr<DataTransfer> transfer = new DataTransfer(aGlobal.GetAsSupports(),
-                                                     eventType, aIsExternal,
+                                                     eventMessage, aIsExternal,
                                                      -1);
   return transfer.forget();
 }
 
 JSObject*
 DataTransfer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DataTransferBinding::Wrap(aCx, this, aGivenProto);
--- a/dom/events/DragEvent.cpp
+++ b/dom/events/DragEvent.cpp
@@ -11,17 +11,18 @@
 
 namespace mozilla {
 namespace dom {
 
 DragEvent::DragEvent(EventTarget* aOwner,
                      nsPresContext* aPresContext,
                      WidgetDragEvent* aEvent)
   : MouseEvent(aOwner, aPresContext,
-               aEvent ? aEvent : new WidgetDragEvent(false, 0, nullptr))
+               aEvent ? aEvent :
+                        new WidgetDragEvent(false, NS_EVENT_NULL, nullptr))
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
     mEvent->refPoint.x = mEvent->refPoint.y = 0;
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -101,17 +101,17 @@ Event::ConstructorInit(EventTarget* aOwn
             mEventIsInternal = false;
           }
           else {
             mEventIsInternal = true;
           }
           ...
         }
      */
-    mEvent = new WidgetEvent(false, 0);
+    mEvent = new WidgetEvent(false, NS_EVENT_NULL);
     mEvent->time = PR_Now();
   }
 
   InitPresContextData(aPresContext);
 }
 
 void
 Event::InitPresContextData(nsPresContext* aPresContext)
@@ -558,18 +558,18 @@ Event::PreventDefaultInternal(bool aCall
 }
 
 void
 Event::SetEventType(const nsAString& aEventTypeArg)
 {
   if (mIsMainThreadEvent) {
     mEvent->typeString.Truncate();
     mEvent->userType =
-      nsContentUtils::GetEventIdAndAtom(aEventTypeArg, mEvent->mClass,
-                                        &(mEvent->mMessage));
+      nsContentUtils::GetEventMessageAndAtom(aEventTypeArg, mEvent->mClass,
+                                             &(mEvent->mMessage));
   } else {
     mEvent->userType = nullptr;
     mEvent->mMessage = NS_USER_DEFINED_EVENT;
     mEvent->typeString = aEventTypeArg;
   }
 }
 
 NS_IMETHODIMP
@@ -721,30 +721,34 @@ Event::GetEventPopupControlState(WidgetE
           abuse = openControlled;
         }
         break;
       case NS_FORM_CHANGE :
         if (PopupAllowedForEvent("change")) {
           abuse = openControlled;
         }
         break;
+      default:
+        break;
       }
     }
     break;
   case eEditorInputEventClass:
     // For this following event only allow popups if it's triggered
     // while handling user input. See
     // nsPresShell::HandleEventInternal() for details.
     if (EventStateManager::IsHandlingUserInput()) {
       switch(aEvent->mMessage) {
       case NS_EDITOR_INPUT:
         if (PopupAllowedForEvent("input")) {
           abuse = openControlled;
         }
         break;
+      default:
+        break;
       }
     }
     break;
   case eInputEventClass:
     // For this following event only allow popups if it's triggered
     // while handling user input. See
     // nsPresShell::HandleEventInternal() for details.
     if (EventStateManager::IsHandlingUserInput()) {
@@ -752,16 +756,18 @@ Event::GetEventPopupControlState(WidgetE
       case NS_FORM_CHANGE :
         if (PopupAllowedForEvent("change")) {
           abuse = openControlled;
         }
         break;
       case NS_XUL_COMMAND:
         abuse = openControlled;
         break;
+      default:
+        break;
       }
     }
     break;
   case eKeyboardEventClass:
     if (aEvent->mFlags.mIsTrusted) {
       uint32_t key = aEvent->AsKeyboardEvent()->keyCode;
       switch(aEvent->mMessage) {
       case NS_KEY_PRESS :
@@ -780,32 +786,36 @@ Event::GetEventPopupControlState(WidgetE
           abuse = openControlled;
         }
         break;
       case NS_KEY_DOWN :
         if (PopupAllowedForEvent("keydown")) {
           abuse = openControlled;
         }
         break;
+      default:
+        break;
       }
     }
     break;
   case eTouchEventClass:
     if (aEvent->mFlags.mIsTrusted) {
       switch (aEvent->mMessage) {
       case NS_TOUCH_START :
         if (PopupAllowedForEvent("touchstart")) {
           abuse = openControlled;
         }
         break;
       case NS_TOUCH_END :
         if (PopupAllowedForEvent("touchend")) {
           abuse = openControlled;
         }
         break;
+      default:
+        break;
       }
     }
     break;
   case eMouseEventClass:
     if (aEvent->mFlags.mIsTrusted &&
         aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
       switch(aEvent->mMessage) {
       case NS_MOUSE_BUTTON_UP :
@@ -827,16 +837,18 @@ Event::GetEventPopupControlState(WidgetE
           abuse = openAllowed;
         }
         break;
       case NS_MOUSE_DOUBLECLICK :
         if (PopupAllowedForEvent("dblclick")) {
           abuse = openControlled;
         }
         break;
+      default:
+        break;
       }
     }
     break;
   case eFormEventClass:
     // For these following events only allow popups if they're
     // triggered while handling user input. See
     // nsPresShell::HandleEventInternal() for details.
     if (EventStateManager::IsHandlingUserInput()) {
@@ -846,16 +858,18 @@ Event::GetEventPopupControlState(WidgetE
           abuse = openControlled;
         }
         break;
       case NS_FORM_RESET :
         if (PopupAllowedForEvent("reset")) {
           abuse = openControlled;
         }
         break;
+      default:
+        break;
       }
     }
     break;
   default:
     break;
   }
 
   return abuse;
@@ -1021,23 +1035,23 @@ Event::GetOffsetCoords(nsPresContext* aP
   }
   return CSSIntPoint(0, 0);
 }
 
 // To be called ONLY by Event::GetType (which has the additional
 // logic for handling user-defined events).
 // static
 const char*
-Event::GetEventName(uint32_t aEventType)
+Event::GetEventName(EventMessage aEventType)
 {
   switch(aEventType) {
-#define ID_TO_EVENT(name_, _id, _type, _struct) \
-  case _id: return #name_;
+#define MESSAGE_TO_EVENT(name_, _message, _type, _struct) \
+  case _message: return #name_;
 #include "mozilla/EventNameList.h"
-#undef ID_TO_EVENT
+#undef MESSAGE_TO_EVENT
   default:
     break;
   }
   // XXXldb We can hit this case for WidgetEvent objects that we didn't
   // create and that are not user defined events since this function and
   // SetEventType are incomplete.  (But fixing that requires fixing the
   // arrays in nsEventListenerManager too, since the events for which
   // this is a problem generally *are* created by Event.)
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -119,17 +119,17 @@ public:
 
   static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent,
                                                      nsIDOMEvent* aDOMEvent = nullptr);
 
   static void PopupAllowedEventsChanged();
 
   static void Shutdown();
 
-  static const char* GetEventName(uint32_t aEventType);
+  static const char* GetEventName(EventMessage aEventType);
   static CSSIntPoint GetClientCoords(nsPresContext* aPresContext,
                                      WidgetEvent* aEvent,
                                      LayoutDeviceIntPoint aPoint,
                                      CSSIntPoint aDefaultPoint);
   static CSSIntPoint GetPageCoords(nsPresContext* aPresContext,
                                    WidgetEvent* aEvent,
                                    LayoutDeviceIntPoint aPoint,
                                    CSSIntPoint aDefaultPoint);
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -47,34 +47,34 @@
 #include "nsSandboxFlags.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 
 using namespace dom;
 using namespace hal;
 
-#define EVENT_TYPE_EQUALS(ls, type, userType, typeString, allEvents) \
-  ((ls->mEventType == type &&                                        \
-    (ls->mEventType != NS_USER_DEFINED_EVENT ||                      \
-    (mIsMainThreadELM && ls->mTypeAtom == userType) ||               \
-    (!mIsMainThreadELM && ls->mTypeString.Equals(typeString)))) ||   \
+#define EVENT_TYPE_EQUALS(ls, message, userType, typeString, allEvents) \
+  ((ls->mEventMessage == message &&                                     \
+    (ls->mEventMessage != NS_USER_DEFINED_EVENT ||                      \
+    (mIsMainThreadELM && ls->mTypeAtom == userType) ||                  \
+    (!mIsMainThreadELM && ls->mTypeString.Equals(typeString)))) ||      \
    (allEvents && ls->mAllEvents))
 
 static const uint32_t kAllMutationBits =
   NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED |
   NS_EVENT_BITS_MUTATION_NODEINSERTED |
   NS_EVENT_BITS_MUTATION_NODEREMOVED |
   NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT |
   NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT |
   NS_EVENT_BITS_MUTATION_ATTRMODIFIED |
   NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
 
 static uint32_t
-MutationBitForEventType(uint32_t aEventType)
+MutationBitForEventType(EventMessage aEventType)
 {
   switch (aEventType) {
     case NS_MUTATION_SUBTREEMODIFIED:
       return NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
     case NS_MUTATION_NODEINSERTED:
       return NS_EVENT_BITS_MUTATION_NODEINSERTED;
     case NS_MUTATION_NODEREMOVED:
       return NS_EVENT_BITS_MUTATION_NODEREMOVED;
@@ -89,29 +89,36 @@ MutationBitForEventType(uint32_t aEventT
     default:
       break;
   }
   return 0;
 }
 
 uint32_t EventListenerManager::sMainThreadCreatedCount = 0;
 
-EventListenerManager::EventListenerManager(EventTarget* aTarget)
-  : mMayHavePaintEventListener(false)
+EventListenerManagerBase::EventListenerManagerBase()
+  : mNoListenerForEvent(NS_EVENT_NULL)
+  , mMayHavePaintEventListener(false)
   , mMayHaveMutationListeners(false)
   , mMayHaveCapturingListeners(false)
   , mMayHaveSystemGroupListeners(false)
   , mMayHaveTouchEventListener(false)
   , mMayHaveMouseEnterLeaveEventListener(false)
   , mMayHavePointerEnterLeaveEventListener(false)
   , mMayHaveKeyEventListener(false)
   , mMayHaveInputOrCompositionEventListener(false)
   , mClearingListeners(false)
   , mIsMainThreadELM(NS_IsMainThread())
-  , mNoListenerForEvent(0)
+{
+  static_assert(sizeof(EventListenerManagerBase) == sizeof(uint32_t),
+                "Keep the size of EventListenerManagerBase size compact!");
+}
+
+EventListenerManager::EventListenerManager(EventTarget* aTarget)
+  : EventListenerManagerBase()
   , mTarget(aTarget)
 {
   NS_ASSERTION(aTarget, "unexpected null pointer");
 
   if (mIsMainThreadELM) {
     ++sMainThreadCreatedCount;
   }
 }
@@ -210,25 +217,27 @@ EventListenerManager::GetTargetAsInnerWi
 
   NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
   return window.forget();
 }
 
 void
 EventListenerManager::AddEventListenerInternal(
                         const EventListenerHolder& aListenerHolder,
-                        uint32_t aType,
+                        EventMessage aEventMessage,
                         nsIAtom* aTypeAtom,
                         const nsAString& aTypeString,
                         const EventListenerFlags& aFlags,
                         bool aHandler,
                         bool aAllEvents)
 {
-  MOZ_ASSERT((NS_IsMainThread() && aType && aTypeAtom) || // Main thread
-             (!NS_IsMainThread() && aType && !aTypeString.IsEmpty()) || // non-main-thread
+  MOZ_ASSERT(// Main thread
+             (NS_IsMainThread() && aEventMessage && aTypeAtom) ||
+             // non-main-thread
+             (!NS_IsMainThread() && aEventMessage && !aTypeString.IsEmpty()) ||
              aAllEvents, "Missing type"); // all-events listener
 
   if (!aListenerHolder || mClearingListeners) {
     return;
   }
 
   // Since there is no public API to call us with an EventListenerHolder, we
   // know that there's an EventListenerHolder on the stack holding a strong ref
@@ -236,31 +245,30 @@ EventListenerManager::AddEventListenerIn
 
   Listener* listener;
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; i++) {
     listener = &mListeners.ElementAt(i);
     // mListener == aListenerHolder is the last one, since it can be a bit slow.
     if (listener->mListenerIsHandler == aHandler &&
         listener->mFlags == aFlags &&
-        EVENT_TYPE_EQUALS(listener, aType, aTypeAtom, aTypeString,
+        EVENT_TYPE_EQUALS(listener, aEventMessage, aTypeAtom, aTypeString,
                           aAllEvents) &&
         listener->mListener == aListenerHolder) {
       return;
     }
   }
 
   mNoListenerForEvent = NS_EVENT_NULL;
   mNoListenerForEventAtom = nullptr;
 
   listener = aAllEvents ? mListeners.InsertElementAt(0) :
                           mListeners.AppendElement();
   listener->mListener = aListenerHolder;
-  MOZ_ASSERT(aType < PR_UINT16_MAX);
-  listener->mEventType = aType;
+  listener->mEventMessage = aEventMessage;
   listener->mTypeString = aTypeString;
   listener->mTypeAtom = aTypeAtom;
   listener->mFlags = aFlags;
   listener->mListenerIsHandler = aHandler;
   listener->mHandlerIsString = false;
   listener->mAllEvents = aAllEvents;
 
   // Detect the type of event listener.
@@ -279,38 +287,39 @@ EventListenerManager::AddEventListenerIn
 
   if (aFlags.mInSystemGroup) {
     mMayHaveSystemGroupListeners = true;
   }
   if (aFlags.mCapture) {
     mMayHaveCapturingListeners = true;
   }
 
-  if (aType == NS_AFTERPAINT) {
+  if (aEventMessage == NS_AFTERPAINT) {
     mMayHavePaintEventListener = true;
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window) {
       window->SetHasPaintEventListeners();
     }
-  } else if (aType >= NS_MUTATION_START && aType <= NS_MUTATION_END) {
+  } else if (aEventMessage >= NS_MUTATION_START &&
+             aEventMessage <= NS_MUTATION_END) {
     // For mutation listeners, we need to update the global bit on the DOM window.
     // Otherwise we won't actually fire the mutation event.
     mMayHaveMutationListeners = true;
     // Go from our target to the nearest enclosing DOM window.
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window) {
       nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
       if (doc) {
         doc->WarnOnceAbout(nsIDocument::eMutationEvent);
       }
-      // If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all
+      // If aEventMessage is NS_MUTATION_SUBTREEMODIFIED, we need to listen all
       // mutations. nsContentUtils::HasMutationListeners relies on this.
-      window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ?
-                                   kAllMutationBits :
-                                   MutationBitForEventType(aType));
+      window->SetMutationListeners(
+        (aEventMessage == NS_MUTATION_SUBTREEMODIFIED) ?
+          kAllMutationBits : MutationBitForEventType(aEventMessage));
     }
   } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
     EnableDevice(NS_DEVICE_ORIENTATION);
   } else if (aTypeAtom == nsGkAtoms::ondeviceproximity || aTypeAtom == nsGkAtoms::onuserproximity) {
     EnableDevice(NS_DEVICE_PROXIMITY);
   } else if (aTypeAtom == nsGkAtoms::ondevicelight) {
     EnableDevice(NS_DEVICE_LIGHT);
   } else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
@@ -338,17 +347,18 @@ EventListenerManager::AddEventListenerIn
              aTypeAtom == nsGkAtoms::ontouchcancel) {
     mMayHaveTouchEventListener = true;
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     // we don't want touchevent listeners added by scrollbars to flip this flag
     // so we ignore listeners created with system event flag
     if (window && !aFlags.mInSystemGroup) {
       window->SetHasTouchEventListeners();
     }
-  } else if (aType >= NS_POINTER_EVENT_START && aType <= NS_POINTER_LOST_CAPTURE) {
+  } else if (aEventMessage >= NS_POINTER_EVENT_START &&
+             aEventMessage <= NS_POINTER_LOST_CAPTURE) {
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (aTypeAtom == nsGkAtoms::onpointerenter ||
         aTypeAtom == nsGkAtoms::onpointerleave) {
       mMayHavePointerEnterLeaveEventListener = true;
       if (window) {
 #ifdef DEBUG
         nsCOMPtr<nsIDocument> d = window->GetExtantDoc();
         NS_WARN_IF_FALSE(!nsContentUtils::IsChromeDoc(d),
@@ -367,18 +377,18 @@ EventListenerManager::AddEventListenerIn
       nsCOMPtr<nsIDocument> d = window->GetExtantDoc();
       NS_WARN_IF_FALSE(!nsContentUtils::IsChromeDoc(d),
                        "Please do not use mouseenter/leave events in chrome. "
                        "They are slower than mouseover/out!");
 #endif
       window->SetHasMouseEnterLeaveEventListeners();
     }
 #ifdef MOZ_GAMEPAD
-  } else if (aType >= NS_GAMEPAD_START &&
-             aType <= NS_GAMEPAD_END) {
+  } else if (aEventMessage >= NS_GAMEPAD_START &&
+             aEventMessage <= NS_GAMEPAD_END) {
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window) {
       window->SetHasGamepadEventListener();
     }
 #endif
   } else if (aTypeAtom == nsGkAtoms::onkeydown ||
              aTypeAtom == nsGkAtoms::onkeypress ||
              aTypeAtom == nsGkAtoms::onkeyup) {
@@ -400,40 +410,40 @@ EventListenerManager::AddEventListenerIn
 
   if (mIsMainThreadELM && mTarget) {
     EventListenerService::NotifyAboutMainThreadListenerChange(mTarget,
                                                               aTypeAtom);
   }
 }
 
 bool
-EventListenerManager::IsDeviceType(uint32_t aType)
+EventListenerManager::IsDeviceType(EventMessage aEventMessage)
 {
-  switch (aType) {
+  switch (aEventMessage) {
     case NS_DEVICE_ORIENTATION:
     case NS_DEVICE_MOTION:
     case NS_DEVICE_LIGHT:
     case NS_DEVICE_PROXIMITY:
     case NS_USER_PROXIMITY:
       return true;
     default:
       break;
   }
   return false;
 }
 
 void
-EventListenerManager::EnableDevice(uint32_t aType)
+EventListenerManager::EnableDevice(EventMessage aEventMessage)
 {
   nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
   if (!window) {
     return;
   }
 
-  switch (aType) {
+  switch (aEventMessage) {
     case NS_DEVICE_ORIENTATION:
       window->EnableDeviceSensor(SENSOR_ORIENTATION);
       break;
     case NS_DEVICE_PROXIMITY:
     case NS_USER_PROXIMITY:
       window->EnableDeviceSensor(SENSOR_PROXIMITY);
       break;
     case NS_DEVICE_LIGHT:
@@ -446,24 +456,24 @@ EventListenerManager::EnableDevice(uint3
       break;
     default:
       NS_WARNING("Enabling an unknown device sensor.");
       break;
   }
 }
 
 void
-EventListenerManager::DisableDevice(uint32_t aType)
+EventListenerManager::DisableDevice(EventMessage aEventMessage)
 {
   nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
   if (!window) {
     return;
   }
 
-  switch (aType) {
+  switch (aEventMessage) {
     case NS_DEVICE_ORIENTATION:
       window->DisableDeviceSensor(SENSOR_ORIENTATION);
       break;
     case NS_DEVICE_MOTION:
       window->DisableDeviceSensor(SENSOR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_GYROSCOPE);
       break;
@@ -478,40 +488,40 @@ EventListenerManager::DisableDevice(uint
       NS_WARNING("Disabling an unknown device sensor.");
       break;
   }
 }
 
 void
 EventListenerManager::RemoveEventListenerInternal(
                         const EventListenerHolder& aListenerHolder,
-                        uint32_t aType,
+                        EventMessage aEventMessage,
                         nsIAtom* aUserType,
                         const nsAString& aTypeString,
                         const EventListenerFlags& aFlags,
                         bool aAllEvents)
 {
-  if (!aListenerHolder || !aType || mClearingListeners) {
+  if (!aListenerHolder || !aEventMessage || mClearingListeners) {
     return;
   }
 
   Listener* listener;
 
   uint32_t count = mListeners.Length();
   uint32_t typeCount = 0;
-  bool deviceType = IsDeviceType(aType);
+  bool deviceType = IsDeviceType(aEventMessage);
 #ifdef MOZ_B2G
-  bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT);
-  bool networkEvent = (aType == NS_NETWORK_UPLOAD_EVENT ||
-                       aType == NS_NETWORK_DOWNLOAD_EVENT);
+  bool timeChangeEvent = (aEventMessage == NS_MOZ_TIME_CHANGE_EVENT);
+  bool networkEvent = (aEventMessage == NS_NETWORK_UPLOAD_EVENT ||
+                       aEventMessage == NS_NETWORK_DOWNLOAD_EVENT);
 #endif // MOZ_B2G
 
   for (uint32_t i = 0; i < count; ++i) {
     listener = &mListeners.ElementAt(i);
-    if (EVENT_TYPE_EQUALS(listener, aType, aUserType, aTypeString,
+    if (EVENT_TYPE_EQUALS(listener, aEventMessage, aUserType, aTypeString,
                           aAllEvents)) {
       ++typeCount;
       if (listener->mListener == aListenerHolder &&
           listener->mFlags.EqualsIgnoringTrustness(aFlags)) {
         nsRefPtr<EventListenerManager> kungFuDeathGrip(this);
         mListeners.RemoveElementAt(i);
         --count;
         mNoListenerForEvent = NS_EVENT_NULL;
@@ -532,123 +542,123 @@ EventListenerManager::RemoveEventListene
           return;
         }
         --typeCount;
       }
     }
   }
 
   if (!aAllEvents && deviceType && typeCount == 0) {
-    DisableDevice(aType);
+    DisableDevice(aEventMessage);
 #ifdef MOZ_B2G
   } else if (timeChangeEvent && typeCount == 0) {
     nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
     if (window) {
       window->DisableTimeChangeNotifications();
     }
   } else if (!aAllEvents && networkEvent && typeCount == 0) {
     nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
     if (window) {
-      window->DisableNetworkEvent(aType);
+      window->DisableNetworkEvent(aEventMessage);
     }
 #endif // MOZ_B2G
   }
 }
 
 bool
 EventListenerManager::ListenerCanHandle(Listener* aListener,
                                         WidgetEvent* aEvent)
 {
   // This is slightly different from EVENT_TYPE_EQUALS in that it returns
   // true even when aEvent->mMessage == NS_USER_DEFINED_EVENT and
-  // aListener=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are
+  // aListener=>mEventMessage != NS_USER_DEFINED_EVENT as long as the atoms are
   // the same
   if (aListener->mAllEvents) {
     return true;
   }
   if (aEvent->mMessage == NS_USER_DEFINED_EVENT) {
     if (mIsMainThreadELM) {
       return aListener->mTypeAtom == aEvent->userType;
     }
     return aListener->mTypeString.Equals(aEvent->typeString);
   }
   MOZ_ASSERT(mIsMainThreadELM);
-  return aListener->mEventType == aEvent->mMessage;
+  return aListener->mEventMessage == aEvent->mMessage;
 }
 
 void
 EventListenerManager::AddEventListenerByType(
                         const EventListenerHolder& aListenerHolder,
                         const nsAString& aType,
                         const EventListenerFlags& aFlags)
 {
   nsCOMPtr<nsIAtom> atom =
     mIsMainThreadELM ? do_GetAtom(NS_LITERAL_STRING("on") + aType) : nullptr;
-  uint32_t type = nsContentUtils::GetEventId(atom);
-  AddEventListenerInternal(aListenerHolder, type, atom, aType, aFlags);
+  EventMessage message = nsContentUtils::GetEventMessage(atom);
+  AddEventListenerInternal(aListenerHolder, message, atom, aType, aFlags);
 }
 
 void
 EventListenerManager::RemoveEventListenerByType(
                         const EventListenerHolder& aListenerHolder,
                         const nsAString& aType,
                         const EventListenerFlags& aFlags)
 {
   nsCOMPtr<nsIAtom> atom =
     mIsMainThreadELM ? do_GetAtom(NS_LITERAL_STRING("on") + aType) : nullptr;
-  uint32_t type = nsContentUtils::GetEventId(atom);
-  RemoveEventListenerInternal(aListenerHolder, type, atom, aType, aFlags);
+  EventMessage message = nsContentUtils::GetEventMessage(atom);
+  RemoveEventListenerInternal(aListenerHolder, message, atom, aType, aFlags);
 }
 
 EventListenerManager::Listener*
-EventListenerManager::FindEventHandler(uint32_t aEventType,
+EventListenerManager::FindEventHandler(EventMessage aEventMessage,
                                        nsIAtom* aTypeAtom,
                                        const nsAString& aTypeString)
 {
   // Run through the listeners for this type and see if a script
   // listener is registered
   Listener* listener;
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     listener = &mListeners.ElementAt(i);
     if (listener->mListenerIsHandler &&
-        EVENT_TYPE_EQUALS(listener, aEventType, aTypeAtom, aTypeString,
+        EVENT_TYPE_EQUALS(listener, aEventMessage, aTypeAtom, aTypeString,
                           false)) {
       return listener;
     }
   }
   return nullptr;
 }
 
 EventListenerManager::Listener*
 EventListenerManager::SetEventHandlerInternal(
                         nsIAtom* aName,
                         const nsAString& aTypeString,
                         const TypedEventHandler& aTypedHandler,
                         bool aPermitUntrustedEvents)
 {
   MOZ_ASSERT(aName || !aTypeString.IsEmpty());
 
-  uint32_t eventType = nsContentUtils::GetEventId(aName);
-  Listener* listener = FindEventHandler(eventType, aName, aTypeString);
+  EventMessage eventMessage = nsContentUtils::GetEventMessage(aName);
+  Listener* listener = FindEventHandler(eventMessage, aName, aTypeString);
 
   if (!listener) {
     // If we didn't find a script listener or no listeners existed
     // create and add a new one.
     EventListenerFlags flags;
     flags.mListenerIsJSListener = true;
 
     nsCOMPtr<JSEventHandler> jsEventHandler;
     NS_NewJSEventHandler(mTarget, aName,
                          aTypedHandler, getter_AddRefs(jsEventHandler));
     EventListenerHolder listenerHolder(jsEventHandler);
-    AddEventListenerInternal(listenerHolder, eventType, aName, aTypeString,
+    AddEventListenerInternal(listenerHolder, eventMessage, aName, aTypeString,
                              flags, true);
 
-    listener = FindEventHandler(eventType, aName, aTypeString);
+    listener = FindEventHandler(eventMessage, aName, aTypeString);
   } else {
     JSEventHandler* jsEventHandler = listener->GetJSEventHandler();
     MOZ_ASSERT(jsEventHandler,
                "How can we have an event handler with no JSEventHandler?");
 
     bool same = jsEventHandler->GetTypedEventHandler() == aTypedHandler;
     // Possibly the same listener, but update still the context and scope.
     jsEventHandler->SetHandler(aTypedHandler);
@@ -771,18 +781,18 @@ EventListenerManager::SetEventHandler(ns
 void
 EventListenerManager::RemoveEventHandler(nsIAtom* aName,
                                          const nsAString& aTypeString)
 {
   if (mClearingListeners) {
     return;
   }
 
-  uint32_t eventType = nsContentUtils::GetEventId(aName);
-  Listener* listener = FindEventHandler(eventType, aName, aTypeString);
+  EventMessage eventMessage = nsContentUtils::GetEventMessage(aName);
+  Listener* listener = FindEventHandler(eventMessage, aName, aTypeString);
 
   if (listener) {
     mListeners.RemoveElementAt(uint32_t(listener - &mListeners.ElementAt(0)));
     mNoListenerForEvent = NS_EVENT_NULL;
     mNoListenerForEventAtom = nullptr;
     if (mTarget && aName) {
       mTarget->EventListenerRemoved(aName);
     }
@@ -1234,40 +1244,40 @@ EventListenerManager::RemoveListenerForA
 
 bool
 EventListenerManager::HasMutationListeners()
 {
   if (mMayHaveMutationListeners) {
     uint32_t count = mListeners.Length();
     for (uint32_t i = 0; i < count; ++i) {
       Listener* listener = &mListeners.ElementAt(i);
-      if (listener->mEventType >= NS_MUTATION_START &&
-          listener->mEventType <= NS_MUTATION_END) {
+      if (listener->mEventMessage >= NS_MUTATION_START &&
+          listener->mEventMessage <= NS_MUTATION_END) {
         return true;
       }
     }
   }
 
   return false;
 }
 
 uint32_t
 EventListenerManager::MutationListenerBits()
 {
   uint32_t bits = 0;
   if (mMayHaveMutationListeners) {
     uint32_t count = mListeners.Length();
     for (uint32_t i = 0; i < count; ++i) {
       Listener* listener = &mListeners.ElementAt(i);
-      if (listener->mEventType >= NS_MUTATION_START &&
-          listener->mEventType <= NS_MUTATION_END) {
-        if (listener->mEventType == NS_MUTATION_SUBTREEMODIFIED) {
+      if (listener->mEventMessage >= NS_MUTATION_START &&
+          listener->mEventMessage <= NS_MUTATION_END) {
+        if (listener->mEventMessage == NS_MUTATION_SUBTREEMODIFIED) {
           return kAllMutationBits;
         }
-        bits |= MutationBitForEventType(listener->mEventType);
+        bits |= MutationBitForEventType(listener->mEventMessage);
       }
     }
   }
   return bits;
 }
 
 bool
 EventListenerManager::HasListenersFor(const nsAString& aEventName)
@@ -1347,18 +1357,18 @@ EventListenerManager::GetListenerInfo(ns
 }
 
 bool
 EventListenerManager::HasUnloadListeners()
 {
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     Listener* listener = &mListeners.ElementAt(i);
-    if (listener->mEventType == NS_PAGE_UNLOAD ||
-        listener->mEventType == NS_BEFORE_PAGE_UNLOAD) {
+    if (listener->mEventMessage == NS_PAGE_UNLOAD ||
+        listener->mEventMessage == NS_BEFORE_PAGE_UNLOAD) {
       return true;
     }
   }
   return false;
 }
 
 void
 EventListenerManager::SetEventHandler(nsIAtom* aEventName,
@@ -1419,18 +1429,18 @@ EventListenerManager::SetEventHandler(
                           !mIsMainThreadELM ||
                           !nsContentUtils::IsCallerChrome());
 }
 
 const TypedEventHandler*
 EventListenerManager::GetTypedEventHandler(nsIAtom* aEventName,
                                            const nsAString& aTypeString)
 {
-  uint32_t eventType = nsContentUtils::GetEventId(aEventName);
-  Listener* listener = FindEventHandler(eventType, aEventName, aTypeString);
+  EventMessage eventMessage = nsContentUtils::GetEventMessage(aEventName);
+  Listener* listener = FindEventHandler(eventMessage, aEventName, aTypeString);
 
   if (!listener) {
     return nullptr;
   }
 
   JSEventHandler* jsEventHandler = listener->GetJSEventHandler();
 
   if (listener->mHandlerIsString) {
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -141,31 +141,51 @@ inline EventListenerFlags AllEventsAtSys
 {
   EventListenerFlags flags;
   flags.mCapture = true;
   flags.mInSystemGroup = true;
   flags.mAllowUntrustedEvents = true;
   return flags;
 }
 
+class EventListenerManagerBase
+{
+protected:
+  EventListenerManagerBase();
+
+  EventMessage mNoListenerForEvent;
+  uint16_t mMayHavePaintEventListener : 1;
+  uint16_t mMayHaveMutationListeners : 1;
+  uint16_t mMayHaveCapturingListeners : 1;
+  uint16_t mMayHaveSystemGroupListeners : 1;
+  uint16_t mMayHaveTouchEventListener : 1;
+  uint16_t mMayHaveMouseEnterLeaveEventListener : 1;
+  uint16_t mMayHavePointerEnterLeaveEventListener : 1;
+  uint16_t mMayHaveKeyEventListener : 1;
+  uint16_t mMayHaveInputOrCompositionEventListener : 1;
+  uint16_t mClearingListeners : 1;
+  uint16_t mIsMainThreadELM : 1;
+  // uint16_t mUnused : 5;
+};
+
 /*
  * Event listener manager
  */
 
-class EventListenerManager final
+class EventListenerManager final : public EventListenerManagerBase
 {
   ~EventListenerManager();
 
 public:
   struct Listener
   {
     EventListenerHolder mListener;
     nsCOMPtr<nsIAtom> mTypeAtom; // for the main thread
     nsString mTypeString; // for non-main-threads
-    uint16_t mEventType;
+    EventMessage mEventMessage;
 
     enum ListenerType : uint8_t
     {
       eNativeListener = 0,
       eJSEventListener,
       eWrappedJSListener,
       eWebIDLListener,
       eListenerTypeCount
@@ -444,35 +464,35 @@ protected:
    */
   nsresult CompileEventHandlerInternal(Listener* aListener,
                                        const nsAString* aBody,
                                        dom::Element* aElement);
 
   /**
    * Find the Listener for the "inline" event listener for aTypeAtom.
    */
-  Listener* FindEventHandler(uint32_t aEventType,
+  Listener* FindEventHandler(EventMessage aEventMessage,
                              nsIAtom* aTypeAtom,
                              const nsAString& aTypeString);
 
   /**
    * Set the "inline" event listener for aName to aHandler.  aHandler may be
    * have no actual handler set to indicate that we should lazily get and
    * compile the string for this listener, but in that case aContext and
    * aScopeGlobal must be non-null.  Otherwise, aContext and aScopeGlobal are
    * allowed to be null.
    */
   Listener* SetEventHandlerInternal(nsIAtom* aName,
                                     const nsAString& aTypeString,
                                     const TypedEventHandler& aHandler,
                                     bool aPermitUntrustedEvents);
 
-  bool IsDeviceType(uint32_t aType);
-  void EnableDevice(uint32_t aType);
-  void DisableDevice(uint32_t aType);
+  bool IsDeviceType(EventMessage aEventMessage);
+  void EnableDevice(EventMessage aEventMessage);
+  void DisableDevice(EventMessage aEventMessage);
 
 public:
   /**
    * Set the "inline" event listener for aEventName to aHandler.  If
    * aHandler is null, this will actually remove the event listener
    */
   void SetEventHandler(nsIAtom* aEventName,
                        const nsAString& aTypeString,
@@ -524,52 +544,44 @@ protected:
                         const EventListenerHolder& aListener,
                         bool aUseCapture,
                         bool aWantsUntrusted);
   void RemoveEventListener(const nsAString& aType,
                            const EventListenerHolder& aListener,
                            bool aUseCapture);
 
   void AddEventListenerInternal(const EventListenerHolder& aListener,
-                                uint32_t aType,
+                                EventMessage aEventMessage,
                                 nsIAtom* aTypeAtom,
                                 const nsAString& aTypeString,
                                 const EventListenerFlags& aFlags,
                                 bool aHandler = false,
                                 bool aAllEvents = false);
   void RemoveEventListenerInternal(const EventListenerHolder& aListener,
-                                   uint32_t aType,
+                                   EventMessage aEventMessage,
                                    nsIAtom* aUserType,
                                    const nsAString& aTypeString,
                                    const EventListenerFlags& aFlags,
                                    bool aAllEvents = false);
   void RemoveAllListeners();
   const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
   const EventTypeData* GetTypeDataForEventName(nsIAtom* aName);
   nsPIDOMWindow* GetInnerWindowForTarget();
   already_AddRefed<nsPIDOMWindow> GetTargetAsInnerWindow() const;
 
   bool ListenerCanHandle(Listener* aListener, WidgetEvent* aEvent);
 
+  // BE AWARE, a lot of instances of EventListenerManager will be created.
+  // Therefor, we need to keep this class compact.  When you add integer
+  // members, please add them to EventListemerManagerBase and check the size
+  // at build time.
+
   already_AddRefed<nsIScriptGlobalObject>
   GetScriptGlobalAndDocument(nsIDocument** aDoc);
 
-  uint32_t mMayHavePaintEventListener : 1;
-  uint32_t mMayHaveMutationListeners : 1;
-  uint32_t mMayHaveCapturingListeners : 1;
-  uint32_t mMayHaveSystemGroupListeners : 1;
-  uint32_t mMayHaveTouchEventListener : 1;
-  uint32_t mMayHaveMouseEnterLeaveEventListener : 1;
-  uint32_t mMayHavePointerEnterLeaveEventListener : 1;
-  uint32_t mMayHaveKeyEventListener : 1;
-  uint32_t mMayHaveInputOrCompositionEventListener : 1;
-  uint32_t mClearingListeners : 1;
-  uint32_t mIsMainThreadELM : 1;
-  uint32_t mNoListenerForEvent : 21;
-
   nsAutoTObserverArray<Listener, 2> mListeners;
   dom::EventTarget* MOZ_NON_OWNING_REF mTarget;
   nsCOMPtr<nsIAtom> mNoListenerForEventAtom;
 
   friend class ELMCreationDetector;
   static uint32_t sMainThreadCreatedCount;
 };
 
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -6,17 +6,17 @@
 
 /*
  * This file contains the list of event names that are exposed via IDL
  * on various objects.  It is designed to be used as inline input to
  * various consumers through the magic of C preprocessing.
  *
  * Each entry consists of 4 pieces of information:
  * 1) The name of the event
- * 2) The event ID (see BasicEvents.h)
+ * 2) The event message
  * 3) The event type (see the EventNameType enum in nsContentUtils.h)
  * 4) The event struct type for this event.
  * Items 2-4 might be empty strings for events for which they don't make sense.
  *
  * Event names that are exposed as content attributes on HTML elements
  * and as IDL attributes on Elements, Documents and Windows and have
  * no forwarding behavior should be enclosed in the EVENT macro.
  *
@@ -47,55 +47,55 @@
  * Event names that are not exposed as IDL attributes at all should be
  * enclosed in NON_IDL_EVENT.  If NON_IDL_EVENT is not defined, it
  * will be defined to the empty string.
  *
  * If you change which macros event names are enclosed in, please
  * update the tests for bug 689564 and bug 659350 as needed.
  */
 
-#ifdef ID_TO_EVENT
+#ifdef MESSAGE_TO_EVENT
 #ifdef EVENT
 #error "Don't define EVENT"
 #endif /* EVENT */
 #ifdef WINDOW_ONLY_EVENT
 #error "Don't define WINDOW_ONLY_EVENT"
 #endif /* WINDOW_ONLY_EVENT */
 #ifdef TOUCH_EVENT
 #error "Don't define TOUCH_EVENT"
 #endif /* TOUCH_EVENT */
 #ifdef DOCUMENT_ONLY_EVENT
 #error "Don't define DOCUMENT_ONLY_EVENT"
 #endif /* DOCUMENT_ONLY_EVENT */
 #ifdef NON_IDL_EVENT
 #error "Don't define NON_IDL_EVENT"
 #endif /* NON_IDL_EVENT */
 
-#define EVENT ID_TO_EVENT
-#define WINDOW_ONLY_EVENT ID_TO_EVENT
-#define TOUCH_EVENT ID_TO_EVENT
-#define DOCUMENT_ONLY_EVENT ID_TO_EVENT
-#define NON_IDL_EVENT ID_TO_EVENT
+#define EVENT MESSAGE_TO_EVENT
+#define WINDOW_ONLY_EVENT MESSAGE_TO_EVENT
+#define TOUCH_EVENT MESSAGE_TO_EVENT
+#define DOCUMENT_ONLY_EVENT MESSAGE_TO_EVENT
+#define NON_IDL_EVENT MESSAGE_TO_EVENT
 #endif
 
 #ifdef DEFINED_FORWARDED_EVENT
 #error "Don't define DEFINED_FORWARDED_EVENT"
 #endif /* DEFINED_FORWARDED_EVENT */
 
 #ifndef FORWARDED_EVENT
 #define FORWARDED_EVENT EVENT
 #define DEFINED_FORWARDED_EVENT
 #endif /* FORWARDED_EVENT */
 
 #ifdef DEFINED_WINDOW_ONLY_EVENT
 #error "Don't define DEFINED_WINDOW_ONLY_EVENT"
 #endif /* DEFINED_WINDOW_ONLY_EVENT */
 
 #ifndef WINDOW_ONLY_EVENT
-#define WINDOW_ONLY_EVENT(_name, _id, _type, _struct)
+#define WINDOW_ONLY_EVENT(_name, _message, _type, _struct)
 #define DEFINED_WINDOW_ONLY_EVENT
 #endif /* WINDOW_ONLY_EVENT */
 
 #ifdef DEFINED_WINDOW_EVENT
 #error "Don't define DEFINED_WINDOW_EVENT"
 #endif /* DEFINED_WINDOW_EVENT */
 
 #ifndef WINDOW_EVENT
@@ -103,35 +103,35 @@
 #define DEFINED_WINDOW_EVENT
 #endif /* WINDOW_EVENT */
 
 #ifdef DEFINED_TOUCH_EVENT
 #error "Don't define DEFINED_TOUCH_EVENT"
 #endif /* DEFINED_TOUCH_EVENT */
 
 #ifndef TOUCH_EVENT
-#define TOUCH_EVENT(_name, _id, _type, _struct)
+#define TOUCH_EVENT(_name, _message, _type, _struct)
 #define DEFINED_TOUCH_EVENT
 #endif /* TOUCH_EVENT */
 
 #ifdef DEFINED_DOCUMENT_ONLY_EVENT
 #error "Don't define DEFINED_DOCUMENT_ONLY_EVENT"
 #endif /* DEFINED_DOCUMENT_ONLY_EVENT */
 
 #ifndef DOCUMENT_ONLY_EVENT
-#define DOCUMENT_ONLY_EVENT(_name, _id, _type, _struct)
+#define DOCUMENT_ONLY_EVENT(_name, _message, _type, _struct)
 #define DEFINED_DOCUMENT_ONLY_EVENT
 #endif /* DOCUMENT_ONLY_EVENT */
 
 #ifdef DEFINED_NON_IDL_EVENT
 #error "Don't define DEFINED_NON_IDL_EVENT"
 #endif /* DEFINED_NON_IDL_EVENT */
 
 #ifndef NON_IDL_EVENT
-#define NON_IDL_EVENT(_name, _id, _type, _struct)
+#define NON_IDL_EVENT(_name, _message, _type, _struct)
 #define DEFINED_NON_IDL_EVENT
 #endif /* NON_IDL_EVENT */
 
 #ifdef DEFINED_ERROR_EVENT
 #error "Don't define DEFINED_ERROR_EVENT"
 #endif /* DEFINED_ERROR_EVENT */
 
 #ifndef ERROR_EVENT
@@ -758,48 +758,48 @@ NON_IDL_EVENT(SVGScroll,
               EventNameType_None,
               eBasicEventClass)
 
 NON_IDL_EVENT(SVGZoom,
               NS_SVG_ZOOM,
               EventNameType_None,
               eSVGZoomEventClass)
 
-// Only map the ID to the real event name when ID_TO_EVENT is defined.
-#ifndef ID_TO_EVENT
+// Only map the ID to the real event name when MESSAGE_TO_EVENT is defined.
+#ifndef MESSAGE_TO_EVENT
 // This is a bit hackish, but SVG's event names are weird.
 NON_IDL_EVENT(zoom,
               NS_SVG_ZOOM,
               EventNameType_SVGSVG,
               eBasicEventClass)
 #endif
-// Only map the ID to the real event name when ID_TO_EVENT is defined.
-#ifndef ID_TO_EVENT
+// Only map the ID to the real event name when MESSAGE_TO_EVENT is defined.
+#ifndef MESSAGE_TO_EVENT
 NON_IDL_EVENT(begin,
               NS_SMIL_BEGIN,
               EventNameType_SMIL,
               eBasicEventClass)
 #endif
 NON_IDL_EVENT(beginEvent,
               NS_SMIL_BEGIN,
               EventNameType_None,
               eSMILTimeEventClass)
-// Only map the ID to the real event name when ID_TO_EVENT is defined.
-#ifndef ID_TO_EVENT
+// Only map the ID to the real event name when MESSAGE_TO_EVENT is defined.
+#ifndef MESSAGE_TO_EVENT
 NON_IDL_EVENT(end,
               NS_SMIL_END,
               EventNameType_SMIL,
               eBasicEventClass)
 #endif
 NON_IDL_EVENT(endEvent,
               NS_SMIL_END,
               EventNameType_None,
               eSMILTimeEventClass)
-// Only map the ID to the real event name when ID_TO_EVENT is defined.
-#ifndef ID_TO_EVENT
+// Only map the ID to the real event name when MESSAGE_TO_EVENT is defined.
+#ifndef MESSAGE_TO_EVENT
 NON_IDL_EVENT(repeat,
               NS_SMIL_REPEAT,
               EventNameType_SMIL,
               eBasicEventClass)
 #endif
 NON_IDL_EVENT(repeatEvent,
               NS_SMIL_REPEAT,
               EventNameType_None,
@@ -962,16 +962,16 @@ NON_IDL_EVENT(complete,
 #undef ERROR_EVENT
 #endif /* DEFINED_ERROR_EVENT */
 
 #ifdef DEFINED_BEFOREUNLOAD_EVENT
 #undef DEFINED_BEFOREUNLOAD_EVENT
 #undef BEFOREUNLOAD_EVENT
 #endif /* BEFOREUNLOAD_EVENT */
 
-#ifdef ID_TO_EVENT
+#ifdef MESSAGE_TO_EVENT
 #undef EVENT
 #undef WINDOW_ONLY_EVENT
 #undef TOUCH_EVENT
 #undef DOCUMENT_ONLY_EVENT
 #undef NON_IDL_EVENT
-#endif /* ID_TO_EVENT */
+#endif /* MESSAGE_TO_EVENT */
 
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -620,17 +620,17 @@ EventStateManager::PreHandleEvent(nsPres
       // then fall through...
     } else {
       if (sPointerEventEnabled) {
         // We should synthetize corresponding pointer events
         GeneratePointerEnterExit(NS_POINTER_LEAVE, mouseEvent);
       }
       GenerateMouseEnterExit(mouseEvent);
       //This is a window level mouse exit event and should stop here
-      aEvent->mMessage = 0;
+      aEvent->mMessage = NS_EVENT_NULL;
       break;
     }
   case NS_MOUSE_MOVE:
   case NS_POINTER_DOWN:
   case NS_POINTER_MOVE: {
     // on the Mac, GenerateDragGesture() may not return until the drag
     // has completed and so |aTargetFrame| may have been deleted (moving
     // a bookmark, for example).  If this is the case, however, we know
@@ -831,16 +831,18 @@ EventStateManager::PreHandleEvent(nsPres
       WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
       WidgetQueryContentEvent selectedText(true, NS_QUERY_SELECTED_TEXT,
                                            compositionEvent->widget);
       DoQuerySelectedText(&selectedText);
       NS_ASSERTION(selectedText.mSucceeded, "Failed to get selected text");
       compositionEvent->mData = selectedText.mReply.mString;
     }
     break;
+  default:
+    break;
   }
   return NS_OK;
 }
 
 // static
 int32_t
 EventStateManager::GetAccessModifierMaskFor(nsISupports* aDocShell)
 {
@@ -1189,16 +1191,18 @@ CrossProcessSafeEvent(const WidgetEvent&
       return false;
     }
   case eDragEventClass:
     switch (aEvent.mMessage) {
     case NS_DRAGDROP_OVER:
     case NS_DRAGDROP_EXIT:
     case NS_DRAGDROP_DROP:
       return true;
+    default:
+      break;
     }
   default:
     return false;
   }
 }
 
 bool
 EventStateManager::HandleCrossProcessEvent(WidgetEvent* aEvent,
@@ -3327,16 +3331,19 @@ EventStateManager::PostHandleEvent(nsPre
       nsCOMPtr<nsIContent> targetContent;
       mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
       if (!NodeAllowsClickThrough(targetContent)) {
         *aStatus = nsEventStatus_eConsumeNoDefault;
       }
     }
     break;
 #endif
+
+  default:
+    break;
   }
 
   //Reset target frame to null to avoid mistargeting after reentrant event
   mCurrentTarget = nullptr;
   mCurrentTargetContent = nullptr;
 
   return ret;
 }
@@ -3680,17 +3687,17 @@ EventStateManager::IsHandlingUserInput()
 
   TimeDuration timeout = nsContentUtils::HandlingUserInputTimeout();
   return timeout <= TimeDuration(0) ||
          (TimeStamp::Now() - sHandlingInputStart) <= timeout;
 }
 
 static void
 CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
-                                uint32_t aMessage,
+                                EventMessage aMessage,
                                 nsIContent* aRelatedContent,
                                 nsAutoPtr<WidgetMouseEvent>& aNewEvent)
 {
   WidgetPointerEvent* sourcePointer = aMouseEvent->AsPointerEvent();
   if (sourcePointer) {
     PROFILER_LABEL("Input", "DispatchPointerEvent",
       js::ProfileEntry::Category::EVENTS);
 
@@ -3720,17 +3727,17 @@ CreateMouseOrPointerWidgetEvent(WidgetMo
   aNewEvent->buttons = aMouseEvent->buttons;
   aNewEvent->pressure = aMouseEvent->pressure;
   aNewEvent->mPluginEvent = aMouseEvent->mPluginEvent;
   aNewEvent->inputSource = aMouseEvent->inputSource;
 }
 
 nsIFrame*
 EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
-                                               uint32_t aMessage,
+                                               EventMessage aMessage,
                                                nsIContent* aTargetContent,
                                                nsIContent* aRelatedContent)
 {
   // http://dvcs.w3.org/hg/webevents/raw-file/default/mouse-lock.html#methods
   // "[When the mouse is locked on an element...e]vents that require the concept
   // of a mouse cursor must not be dispatched (for example: mouseover, mouseout).
   if (sIsPointerLocked &&
       (aMessage == NS_MOUSELEAVE ||
@@ -3809,20 +3816,21 @@ EventStateManager::DispatchMouseOrPointe
   return targetFrame;
 }
 
 class EnterLeaveDispatcher
 {
 public:
   EnterLeaveDispatcher(EventStateManager* aESM,
                        nsIContent* aTarget, nsIContent* aRelatedTarget,
-                       WidgetMouseEvent* aMouseEvent, uint32_t aType)
+                       WidgetMouseEvent* aMouseEvent,
+                       EventMessage aEventMessage)
     : mESM(aESM)
     , mMouseEvent(aMouseEvent)
-    , mType(aType)
+    , mEventMessage(aEventMessage)
   {
     nsPIDOMWindow* win =
       aTarget ? aTarget->OwnerDoc()->GetInnerWindow() : nullptr;
     if (aMouseEvent->AsPointerEvent() ? win && win->HasPointerEnterLeaveEventListeners() :
                                         win && win->HasMouseEnterLeaveEventListeners()) {
       mRelatedTarget = aRelatedTarget ?
         aRelatedTarget->FindFirstNonChromeOnlyAccessContent() : nullptr;
       nsINode* commonParent = nullptr;
@@ -3839,35 +3847,35 @@ public:
         // mouseenter/leave is fired only on elements.
         current = current->GetParent();
       }
     }
   }
 
   ~EnterLeaveDispatcher()
   {
-    if (mType == NS_MOUSEENTER ||
-        mType == NS_POINTER_ENTER) {
+    if (mEventMessage == NS_MOUSEENTER ||
+        mEventMessage == NS_POINTER_ENTER) {
       for (int32_t i = mTargets.Count() - 1; i >= 0; --i) {
-        mESM->DispatchMouseOrPointerEvent(mMouseEvent, mType, mTargets[i],
-                                          mRelatedTarget);
+        mESM->DispatchMouseOrPointerEvent(mMouseEvent, mEventMessage,
+                                          mTargets[i], mRelatedTarget);
       }
     } else {
       for (int32_t i = 0; i < mTargets.Count(); ++i) {
-        mESM->DispatchMouseOrPointerEvent(mMouseEvent, mType, mTargets[i],
-                                          mRelatedTarget);
+        mESM->DispatchMouseOrPointerEvent(mMouseEvent, mEventMessage,
+                                          mTargets[i], mRelatedTarget);
       }
     }
   }
 
   EventStateManager* mESM;
   nsCOMArray<nsIContent> mTargets;
   nsCOMPtr<nsIContent> mRelatedTarget;
   WidgetMouseEvent* mMouseEvent;
-  uint32_t mType;
+  EventMessage mEventMessage;
 };
 
 void
 EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
                                   nsIContent* aMovingInto)
 {
   OverOutElementsWrapper* wrapper = GetWrapperByEventID(aMouseEvent);
 
@@ -4050,17 +4058,18 @@ GetWindowInnerRectCenter(nsPIDOMWindow* 
   int32_t cssScreenY = aContext->DevPixelsToIntCSSPixels(screen.y);
 
   return LayoutDeviceIntPoint(
     aContext->CSSPixelsToDevPixels(innerX - cssScreenX + innerWidth / 2),
     aContext->CSSPixelsToDevPixels(innerY - cssScreenY + innerHeight / 2));
 }
 
 void
-EventStateManager::GeneratePointerEnterExit(uint32_t aMessage, WidgetMouseEvent* aEvent)
+EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
+                                            WidgetMouseEvent* aEvent)
 {
   WidgetPointerEvent pointerEvent(*aEvent);
   pointerEvent.mMessage = aMessage;
   GenerateMouseEnterExit(&pointerEvent);
 }
 
 void
 EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
@@ -4173,16 +4182,18 @@ EventStateManager::GenerateMouseEnterExi
 
       // Reset sLastRefPoint, so that we'll know not to report any
       // movement the next time we re-enter the window.
       sLastRefPoint = kInvalidRefPoint;
 
       NotifyMouseOut(aMouseEvent, nullptr);
     }
     break;
+  default:
+    break;
   }
 
   // reset mCurretTargetContent to what it was
   mCurrentTargetContent = targetBeforeEvent;
 }
 
 OverOutElementsWrapper*
 EventStateManager::GetWrapperByEventID(WidgetMouseEvent* aEvent)
@@ -4319,35 +4330,38 @@ EventStateManager::GenerateDragDropEnter
         FireDragEnterOrExit(lastDragOverFramePresContext,
                             aDragEvent, NS_DRAGDROP_LEAVE,
                             nullptr, lastContent, sLastDragOverFrame);
 
         sLastDragOverFrame = nullptr;
       }
     }
     break;
+
+  default:
+    break;
   }
 
   //reset mCurretTargetContent to what it was
   mCurrentTargetContent = targetBeforeEvent;
 
   // Now flush all pending notifications, for better responsiveness.
   FlushPendingEvents(aPresContext);
 }
 
 void
 EventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
                                        WidgetDragEvent* aDragEvent,
-                                       uint32_t aMsg,
+                                       EventMessage aMessage,
                                        nsIContent* aRelatedTarget,
                                        nsIContent* aTargetContent,
                                        nsWeakFrame& aTargetFrame)
 {
   nsEventStatus status = nsEventStatus_eIgnore;
-  WidgetDragEvent event(aDragEvent->mFlags.mIsTrusted, aMsg,
+  WidgetDragEvent event(aDragEvent->mFlags.mIsTrusted, aMessage,
                         aDragEvent->widget);
   event.refPoint = aDragEvent->refPoint;
   event.modifiers = aDragEvent->modifiers;
   event.buttons = aDragEvent->buttons;
   event.relatedTarget = aRelatedTarget;
   event.inputSource = aDragEvent->inputSource;
 
   mCurrentTargetContent = aTargetContent;
@@ -4355,25 +4369,29 @@ EventStateManager::FireDragEnterOrExit(n
   if (aTargetContent != aRelatedTarget) {
     //XXX This event should still go somewhere!!
     if (aTargetContent) {
       EventDispatcher::Dispatch(aTargetContent, aPresContext, &event,
                                 nullptr, &status);
     }
 
     // adjust the drag hover if the dragenter event was cancelled or this is a drag exit
-    if (status == nsEventStatus_eConsumeNoDefault || aMsg == NS_DRAGDROP_EXIT)
-      SetContentState((aMsg == NS_DRAGDROP_ENTER) ? aTargetContent : nullptr,
+    if (status == nsEventStatus_eConsumeNoDefault ||
+        aMessage == NS_DRAGDROP_EXIT) {
+      SetContentState((aMessage == NS_DRAGDROP_ENTER) ?
+                        aTargetContent : nullptr,
                       NS_EVENT_STATE_DRAGOVER);
+    }
 
     // collect any changes to moz cursor settings stored in the event's
     // data transfer.
-    if (aMsg == NS_DRAGDROP_LEAVE || aMsg == NS_DRAGDROP_EXIT ||
-        aMsg == NS_DRAGDROP_ENTER)
+    if (aMessage == NS_DRAGDROP_LEAVE || aMessage == NS_DRAGDROP_EXIT ||
+        aMessage == NS_DRAGDROP_ENTER) {
       UpdateDragDataTransfer(&event);
+    }
   }
 
   // Finally dispatch the event to the frame
   if (aTargetFrame)
     aTargetFrame->HandleEvent(aPresContext, &event, &status);
 }
 
 void
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -298,23 +298,24 @@ protected:
                     nsIFrame* aTargetFrame,
                     nsEventStatus* aStatus);
   /**
    * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the specified
    * content.  This returns the primary frame for the content (or null
    * if it goes away during the event).
    */
   nsIFrame* DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
-                                        uint32_t aMessage,
+                                        EventMessage aMessage,
                                         nsIContent* aTargetContent,
                                         nsIContent* aRelatedContent);
   /**
    * Synthesize DOM pointerover and pointerout events
    */
-  void GeneratePointerEnterExit(uint32_t aMessage, WidgetMouseEvent* aEvent);
+  void GeneratePointerEnterExit(EventMessage aMessage,
+                                WidgetMouseEvent* aEvent);
   /**
    * Synthesize DOM and frame mouseover and mouseout events from this
    * MOUSE_MOVE or MOUSE_EXIT event.
    */
   void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent);
   /**
    * Tell this ESM and ESMs in parent documents that the mouse is
    * over some content in this document.
@@ -346,17 +347,17 @@ protected:
    * new target.
    *
    * @param aRelatedTarget relatedTarget to set for the event
    * @param aTargetContent target to set for the event
    * @param aTargetFrame target frame for the event
    */
   void FireDragEnterOrExit(nsPresContext* aPresContext,
                            WidgetDragEvent* aDragEvent,
-                           uint32_t aMsg,
+                           EventMessage aMessage,
                            nsIContent* aRelatedTarget,
                            nsIContent* aTargetContent,
                            nsWeakFrame& aTargetFrame);
   /**
    * Update the initial drag session data transfer with any changes that occur
    * on cloned data transfer objects used for events.
    */
   void UpdateDragDataTransfer(WidgetDragEvent* dragEvent);
--- a/dom/events/EventStates.h
+++ b/dom/events/EventStates.h
@@ -257,18 +257,16 @@ private:
 // Handler for click to play plugin (vulnerable w/no update)
 #define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(40)
 // Platform does not support plugin content (some mobile platforms)
 #define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(41)
 // Element is ltr (for :dir pseudo-class)
 #define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(42)
 // Element is rtl (for :dir pseudo-class)
 #define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(43)
-// Handler for play preview plugin
-#define NS_EVENT_STATE_TYPE_PLAY_PREVIEW NS_DEFINE_EVENT_STATE_MACRO(44)
 // Element is highlighted (devtools inspector)
 #define NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED NS_DEFINE_EVENT_STATE_MACRO(45)
 // Element is an unresolved custom element candidate
 #define NS_EVENT_STATE_UNRESOLVED NS_DEFINE_EVENT_STATE_MACRO(46)
 
 // Event state that is used for values that need to be parsed but do nothing.
 #define NS_EVENT_STATE_IGNORE NS_DEFINE_EVENT_STATE_MACRO(63)
 
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -129,17 +129,17 @@ GetIMEStateSetOpenName(IMEState::Open aO
     case IMEState::CLOSED:
       return "CLOSED";
     default:
       return "illegal value";
   }
 }
 
 static const char*
-GetEventMessageName(uint32_t aMessage)
+GetEventMessageName(EventMessage aMessage)
 {
   switch (aMessage) {
     case NS_COMPOSITION_START:
       return "NS_COMPOSITION_START";
     case NS_COMPOSITION_END:
       return "NS_COMPOSITION_END";
     case NS_COMPOSITION_UPDATE:
       return "NS_COMPOSITION_UPDATE";
--- a/dom/events/InputEvent.cpp
+++ b/dom/events/InputEvent.cpp
@@ -10,17 +10,19 @@
 
 namespace mozilla {
 namespace dom {
 
 InputEvent::InputEvent(EventTarget* aOwner,
                        nsPresContext* aPresContext,
                        InternalEditorInputEvent* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new InternalEditorInputEvent(false, 0, nullptr))
+            aEvent ? aEvent :
+                     new InternalEditorInputEvent(false, NS_EVENT_NULL,
+                                                  nullptr))
 {
   NS_ASSERTION(mEvent->mClass == eEditorInputEventClass,
                "event type mismatch");
 
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
--- a/dom/events/InternalMutationEvent.h
+++ b/dom/events/InternalMutationEvent.h
@@ -14,17 +14,17 @@
 
 namespace mozilla {
 
 class InternalMutationEvent : public WidgetEvent
 {
 public:
   virtual InternalMutationEvent* AsMutationEvent() override { return this; }
 
-  InternalMutationEvent(bool aIsTrusted, uint32_t aMessage)
+  InternalMutationEvent(bool aIsTrusted, EventMessage aMessage)
     : WidgetEvent(aIsTrusted, aMessage, eMutationEventClass)
     , mAttrChange(0)
   {
     mFlags.mCancelable = false;
   }
 
   virtual WidgetEvent* Duplicate() const override
   {
--- a/dom/events/KeyboardEvent.cpp
+++ b/dom/events/KeyboardEvent.cpp
@@ -10,17 +10,18 @@
 
 namespace mozilla {
 namespace dom {
 
 KeyboardEvent::KeyboardEvent(EventTarget* aOwner,
                              nsPresContext* aPresContext,
                              WidgetKeyboardEvent* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new WidgetKeyboardEvent(false, 0, nullptr))
+            aEvent ? aEvent :
+                     new WidgetKeyboardEvent(false, NS_EVENT_NULL, nullptr))
   , mInitializedByCtor(false)
   , mInitializedWhichValue(0)
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
@@ -156,16 +157,18 @@ KeyboardEvent::CharCode()
   case NS_KEY_DOWN:
   case NS_KEY_AFTER_DOWN:
   case NS_KEY_BEFORE_UP:
   case NS_KEY_UP:
   case NS_KEY_AFTER_UP:
     return 0;
   case NS_KEY_PRESS:
     return mEvent->AsKeyboardEvent()->charCode;
+  default:
+    break;
   }
   return 0;
 }
 
 NS_IMETHODIMP
 KeyboardEvent::GetKeyCode(uint32_t* aKeyCode)
 {
   NS_ENSURE_ARG_POINTER(aKeyCode);
@@ -208,16 +211,18 @@ KeyboardEvent::Which()
       //more closely mirror the values that 4.x gave for RETURN and BACKSPACE
       {
         uint32_t keyCode = mEvent->AsKeyboardEvent()->keyCode;
         if (keyCode == NS_VK_RETURN || keyCode == NS_VK_BACK) {
           return keyCode;
         }
         return CharCode();
       }
+    default:
+      break;
   }
 
   return 0;
 }
 
 NS_IMETHODIMP
 KeyboardEvent::GetLocation(uint32_t* aLocation)
 {
--- a/dom/events/MouseEvent.cpp
+++ b/dom/events/MouseEvent.cpp
@@ -12,18 +12,19 @@
 
 namespace mozilla {
 namespace dom {
 
 MouseEvent::MouseEvent(EventTarget* aOwner,
                        nsPresContext* aPresContext,
                        WidgetMouseEventBase* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new WidgetMouseEvent(false, 0, nullptr,
-                                                   WidgetMouseEvent::eReal))
+            aEvent ? aEvent :
+                     new WidgetMouseEvent(false, NS_EVENT_NULL, nullptr,
+                                          WidgetMouseEvent::eReal))
 {
   // There's no way to make this class' ctor allocate an WidgetMouseScrollEvent.
   // It's not that important, though, since a scroll event is not a real
   // DOM event.
 
   WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
   if (aEvent) {
     mEventIsInternal = false;
--- a/dom/events/MouseScrollEvent.cpp
+++ b/dom/events/MouseScrollEvent.cpp
@@ -10,17 +10,19 @@
 
 namespace mozilla {
 namespace dom {
 
 MouseScrollEvent::MouseScrollEvent(EventTarget* aOwner,
                                    nsPresContext* aPresContext,
                                    WidgetMouseScrollEvent* aEvent)
   : MouseEvent(aOwner, aPresContext,
-               aEvent ? aEvent : new WidgetMouseScrollEvent(false, 0, nullptr))
+               aEvent ? aEvent :
+                        new WidgetMouseScrollEvent(false, NS_EVENT_NULL,
+                                                   nullptr))
 {
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
     mEvent->refPoint.x = mEvent->refPoint.y = 0;
     static_cast<WidgetMouseEventBase*>(mEvent)->inputSource =
--- a/dom/events/MutationEvent.cpp
+++ b/dom/events/MutationEvent.cpp
@@ -12,17 +12,17 @@ class nsPresContext;
 
 namespace mozilla {
 namespace dom {
 
 MutationEvent::MutationEvent(EventTarget* aOwner,
                              nsPresContext* aPresContext,
                              InternalMutationEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalMutationEvent(false, 0))
+          aEvent ? aEvent : new InternalMutationEvent(false, NS_EVENT_NULL))
 {
   mEventIsInternal = (aEvent == nullptr);
 }
 
 NS_INTERFACE_MAP_BEGIN(MutationEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMutationEvent)
 NS_INTERFACE_MAP_END_INHERITING(Event)
 
--- a/dom/events/NotifyPaintEvent.cpp
+++ b/dom/events/NotifyPaintEvent.cpp
@@ -13,22 +13,22 @@
 #include "nsContentUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 NotifyPaintEvent::NotifyPaintEvent(EventTarget* aOwner,
                                    nsPresContext* aPresContext,
                                    WidgetEvent* aEvent,
-                                   uint32_t aEventType,
+                                   EventMessage aEventMessage,
                                    nsInvalidateRequestList* aInvalidateRequests)
   : Event(aOwner, aPresContext, aEvent)
 {
   if (mEvent) {
-    mEvent->mMessage = aEventType;
+    mEvent->mMessage = aEventMessage;
   }
   if (aInvalidateRequests) {
     mInvalidateRequests.AppendElements(Move(aInvalidateRequests->mRequests));
   }
 }
 
 NS_INTERFACE_MAP_BEGIN(NotifyPaintEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyPaintEvent)
@@ -161,16 +161,16 @@ NotifyPaintEvent::Deserialize(const IPC:
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 already_AddRefed<NotifyPaintEvent>
 NS_NewDOMNotifyPaintEvent(EventTarget* aOwner,
                           nsPresContext* aPresContext,
                           WidgetEvent* aEvent,
-                          uint32_t aEventType,
+                          EventMessage aEventMessage,
                           nsInvalidateRequestList* aInvalidateRequests) 
 {
   nsRefPtr<NotifyPaintEvent> it =
-    new NotifyPaintEvent(aOwner, aPresContext, aEvent, aEventType,
+    new NotifyPaintEvent(aOwner, aPresContext, aEvent, aEventMessage,
                          aInvalidateRequests);
   return it.forget();
 }
--- a/dom/events/NotifyPaintEvent.h
+++ b/dom/events/NotifyPaintEvent.h
@@ -23,17 +23,17 @@ class PaintRequestList;
 class NotifyPaintEvent : public Event,
                          public nsIDOMNotifyPaintEvent
 {
 
 public:
   NotifyPaintEvent(EventTarget* aOwner,
                    nsPresContext* aPresContext,
                    WidgetEvent* aEvent,
-                   uint32_t aEventType,
+                   EventMessage aEventMessage,
                    nsInvalidateRequestList* aInvalidateRequests);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMNOTIFYPAINTEVENT
 
   // Forward to base class
   NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION
@@ -67,12 +67,14 @@ private:
 } // namespace dom
 } // namespace mozilla
 
 // This empties aInvalidateRequests.
 already_AddRefed<mozilla::dom::NotifyPaintEvent>
 NS_NewDOMNotifyPaintEvent(mozilla::dom::EventTarget* aOwner,
                           nsPresContext* aPresContext,
                           mozilla::WidgetEvent* aEvent,
-                          uint32_t aEventType = 0,
-                          nsInvalidateRequestList* aInvalidateRequests = nullptr);
+                          mozilla::EventMessage aEventMessage =
+                            mozilla::NS_EVENT_NULL,
+                          nsInvalidateRequestList* aInvalidateRequests =
+                            nullptr);
 
 #endif // mozilla_dom_NotifyPaintEvent_h_
--- a/dom/events/PointerEvent.cpp
+++ b/dom/events/PointerEvent.cpp
@@ -12,17 +12,18 @@
 
 namespace mozilla {
 namespace dom {
 
 PointerEvent::PointerEvent(EventTarget* aOwner,
                            nsPresContext* aPresContext,
                            WidgetPointerEvent* aEvent)
   : MouseEvent(aOwner, aPresContext,
-               aEvent ? aEvent : new WidgetPointerEvent(false, 0, nullptr))
+               aEvent ? aEvent :
+                        new WidgetPointerEvent(false, NS_EVENT_NULL, nullptr))
 {
   NS_ASSERTION(mEvent->mClass == ePointerEventClass,
                "event type mismatch ePointerEventClass");
 
   WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
   if (aEvent) {
     mEventIsInternal = false;
   } else {
--- a/dom/events/SimpleGestureEvent.cpp
+++ b/dom/events/SimpleGestureEvent.cpp
@@ -11,17 +11,18 @@
 namespace mozilla {
 namespace dom {
 
 SimpleGestureEvent::SimpleGestureEvent(EventTarget* aOwner,
                                        nsPresContext* aPresContext,
                                        WidgetSimpleGestureEvent* aEvent)
   : MouseEvent(aOwner, aPresContext,
                aEvent ? aEvent :
-                        new WidgetSimpleGestureEvent(false, 0, nullptr))
+                        new WidgetSimpleGestureEvent(false, NS_EVENT_NULL,
+                                                     nullptr))
 {
   NS_ASSERTION(mEvent->mClass == eSimpleGestureEventClass,
                "event type mismatch");
 
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -95,17 +95,17 @@ TextComposition::MaybeDispatchCompositio
   }
   CloneAndDispatchAs(aCompositionEvent, NS_COMPOSITION_UPDATE);
   return IsValidStateForComposition(aCompositionEvent->widget);
 }
 
 BaseEventFlags
 TextComposition::CloneAndDispatchAs(
                    const WidgetCompositionEvent* aCompositionEvent,
-                   uint32_t aMessage,
+                   EventMessage aMessage,
                    nsEventStatus* aStatus,
                    EventDispatchingCallback* aCallBack)
 {
   MOZ_RELEASE_ASSERT(!mTabParent);
 
   MOZ_ASSERT(IsValidStateForComposition(aCompositionEvent->widget),
              "Should be called only when it's safe to dispatch an event");
 
@@ -432,17 +432,17 @@ TextComposition::NotityUpdateComposition
   } else {
     return;
   }
 
   NotifyIME(NOTIFY_IME_OF_COMPOSITION_UPDATE);
 }
 
 void
-TextComposition::DispatchCompositionEventRunnable(uint32_t aEventMessage,
+TextComposition::DispatchCompositionEventRunnable(EventMessage aEventMessage,
                                                   const nsAString& aData,
                                                   bool aIsSynthesizingCommit)
 {
   nsContentUtils::AddScriptRunner(
     new CompositionEventDispatcher(this, mNode, aEventMessage, aData,
                                    aIsSynthesizingCommit));
 }
 
@@ -580,23 +580,23 @@ TextComposition::HasEditor() const
 
 /******************************************************************************
  * TextComposition::CompositionEventDispatcher
  ******************************************************************************/
 
 TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
                                                TextComposition* aComposition,
                                                nsINode* aEventTarget,
-                                               uint32_t aEventMessage,
+                                               EventMessage aEventMessage,
                                                const nsAString& aData,
                                                bool aIsSynthesizedEvent)
   : mTextComposition(aComposition)
   , mEventTarget(aEventTarget)
+  , mData(aData)
   , mEventMessage(aEventMessage)
-  , mData(aData)
   , mIsSynthesizedEvent(aIsSynthesizedEvent)
 {
 }
 
 NS_IMETHODIMP
 TextComposition::CompositionEventDispatcher::Run()
 {
   // The widget can be different from the widget which has dispatched
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -314,17 +314,17 @@ private:
   /**
    * CloneAndDispatchAs() dispatches a composition event which is
    * duplicateed from aCompositionEvent and set the aMessage.
    *
    * @return Returns BaseEventFlags which is the result of dispatched event.
    */
   BaseEventFlags CloneAndDispatchAs(
                    const WidgetCompositionEvent* aCompositionEvent,
-                   uint32_t aMessage,
+                   EventMessage aMessage,
                    nsEventStatus* aStatus = nullptr,
                    EventDispatchingCallback* aCallBack = nullptr);
 
   /**
    * If IME has already dispatched compositionend event but it was discarded
    * by PresShell due to not safe to dispatch, this returns true.
    */
   bool WasNativeCompositionEndEventDiscarded() const
@@ -348,26 +348,26 @@ private:
    * CompositionEventDispatcher dispatches the specified composition (or text)
    * event.
    */
   class CompositionEventDispatcher : public nsRunnable
   {
   public:
     CompositionEventDispatcher(TextComposition* aTextComposition,
                                nsINode* aEventTarget,
-                               uint32_t aEventMessage,
+                               EventMessage aEventMessage,
                                const nsAString& aData,
                                bool aIsSynthesizedEvent = false);
     NS_IMETHOD Run() override;
 
   private:
     nsRefPtr<TextComposition> mTextComposition;
     nsCOMPtr<nsINode> mEventTarget;
-    uint32_t mEventMessage;
     nsString mData;
+    EventMessage mEventMessage;
     bool mIsSynthesizedEvent;
 
     CompositionEventDispatcher() {};
   };
 
   /**
    * DispatchCompositionEventRunnable() dispatches a composition event to the
    * content.  Be aware, if you use this method, nsPresShellEventCB isn't used.
@@ -376,17 +376,17 @@ private:
    *          destroyed by this method call.
    *
    * @param aEventMessage       Must be one of composition events.
    * @param aData               Used for mData value.
    * @param aIsSynthesizingCommit   true if this is called for synthesizing
    *                                commit or cancel composition.  Otherwise,
    *                                false.
    */
-  void DispatchCompositionEventRunnable(uint32_t aEventMessage,
+  void DispatchCompositionEventRunnable(EventMessage aEventMessage,
                                         const nsAString& aData,
                                         bool aIsSynthesizingCommit = false);
 };
 
 /**
  * TextCompositionArray manages the instances of TextComposition class.
  * Managing with array is enough because only one composition is typically
  * there.  Even if user switches native IME context, it's very rare that
--- a/dom/events/TouchEvent.cpp
+++ b/dom/events/TouchEvent.cpp
@@ -58,17 +58,18 @@ TouchList::IdentifiedTouch(int32_t aIden
 /******************************************************************************
  * TouchEvent
  *****************************************************************************/
 
 TouchEvent::TouchEvent(EventTarget* aOwner,
                        nsPresContext* aPresContext,
                        WidgetTouchEvent* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new WidgetTouchEvent(false, 0, nullptr))
+            aEvent ? aEvent :
+                     new WidgetTouchEvent(false, NS_EVENT_NULL, nullptr))
 {
   if (aEvent) {
     mEventIsInternal = false;
 
     for (uint32_t i = 0; i < aEvent->touches.Length(); ++i) {
       Touch* touch = aEvent->touches[i];
       touch->InitializePoints(mPresContext, aEvent);
     }
--- a/dom/events/TransitionEvent.cpp
+++ b/dom/events/TransitionEvent.cpp
@@ -10,17 +10,17 @@
 
 namespace mozilla {
 namespace dom {
 
 TransitionEvent::TransitionEvent(EventTarget* aOwner,
                                  nsPresContext* aPresContext,
                                  InternalTransitionEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalTransitionEvent(false, 0))
+          aEvent ? aEvent : new InternalTransitionEvent(false, NS_EVENT_NULL))
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
   }
--- a/dom/events/UIEvent.cpp
+++ b/dom/events/UIEvent.cpp
@@ -24,17 +24,17 @@
 
 namespace mozilla {
 namespace dom {
 
 UIEvent::UIEvent(EventTarget* aOwner,
                  nsPresContext* aPresContext,
                  WidgetGUIEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalUIEvent(false, 0, nullptr))
+          aEvent ? aEvent : new InternalUIEvent(false, NS_EVENT_NULL, nullptr))
   , mClientPoint(0, 0)
   , mLayerPoint(0, 0)
   , mPagePoint(0, 0)
   , mMovementPoint(0, 0)
   , mIsPointerLocked(EventStateManager::sIsPointerLocked)
   , mLastClientPoint(EventStateManager::sLastClientPoint)
 {
   if (aEvent) {
--- a/dom/events/WheelEvent.cpp
+++ b/dom/events/WheelEvent.cpp
@@ -11,17 +11,18 @@
 namespace mozilla {
 namespace dom {
 
 WheelEvent::WheelEvent(EventTarget* aOwner,
                        nsPresContext* aPresContext,
                        WidgetWheelEvent* aWheelEvent)
   : MouseEvent(aOwner, aPresContext,
                aWheelEvent ? aWheelEvent :
-                             new WidgetWheelEvent(false, 0, nullptr))
+                             new WidgetWheelEvent(false, NS_EVENT_NULL,
+                                                  nullptr))
   , mAppUnitsPerDevPixel(0)
 {
   if (aWheelEvent) {
     mEventIsInternal = false;
     // If the delta mode is pixel, the WidgetWheelEvent's delta values are in
     // device pixels.  However, JS contents need the delta values in CSS pixels.
     // We should store the value of mAppUnitsPerDevPixel here because
     // it might be changed by changing zoom or something.
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -213,16 +213,18 @@ WheelTransaction::OnEvent(WidgetEvent* a
     case NS_MOUSE_BUTTON_UP:
     case NS_MOUSE_BUTTON_DOWN:
     case NS_MOUSE_DOUBLECLICK:
     case NS_MOUSE_CLICK:
     case NS_CONTEXTMENU:
     case NS_DRAGDROP_DROP:
       EndTransaction();
       return;
+    default:
+      break;
   }
 }
 
 /* static */ void
 WheelTransaction::Shutdown()
 {
   NS_IF_RELEASE(sTimer);
 }
--- a/dom/events/XULCommandEvent.cpp
+++ b/dom/events/XULCommandEvent.cpp
@@ -9,17 +9,18 @@
 
 namespace mozilla {
 namespace dom {
 
 XULCommandEvent::XULCommandEvent(EventTarget* aOwner,
                                  nsPresContext* aPresContext,
                                  WidgetInputEvent* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new WidgetInputEvent(false, 0, nullptr))
+            aEvent ? aEvent :
+                     new WidgetInputEvent(false, NS_EVENT_NULL, nullptr))
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
   }
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -11,16 +11,17 @@
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/URL.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/workers/bindings/URL.h"
+#include "mozilla/unused.h"
 
 #include "WorkerPrivate.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
@@ -76,17 +77,27 @@ GetRequestURLFromDocument(nsIDocument* a
 {
   MOZ_ASSERT(aDocument);
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIURI> baseURI = aDocument->GetBaseURI();
   nsCOMPtr<nsIURI> resolvedURI;
   aRv = NS_NewURI(getter_AddRefs(resolvedURI), aInput, nullptr, baseURI);
   if (NS_WARN_IF(aRv.Failed())) {
-      return;
+    aRv.ThrowTypeError(MSG_INVALID_URL, &aInput);
+    return;
+  }
+
+  // This fails with URIs with weird protocols, even when they are valid,
+  // so we ignore the failure
+  nsAutoCString credentials;
+  unused << resolvedURI->GetUserPass(credentials);
+  if (!credentials.IsEmpty()) {
+    aRv.ThrowTypeError(MSG_URL_HAS_CREDENTIALS, &aInput);
+    return;
   }
 
   nsCOMPtr<nsIURI> resolvedURIClone;
   // We use CloneIgnoringRef to strip away the fragment even if the original URI
   // is immutable.
   aRv = resolvedURI->CloneIgnoringRef(getter_AddRefs(resolvedURIClone));
   if (NS_WARN_IF(aRv.Failed())) {
     return;
@@ -105,16 +116,26 @@ void
 GetRequestURLFromChrome(const nsAString& aInput, nsAString& aRequestURL,
                         ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIURI> uri;
   aRv = NS_NewURI(getter_AddRefs(uri), aInput, nullptr, nullptr);
   if (NS_WARN_IF(aRv.Failed())) {
+    aRv.ThrowTypeError(MSG_INVALID_URL, &aInput);
+    return;
+  }
+
+  // This fails with URIs with weird protocols, even when they are valid,
+  // so we ignore the failure
+  nsAutoCString credentials;
+  unused << uri->GetUserPass(credentials);
+  if (!credentials.IsEmpty()) {
+    aRv.ThrowTypeError(MSG_URL_HAS_CREDENTIALS, &aInput);
     return;
   }
 
   nsCOMPtr<nsIURI> uriClone;
   // We use CloneIgnoringRef to strip away the fragment even if the original URI
   // is immutable.
   aRv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
   if (NS_WARN_IF(aRv.Failed())) {
@@ -137,16 +158,34 @@ GetRequestURLFromWorker(const GlobalObje
   workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(worker);
   worker->AssertIsOnWorkerThread();
 
   NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref);
   nsRefPtr<workers::URL> url =
     workers::URL::Constructor(aGlobal, aInput, baseURL, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
+    aRv.ThrowTypeError(MSG_INVALID_URL, &aInput);
+    return;
+  }
+
+  nsString username;
+  url->GetUsername(username, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  nsString password;
+  url->GetPassword(password, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  if (!username.IsEmpty() || !password.IsEmpty()) {
+    aRv.ThrowTypeError(MSG_URL_HAS_CREDENTIALS, &aInput);
     return;
   }
 
   url->SetHash(EmptyString(), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -195,17 +195,17 @@ HTMLButtonElement::ParseAttribute(int32_
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 bool
-HTMLButtonElement::IsDisabledForEvents(uint32_t aMessage)
+HTMLButtonElement::IsDisabledForEvents(EventMessage aMessage)
 {
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
   nsIFrame* formFrame = do_QueryFrame(formControlFrame);
   return IsElementDisabledForEvents(aMessage, formFrame);
 }
 
 nsresult
 HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -47,17 +47,17 @@ public:
   NS_DECL_NSIDOMHTMLBUTTONELEMENT
 
   // overriden nsIFormControl methods
   NS_IMETHOD_(uint32_t) GetType() const override { return mType; }
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) override;
   NS_IMETHOD SaveState() override;
   bool RestoreState(nsPresState* aState) override;
-  virtual bool IsDisabledForEvents(uint32_t aMessage) override;
+  virtual bool IsDisabledForEvents(EventMessage aMessage) override;
 
   virtual void FieldSetDisabledChanged(bool aNotify) override;
 
   // nsIDOMEventTarget
   virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
--- a/dom/html/HTMLFieldSetElement.cpp
+++ b/dom/html/HTMLFieldSetElement.cpp
@@ -58,17 +58,17 @@ NS_IMPL_ELEMENT_CLONE(HTMLFieldSetElemen
 
 NS_IMPL_BOOL_ATTR(HTMLFieldSetElement, Disabled, disabled)
 NS_IMPL_STRING_ATTR(HTMLFieldSetElement, Name, name)
 
 // nsIConstraintValidation
 NS_IMPL_NSICONSTRAINTVALIDATION(HTMLFieldSetElement)
 
 bool
-HTMLFieldSetElement::IsDisabledForEvents(uint32_t aMessage)
+HTMLFieldSetElement::IsDisabledForEvents(EventMessage aMessage)
 {
   return IsElementDisabledForEvents(aMessage, nullptr);
 }
 
 // nsIContent
 nsresult
 HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
 {
--- a/dom/html/HTMLFieldSetElement.h
+++ b/dom/html/HTMLFieldSetElement.h
@@ -46,17 +46,17 @@ public:
   virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
                                      bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
 
   // nsIFormControl
   NS_IMETHOD_(uint32_t) GetType() const override { return NS_FORM_FIELDSET; }
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) override;
-  virtual bool IsDisabledForEvents(uint32_t aMessage) override;
+  virtual bool IsDisabledForEvents(EventMessage aMessage) override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   const nsIContent* GetFirstLegend() const { return mFirstLegend; }
 
   void AddElement(nsGenericHTMLFormElement* aElement);
 
   void RemoveElement(nsGenericHTMLFormElement* aElement);
 
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -530,17 +530,17 @@ HTMLFormElement::WillHandleEvent(EventCh
   }
   return NS_OK;
 }
 
 nsresult
 HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
 {
   if (aVisitor.mEvent->originalTarget == static_cast<nsIContent*>(this)) {
-    uint32_t msg = aVisitor.mEvent->mMessage;
+    EventMessage msg = aVisitor.mEvent->mMessage;
     if (msg == NS_FORM_SUBMIT) {
       // let the form know not to defer subsequent submissions
       mDeferSubmission = false;
     }
 
     if (aVisitor.mEventStatus == nsEventStatus_eIgnore) {
       switch (msg) {
         case NS_FORM_RESET:
@@ -550,18 +550,20 @@ HTMLFormElement::PostHandleEvent(EventCh
             // tell the form to forget a possible pending submission.
             // the reason is that the script returned true (the event was
             // ignored) so if there is a stored submission, it will miss
             // the name/value of the submitting element, thus we need
             // to forget it and the form element will build a new one
             mPendingSubmission = nullptr;
           }
           DoSubmitOrReset(aVisitor.mEvent, msg);
+          break;
         }
-        break;
+        default:
+          break;
       }
     } else {
       if (msg == NS_FORM_SUBMIT) {
         // tell the form to flush a possible pending submission.
         // the reason is that the script returned false (the event was
         // not ignored) so if there is a stored submission, it needs to
         // be submitted immediatelly.
         FlushPendingSubmission();
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3035,17 +3035,17 @@ HTMLInputElement::NeedToInitializeEditor
   case NS_SCROLLPORT_OVERFLOW:
     return false;
   default:
     return true;
   }
 }
 
 bool
-HTMLInputElement::IsDisabledForEvents(uint32_t aMessage)
+HTMLInputElement::IsDisabledForEvents(EventMessage aMessage)
 {
   return IsElementDisabledForEvents(aMessage, GetPrimaryFrame());
 }
 
 nsresult
 HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
 {
   // Do not process any DOM events if the element is disabled
@@ -3657,16 +3657,18 @@ HTMLInputElement::PostHandleEvent(EventC
         if (mForm) {
           // tell the form that we are about to exit a click handler
           // so the form knows not to defer subsequent submissions
           // the pending ones that were created during the handler
           // will be flushed or forgoten.
           mForm->OnSubmitClickEnd();
         }
         break;
+      default:
+        break;
     }
   }
 
   // Reset the flag for other content besides this text field
   aVisitor.mEvent->mFlags.mNoContentDispatch = noContentDispatch;
 
   // now check to see if the event was "cancelled"
   if (mCheckedIsToggled && outerActivateEvent) {
@@ -4151,16 +4153,19 @@ HTMLInputElement::PostHandleEventForRang
       }
       break;
 
     case NS_TOUCH_CANCEL:
       if (mIsDraggingRange) {
         CancelRangeThumbDrag();
       }
       break;
+
+    default:
+      break;
   }
 }
 
 void
 HTMLInputElement::MaybeLoadImage()
 {
   // Our base URI may have changed; claim that our URI changed, and the
   // nsImageLoadingContent will decide whether a new image load is warranted.
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -144,17 +144,17 @@ public:
 
   // Overriden nsIFormControl methods
   NS_IMETHOD_(uint32_t) GetType() const override { return mType; }
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) override;
   NS_IMETHOD SaveState() override;
   virtual bool RestoreState(nsPresState* aState) override;
   virtual bool AllowDrop() override;
-  virtual bool IsDisabledForEvents(uint32_t aMessage) override;
+  virtual bool IsDisabledForEvents(EventMessage aMessage) override;
 
   virtual void FieldSetDisabledChanged(bool aNotify) override;
 
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -192,16 +192,19 @@ HTMLLabelElement::PostHandleEvent(EventC
           eventFlags.mMultipleActionsPrevented = true;
           DispatchClickEvent(aVisitor.mPresContext, mouseEvent,
                              content, false, &eventFlags, &status);
           // Do we care about the status this returned?  I don't think we do...
           // Don't run another <label> off of this click
           mouseEvent->mFlags.mMultipleActionsPrevented = true;
         }
         break;
+
+      default:
+        break;
     }
     mHandlingEvent = false;
   }
   return NS_OK;
 }
 
 nsresult
 HTMLLabelElement::Reset()
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2329,17 +2329,16 @@ HTMLMediaElement::WakeLockCreate()
 }
 
 void
 HTMLMediaElement::WakeLockRelease()
 {
   if (mWakeLock) {
     ErrorResult rv;
     mWakeLock->Unlock(rv);
-    NS_WARN_IF_FALSE(!rv.Failed(), "Failed to unlock the wakelock.");
     mWakeLock = nullptr;
   }
 }
 
 bool HTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
                                       nsIAtom* aAttribute,
                                       const nsAString& aValue,
                                       nsAttrValue& aResult)
--- a/dom/html/HTMLMetaElement.cpp
+++ b/dom/html/HTMLMetaElement.cpp
@@ -51,16 +51,23 @@ HTMLMetaElement::SetItemValueText(const 
 
 nsresult
 HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                               const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::content) {
       nsIDocument *document = GetUncomposedDoc();
+      if (document && AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                                  nsGkAtoms::viewport, eIgnoreCase)) {
+        nsAutoString content;
+        nsresult rv = GetContent(content);
+        NS_ENSURE_SUCCESS(rv, rv);
+        nsContentUtils::ProcessViewportInfo(document, content);
+      }
       CreateAndDispatchEvent(document, NS_LITERAL_STRING("DOMMetaChanged"));
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                             aNotify);
 }
 
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -219,16 +219,18 @@ HTMLObjectElement::HandleFocusBlurPlugin
     case NS_FOCUS_CONTENT: {
       OnFocusBlurPlugin(aElement, true);
       break;
     }
     case NS_BLUR_CONTENT: {
       OnFocusBlurPlugin(aElement, false);
       break;
     }
+    default:
+      break;
   }
 }
 
 NS_IMETHODIMP
 HTMLObjectElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
 {
   HandleFocusBlurPlugin(this, aVisitor.mEvent);
   return NS_OK;
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -1482,17 +1482,17 @@ HTMLSelectElement::IsAttributeMapped(con
 
 nsMapRuleToAttributesFunc
 HTMLSelectElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 bool
-HTMLSelectElement::IsDisabledForEvents(uint32_t aMessage)
+HTMLSelectElement::IsDisabledForEvents(EventMessage aMessage)
 {
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
   nsIFrame* formFrame = nullptr;
   if (formControlFrame) {
     formFrame = do_QueryFrame(formControlFrame);
   }
   return IsElementDisabledForEvents(aMessage, formFrame);
 }
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -286,17 +286,17 @@ public:
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
 
   // Overriden nsIFormControl methods
   NS_IMETHOD_(uint32_t) GetType() const override { return NS_FORM_SELECT; }
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) override;
   NS_IMETHOD SaveState() override;
   virtual bool RestoreState(nsPresState* aState) override;
-  virtual bool IsDisabledForEvents(uint32_t aMessage) override;
+  virtual bool IsDisabledForEvents(EventMessage aMessage) override;
 
   virtual void FieldSetDisabledChanged(bool aNotify) override;
 
   EventStates IntrinsicState() const override;
 
   /**
    * To be called when stuff is added under a child of the select--but *before*
    * they are actually added.
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -464,17 +464,17 @@ HTMLTextAreaElement::IsAttributeMapped(c
 
 nsMapRuleToAttributesFunc
 HTMLTextAreaElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 bool
-HTMLTextAreaElement::IsDisabledForEvents(uint32_t aMessage)
+HTMLTextAreaElement::IsDisabledForEvents(EventMessage aMessage)
 {
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
   nsIFrame* formFrame = do_QueryFrame(formControlFrame);
   return IsElementDisabledForEvents(aMessage, formFrame);
 }
 
 nsresult
 HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -70,17 +70,17 @@ public:
   NS_IMETHOD SetUserInput(const nsAString& aInput) override;
 
   // nsIFormControl
   NS_IMETHOD_(uint32_t) GetType() const override { return NS_FORM_TEXTAREA; }
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) override;
   NS_IMETHOD SaveState() override;
   virtual bool RestoreState(nsPresState* aState) override;
-  virtual bool IsDisabledForEvents(uint32_t aMessage) override;
+  virtual bool IsDisabledForEvents(EventMessage aMessage) override;
 
   virtual void FieldSetDisabledChanged(bool aNotify) override;
 
   virtual EventStates IntrinsicState() const override;
 
   // nsITextControlElemet
   NS_IMETHOD SetValueChanged(bool aValueChanged) override;
   NS_IMETHOD_(bool) IsSingleLineTextControl() const override;
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -248,17 +248,16 @@ HTMLVideoElement::WakeLockRelease()
 void
 HTMLVideoElement::UpdateScreenWakeLock()
 {
   bool hidden = OwnerDoc()->Hidden();
 
   if (mScreenWakeLock && (mPaused || hidden)) {
     ErrorResult rv;
     mScreenWakeLock->Unlock(rv);
-    NS_WARN_IF_FALSE(!rv.Failed(), "Failed to unlock the wakelock.");
     mScreenWakeLock = nullptr;
     return;
   }
 
   if (!mScreenWakeLock && !mPaused && !hidden && HasVideo()) {
     nsRefPtr<power::PowerManagerService> pmService =
       power::PowerManagerService::GetInstance();
     NS_ENSURE_TRUE_VOID(pmService);
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2264,16 +2264,18 @@ nsGenericHTMLFormElement::PreHandleEvent
       }
       case NS_BLUR_CONTENT:
       {
         nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
         if (formControlFrame)
           formControlFrame->SetFocus(false, false);
         break;
       }
+      default:
+        break;
     }
   }
 
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
 
 /* virtual */
 bool
@@ -2449,18 +2451,18 @@ nsGenericHTMLFormElement::FormIdUpdated(
   NS_ASSERTION(element->IsHTMLElement(), "aData should be an HTML element");
 
   element->UpdateFormOwner(false, aNewElement);
 
   return true;
 }
 
 bool 
-nsGenericHTMLFormElement::IsElementDisabledForEvents(uint32_t aMessage, 
-                                                    nsIFrame* aFrame)
+nsGenericHTMLFormElement::IsElementDisabledForEvents(EventMessage aMessage,
+                                                     nsIFrame* aFrame)
 {
   bool disabled = IsDisabled();
   if (!disabled && aFrame) {
     const nsStyleUserInterface* uiStyle = aFrame->StyleUserInterface();
     disabled = uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
       uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED;
 
   }
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -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/. */
 #ifndef nsGenericHTMLElement_h___
 #define nsGenericHTMLElement_h___
 
 #include "mozilla/Attributes.h"
+#include "mozilla/EventForwards.h"
 #include "nsMappedAttributeElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsNameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozilla/ErrorResult.h"
 #include "nsIDOMHTMLMenuElement.h"
@@ -1403,17 +1404,18 @@ protected:
    * This method is a a callback for IDTargetObserver (from nsIDocument).
    * It will be called each time the element associated with the id in @form
    * changes.
    */
   static bool FormIdUpdated(Element* aOldElement, Element* aNewElement,
                               void* aData);
 
   // Returns true if the event should not be handled from PreHandleEvent
-  bool IsElementDisabledForEvents(uint32_t aMessage, nsIFrame* aFrame);
+  bool IsElementDisabledForEvents(mozilla::EventMessage aMessage,
+                                  nsIFrame* aFrame);
 
   // The focusability state of this form control.  eUnfocusable means that it
   // shouldn't be focused at all, eInactiveWindow means it's in an inactive
   // window, eActiveWindow means it's in an active window.
   enum FocusTristate {
     eUnfocusable,
     eInactiveWindow,
     eActiveWindow
--- a/dom/html/nsIFormControl.h
+++ b/dom/html/nsIFormControl.h
@@ -1,17 +1,19 @@
 /* -*- 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 nsIFormControl_h___
 #define nsIFormControl_h___
 
+#include "mozilla/EventForwards.h"
 #include "nsISupports.h"
+
 class nsIDOMHTMLFormElement;
 class nsPresState;
 class nsFormSubmission;
 
 namespace mozilla {
 namespace dom {
 class Element;
 class HTMLFieldSetElement;
@@ -190,17 +192,17 @@ public:
   inline bool IsSubmittableControl() const;
 
   /**
    * Returns whether this form control can have draggable children.
    * @return whether this form control can have draggable children.
    */
   inline bool AllowDraggableChildren() const;
 
-  virtual bool IsDisabledForEvents(uint32_t aMessage)
+  virtual bool IsDisabledForEvents(mozilla::EventMessage aMessage)
   {
     return false;
   }
 protected:
 
   /**
    * Returns whether mType corresponds to a single line text control type.
    * @param aExcludePassword to have NS_FORM_INPUT_PASSWORD ignored.
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -849,17 +849,17 @@ DOMError*
 IDBTransaction::GetError() const
 {
   AssertIsOnOwningThread();
 
   return mError;
 }
 
 already_AddRefed<DOMStringList>
-IDBTransaction::ObjectStoreNames()
+IDBTransaction::ObjectStoreNames() const
 {
   AssertIsOnOwningThread();
 
   if (mMode == IDBTransaction::VERSION_CHANGE) {
     return mDatabase->ObjectStoreNames();
   }
 
   nsRefPtr<DOMStringList> list = new DOMStringList();
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -276,17 +276,17 @@ public:
   void
   Abort(ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(abort)
   IMPL_EVENT_HANDLER(complete)
   IMPL_EVENT_HANDLER(error)
 
   already_AddRefed<DOMStringList>
-  ObjectStoreNames();
+  ObjectStoreNames() const;
 
   void
   FireCompleteOrAbortEvents(nsresult aResult);
 
   // Only for VERSION_CHANGE transactions.
   int64_t
   NextObjectStoreId();
 
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1086,18 +1086,16 @@ interface nsIDOMWindowUtils : nsISupport
   nsIQueryContentEventResult sendQueryContentEvent(
                                in unsigned long aType,
                                in unsigned long aOffset,
                                in unsigned long aLength,
                                in long aX,
                                in long aY,
                                [optional] in unsigned long aAdditionalFlags);
 
-  // NOTE: following values are same as NS_QUERY_* in BasicEvents.h
-
   /**
    * QUERY_SELECTED_TEXT queries the first selection range's information.
    *
    * @param aOffset   Not used.
    * @param aLength   Not used.
    * @param aX        Not used.
    * @param aY        Not used.
    *
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -60,16 +60,17 @@ using mozilla::CSSToScreenScale from "Un
 using mozilla::CommandInt from "mozilla/EventForwards.h";
 using mozilla::Modifiers from "mozilla/EventForwards.h";
 using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
 using mozilla::WritingMode from "mozilla/WritingModes.h";
 using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
 using nsIWidget::TouchPointerState from "nsIWidget.h";
 using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
 using struct mozilla::OwningSerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h";
+using mozilla::EventMessage from "mozilla/EventForwards.h";
 using nsEventStatus from "mozilla/EventForwards.h";
 
 namespace mozilla {
 namespace dom {
 
 struct NativeKeyBinding
 {
   CommandInt[] singleLineCommands;
@@ -271,17 +272,17 @@ parent:
 
     /**
      * OnEventNeedingAckHandled() is called after a child process dispatches a
      * composition event or a selection event which is sent from the parent
      * process.
      *
      * message      The message value of the handled event.
      */
-    prio(urgent) async OnEventNeedingAckHandled(uint32_t message);
+    prio(urgent) async OnEventNeedingAckHandled(EventMessage message);
 
     /**
      * Tells chrome to start plugin IME.  If this results in a string getting
      * committed, the result is in aCommitted (otherwise aCommitted is empty).
      *
      * aKeyboardEvent     The event with which plugin IME is to be started
      * panelX and panelY  Location in screen coordinates of the IME input panel
      *                    (should be just under the plugin)
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2105,17 +2105,17 @@ TabParent::RecvNotifyIMEPositionChange(c
     widget->GetIMEUpdatePreference();
   if (updatePreference.WantPositionChanged()) {
     mContentCache.MaybeNotifyIME(widget, aIMENotification);
   }
   return true;
 }
 
 bool
-TabParent::RecvOnEventNeedingAckHandled(const uint32_t& aMessage)
+TabParent::RecvOnEventNeedingAckHandled(const EventMessage& aMessage)
 {
   // This is called when the child process receives WidgetCompositionEvent or
   // WidgetSelectionEvent.
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return true;
   }
 
@@ -2886,18 +2886,18 @@ TabParent::InjectTouchEvent(const nsAStr
                             int32_t* aYs,
                             uint32_t* aRxs,
                             uint32_t* aRys,
                             float* aRotationAngles,
                             float* aForces,
                             uint32_t aCount,
                             int32_t aModifiers)
 {
-  uint32_t msg;
-  nsContentUtils::GetEventIdAndAtom(aType, eTouchEventClass, &msg);
+  EventMessage msg;
+  nsContentUtils::GetEventMessageAndAtom(aType, eTouchEventClass, &msg);
   if (msg != NS_TOUCH_START && msg != NS_TOUCH_MOVE &&
       msg != NS_TOUCH_END && msg != NS_TOUCH_CANCEL) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return NS_ERROR_FAILURE;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -174,17 +174,17 @@ public:
                                                 const widget::IMENotification& aEventMessage) override;
     virtual bool RecvNotifyIMESelection(const ContentCache& aContentCache,
                                         const widget::IMENotification& aEventMessage) override;
     virtual bool RecvUpdateContentCache(const ContentCache& aContentCache) override;
     virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
                                                bool* aConsumedByIME) override;
     virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
                                              const widget::IMENotification& aEventMessage) override;
-    virtual bool RecvOnEventNeedingAckHandled(const uint32_t& aMessage) override;
+    virtual bool RecvOnEventNeedingAckHandled(const EventMessage& aMessage) override;
     virtual bool RecvEndIMEComposition(const bool& aCancel,
                                        bool* aNoCompositionEvent,
                                        nsString* aComposition) override;
     virtual bool RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
                                     const int32_t& aPanelX,
                                     const int32_t& aPanelY,
                                     nsString* aCommitted) override;
     virtual bool RecvSetPluginFocused(const bool& aFocused) override;
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -295,18 +295,17 @@ public:
   }
 
   NS_METHOD Run()
   {
     MOZ_ASSERT(mReader->OnTaskQueue());
 
     // Make sure ResetDecode hasn't been called in the mean time.
     if (!mReader->mBaseVideoPromise.IsEmpty()) {
-      mReader->RequestVideoData(/* aSkip = */ true, mTimeThreshold,
-                                /* aForceDecodeAhead = */ false);
+      mReader->RequestVideoData(/* aSkip = */ true, mTimeThreshold);
     }
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<MediaDecoderReader> mReader;
   const int64_t mTimeThreshold;
@@ -333,18 +332,17 @@ public:
   }
 
 private:
   nsRefPtr<MediaDecoderReader> mReader;
 };
 
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
 MediaDecoderReader::RequestVideoData(bool aSkipToNextKeyframe,
-                                     int64_t aTimeThreshold,
-                                     bool aForceDecodeAhead)
+                                     int64_t aTimeThreshold)
 {
   nsRefPtr<VideoDataPromise> p = mBaseVideoPromise.Ensure(__func__);
   bool skip = aSkipToNextKeyframe;
   while (VideoQueue().GetSize() == 0 &&
          !VideoQueue().IsFinished()) {
     if (!DecodeVideoFrame(skip, aTimeThreshold)) {
       VideoQueue().Finish();
     } else if (skip) {
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -143,17 +143,17 @@ public:
 
   // Requests one video sample from the reader.
   //
   // Don't hold the decoder monitor while calling this, as the implementation
   // may try to wait on something that needs the monitor and deadlock.
   // If aSkipToKeyframe is true, the decode should skip ahead to the
   // the next keyframe at or after aTimeThreshold microseconds.
   virtual nsRefPtr<VideoDataPromise>
-  RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold, bool aForceDecodeAhead);
+  RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold);
 
   friend class ReRequestVideoWithSkipTask;
   friend class ReRequestAudioTask;
 
   // By default, the state machine polls the reader once per second when it's
   // in buffering mode. Some readers support a promise-based mechanism by which
   // they notify the state machine when the data arrives.
   virtual bool IsWaitForDataSupported() { return false; }
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -166,17 +166,16 @@ static TimeDuration UsecsToDuration(int6
 }
 
 static int64_t DurationToUsecs(TimeDuration aDuration) {
   return static_cast<int64_t>(aDuration.ToSeconds() * USECS_PER_S);
 }
 
 static const uint32_t MIN_VIDEO_QUEUE_SIZE = 3;
 static const uint32_t MAX_VIDEO_QUEUE_SIZE = 10;
-static const uint32_t SCARCE_VIDEO_QUEUE_SIZE = 1;
 static const uint32_t VIDEO_QUEUE_SEND_TO_COMPOSITOR_SIZE = 9999;
 
 static uint32_t sVideoQueueDefaultSize = MAX_VIDEO_QUEUE_SIZE;
 static uint32_t sVideoQueueHWAccelSize = MIN_VIDEO_QUEUE_SIZE;
 static uint32_t sVideoQueueSendToCompositorSize = VIDEO_QUEUE_SEND_TO_COMPOSITOR_SIZE;
 
 MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
                                                    MediaDecoderReader* aReader,
@@ -1705,36 +1704,34 @@ MediaDecoderStateMachine::RequestVideoDa
   // Time the video decode, so that if it's slow, we can increase our low
   // audio threshold to reduce the chance of an audio underrun while we're
   // waiting for a video decode to complete.
   mVideoDecodeStartTime = TimeStamp::Now();
 
   bool skipToNextKeyFrame = mSentFirstFrameLoadedEvent &&
     NeedToSkipToNextKeyframe();
   int64_t currentTime = mState == DECODER_STATE_SEEKING ? 0 : GetMediaTime();
-  bool forceDecodeAhead = mSentFirstFrameLoadedEvent && !IsSeeking() &&
-    static_cast<uint32_t>(VideoQueue().GetSize()) <= SCARCE_VIDEO_QUEUE_SIZE;
 
   SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
              VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
              currentTime);
 
   if (mSentFirstFrameLoadedEvent) {
     mVideoDataRequest.Begin(
       InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
                   &MediaDecoderReader::RequestVideoData,
-                  skipToNextKeyFrame, currentTime, forceDecodeAhead)
+                  skipToNextKeyFrame, currentTime)
       ->Then(OwnerThread(), __func__, this,
              &MediaDecoderStateMachine::OnVideoDecoded,
              &MediaDecoderStateMachine::OnVideoNotDecoded));
   } else {
     mVideoDataRequest.Begin(
       InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
                   &MediaDecoderReader::RequestVideoData,
-                  skipToNextKeyFrame, currentTime, forceDecodeAhead)
+                  skipToNextKeyFrame, currentTime)
       ->Then(OwnerThread(), __func__, mStartTimeRendezvous.get(),
              &StartTimeRendezvous::ProcessFirstSample<VideoDataPromise>,
              &StartTimeRendezvous::FirstSampleRejected<VideoData>)
       ->CompletionPromise()
       ->Then(OwnerThread(), __func__, this,
              &MediaDecoderStateMachine::OnVideoDecoded,
              &MediaDecoderStateMachine::OnVideoNotDecoded));
   }
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -305,27 +305,33 @@ MediaFormatReader::OnDemuxerInitDone(nsr
 
   // To decode, we need valid video and a place to put it.
   bool videoActive = !!mDemuxer->GetNumberTracks(TrackInfo::kVideoTrack) &&
     mDecoder->GetImageContainer();
 
   if (videoActive) {
     // We currently only handle the first video track.
     mVideo.mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
-    MOZ_ASSERT(mVideo.mTrackDemuxer);
+    if (!mVideo.mTrackDemuxer) {
+      mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
+      return;
+    }
     mInfo.mVideo = *mVideo.mTrackDemuxer->GetInfo()->GetAsVideoInfo();
     mVideo.mCallback = new DecoderCallback(this, TrackInfo::kVideoTrack);
     mVideo.mTimeRanges = mVideo.mTrackDemuxer->GetBuffered();
     mTrackDemuxersMayBlock |= mVideo.mTrackDemuxer->GetSamplesMayBlock();
   }
 
   bool audioActive = !!mDemuxer->GetNumberTracks(TrackInfo::kAudioTrack);
   if (audioActive) {
     mAudio.mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
-    MOZ_ASSERT(mAudio.mTrackDemuxer);
+    if (!mAudio.mTrackDemuxer) {
+      mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
+      return;
+    }
     mInfo.mAudio = *mAudio.mTrackDemuxer->GetInfo()->GetAsAudioInfo();
     mAudio.mCallback = new DecoderCallback(this, TrackInfo::kAudioTrack);
     mAudio.mTimeRanges = mAudio.mTrackDemuxer->GetBuffered();
     mTrackDemuxersMayBlock |= mAudio.mTrackDemuxer->GetSamplesMayBlock();
   }
 
   UniquePtr<EncryptionInfo> crypto = mDemuxer->GetCrypto();
 
@@ -366,22 +372,28 @@ MediaFormatReader::OnDemuxerInitDone(nsr
 
   if (!videoActive && !audioActive) {
     mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
     return;
   }
   if (videoActive) {
     mVideoTrackDemuxer =
       mMainThreadDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
-    MOZ_ASSERT(mVideoTrackDemuxer);
+    if (!mVideoTrackDemuxer) {
+      mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
+      return;
+    }
   }
   if (audioActive) {
     mAudioTrackDemuxer =
       mMainThreadDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
-    MOZ_ASSERT(mAudioTrackDemuxer);
+    if (!mAudioTrackDemuxer) {
+      mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
+      return;
+    }
   }
 
   if (IsWaitingOnCDMResource()) {
     // Decoder can't be allocated before CDM resource is ready, so resolving the
     // mMetadataPromise here to wait for CDM on MDSM.
     mInitDone = true;
     nsRefPtr<MetadataHolder> metadata = new MetadataHolder();
     metadata->mInfo = mInfo;
@@ -620,18 +632,17 @@ MediaFormatReader::ShouldSkip(bool aSkip
   if (NS_FAILED(rv)) {
     return aSkipToNextKeyframe;
   }
   return nextKeyframe < aTimeThreshold && nextKeyframe.ToMicroseconds() >= 0;
 }
 
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
 MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
-                                    int64_t aTimeThreshold,
-                                    bool aForceDecodeAhead)
+                                     int64_t aTimeThreshold)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty(), "No sample requests allowed while seeking");
   MOZ_DIAGNOSTIC_ASSERT(!mVideo.HasPromise(), "No duplicate sample requests");
   MOZ_DIAGNOSTIC_ASSERT(!mVideo.mSeekRequest.Exists() ||
                         mVideo.mTimeThreshold.isSome());
   MOZ_DIAGNOSTIC_ASSERT(!mSkipRequest.Exists(), "called mid-skipping");
   MOZ_DIAGNOSTIC_ASSERT(!IsSeeking(), "called mid-seek");
@@ -647,27 +658,28 @@ MediaFormatReader::RequestVideoData(bool
     return VideoDataPromise::CreateAndReject(CANCELED, __func__);
   }
 
   if (mShutdown) {
     NS_WARNING("RequestVideoData on shutdown MediaFormatReader!");
     return VideoDataPromise::CreateAndReject(CANCELED, __func__);
   }
 
-  mVideo.mForceDecodeAhead = aForceDecodeAhead;
   media::TimeUnit timeThreshold{media::TimeUnit::FromMicroseconds(aTimeThreshold)};
   if (ShouldSkip(aSkipToNextKeyframe, timeThreshold)) {
+    mVideo.mDecodingRequested = false;
     Flush(TrackInfo::kVideoTrack);
     nsRefPtr<VideoDataPromise> p = mVideo.mPromise.Ensure(__func__);
     SkipVideoDemuxToNextKeyFrame(timeThreshold);
     return p;
   }
 
   nsRefPtr<VideoDataPromise> p = mVideo.mPromise.Ensure(__func__);
-  ScheduleUpdate(TrackInfo::kVideoTrack);
+  NotifyDecodingRequested(TrackInfo::kVideoTrack);
+
   return p;
 }
 
 void
 MediaFormatReader::OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure)
 {
   MOZ_ASSERT(OnTaskQueue());
   LOG("Failed to demux %s, failure:%d",
@@ -739,17 +751,17 @@ MediaFormatReader::RequestAudioData()
   }
 
   if (mShutdown) {
     NS_WARNING("RequestAudioData on shutdown MediaFormatReader!");
     return AudioDataPromise::CreateAndReject(CANCELED, __func__);
   }
 
   nsRefPtr<AudioDataPromise> p = mAudio.mPromise.Ensure(__func__);
-  ScheduleUpdate(TrackType::kAudioTrack);
+  NotifyDecodingRequested(TrackInfo::kAudioTrack);
 
   return p;
 }
 
 void
 MediaFormatReader::DoDemuxAudio()
 {
   // TODO Use DecodeAhead value rather than 1.
@@ -835,35 +847,43 @@ MediaFormatReader::NotifyEndOfStream(Tra
 {
   MOZ_ASSERT(OnTaskQueue());
   auto& decoder = GetDecoderData(aTrack);
   decoder.mDemuxEOS = true;
   decoder.mNeedDraining = true;
   ScheduleUpdate(aTrack);
 }
 
+void
+MediaFormatReader::NotifyDecodingRequested(TrackType aTrack)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  auto& decoder = GetDecoderData(aTrack);
+  decoder.mDecodingRequested = true;
+  ScheduleUpdate(aTrack);
+}
+
 bool
 MediaFormatReader::NeedInput(DecoderData& aDecoder)
 {
   MOZ_ASSERT(OnTaskQueue());
   // We try to keep a few more compressed samples input than decoded samples
   // have been output, provided the state machine has requested we send it a
   // decoded sample. To account for H.264 streams which may require a longer
   // run of input than we input, decoders fire an "input exhausted" callback,
   // which overrides our "few more samples" threshold.
   return
     !aDecoder.mDraining &&
     !aDecoder.mError &&
-    (aDecoder.HasPromise() || aDecoder.mForceDecodeAhead) &&
+    aDecoder.mDecodingRequested &&
     !aDecoder.mDemuxRequest.Exists() &&
-    aDecoder.mOutput.IsEmpty() &&
+    aDecoder.mOutput.Length() <= aDecoder.mDecodeAhead &&
     (aDecoder.mInputExhausted || !aDecoder.mQueuedSamples.IsEmpty() ||
      aDecoder.mTimeThreshold.isSome() ||
-     aDecoder.mForceDecodeAhead ||
-     aDecoder.mNumSamplesInput - aDecoder.mNumSamplesOutput < aDecoder.mDecodeAhead);
+     aDecoder.mNumSamplesInput - aDecoder.mNumSamplesOutput <= aDecoder.mDecodeAhead);
 }
 
 void
 MediaFormatReader::ScheduleUpdate(TrackType aTrack)
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mShutdown) {
     return;
@@ -1172,26 +1192,28 @@ MediaFormatReader::Update(TrackType aTra
   }
 
   if (decoder.mNeedDraining) {
     DrainDecoder(aTrack);
     return;
   }
 
   if (!NeedInput(decoder)) {
-    LOGV("No need for additional input");
+    LOGV("No need for additional input (pending:%u)",
+         uint32_t(decoder.mOutput.Length()));
     return;
   }
 
   needInput = true;
 
-  LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u sid:%u",
+  LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u pending:%u ahead:%d sid:%u",
        TrackTypeToStr(aTrack), needInput, needOutput, decoder.mInputExhausted,
        decoder.mNumSamplesInput, decoder.mNumSamplesOutput,
-       uint32_t(size_t(decoder.mSizeOfQueue)), decoder.mLastStreamSourceID);
+       uint32_t(size_t(decoder.mSizeOfQueue)), uint32_t(decoder.mOutput.Length()),
+       !decoder.HasPromise(), decoder.mLastStreamSourceID);
 
   // Demux samples if we don't have some.
   RequestDemuxSamples(aTrack);
   // Decode all pending demuxed samples.
   DecodeDemuxedSamples(aTrack, a);
 }
 
 void
@@ -1360,16 +1382,17 @@ MediaFormatReader::Flush(TrackType aTrac
 
 void
 MediaFormatReader::SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold)
 {
   MOZ_ASSERT(OnTaskQueue());
 
   MOZ_ASSERT(mVideo.mDecoder);
   MOZ_ASSERT(mVideo.HasPromise());
+  MOZ_ASSERT(!mVideo.mDecodingRequested);
   LOG("Skipping up to %lld", aTimeThreshold.ToMicroseconds());
 
   if (mVideo.mError) {
     mVideo.RejectPromise(DECODE_ERROR, __func__);
     return;
   }
 
   mSkipRequest.Begin(mVideo.mTrackDemuxer->SkipToNextRandomAccessPoint(aTimeThreshold)
@@ -1383,42 +1406,42 @@ void
 MediaFormatReader::OnVideoSkipCompleted(uint32_t aSkipped)
 {
   MOZ_ASSERT(OnTaskQueue());
   LOG("Skipping succeeded, skipped %u frames", aSkipped);
   mSkipRequest.Complete();
   mDecoder->NotifyDecodedFrames(aSkipped, 0, aSkipped);
   MOZ_ASSERT(!mVideo.mError); // We have flushed the decoder, no frame could
                               // have been decoded (and as such errored)
-  ScheduleUpdate(TrackInfo::kVideoTrack);
+  NotifyDecodingRequested(TrackInfo::kVideoTrack);
 }
 
 void
 MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailure)
 {
   MOZ_ASSERT(OnTaskQueue());
   LOG("Skipping failed, skipped %u frames", aFailure.mSkipped);
   mSkipRequest.Complete();
   mDecoder->NotifyDecodedFrames(aFailure.mSkipped, 0, aFailure.mSkipped);
   MOZ_ASSERT(mVideo.HasPromise());
   switch (aFailure.mFailure) {
     case DemuxerFailureReason::END_OF_STREAM:
       NotifyEndOfStream(TrackType::kVideoTrack);
-      mVideo.RejectPromise(END_OF_STREAM, __func__);
       break;
     case DemuxerFailureReason::WAITING_FOR_DATA:
       NotifyWaitingForData(TrackType::kVideoTrack);
-      mVideo.RejectPromise(WAITING_FOR_DATA, __func__);
       break;
     case DemuxerFailureReason::CANCELED:
     case DemuxerFailureReason::SHUTDOWN:
+      if (mVideo.HasPromise()) {
+        mVideo.RejectPromise(CANCELED, __func__);
+      }
       break;
     default:
       NotifyError(TrackType::kVideoTrack);
-      mVideo.RejectPromise(DECODE_ERROR, __func__);
       break;
   }
 }
 
 nsRefPtr<MediaDecoderReader::SeekPromise>
 MediaFormatReader::Seek(int64_t aTime, int64_t aUnused)
 {
   MOZ_ASSERT(OnTaskQueue());
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -30,28 +30,28 @@ public:
   virtual ~MediaFormatReader();
 
   nsresult Init(MediaDecoderReader* aCloneDonor) override;
 
   size_t SizeOfVideoQueueInFrames() override;
   size_t SizeOfAudioQueueInFrames() override;
 
   nsRefPtr<VideoDataPromise>
-  RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold, bool aForceDecodeAhead) override;
+  RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold) override;
 
   nsRefPtr<AudioDataPromise> RequestAudioData() override;
 
   bool HasVideo() override
   {
-    return mInfo.HasVideo();
+    return mVideo.mTrackDemuxer;
   }
 
   bool HasAudio() override
   {
-    return mInfo.HasAudio();
+    return mAudio.mTrackDemuxer;
   }
 
   nsRefPtr<MetadataPromise> AsyncReadMetadata() override;
 
   void ReadUpdatedMetadata(MediaInfo* aInfo) override;
 
   nsRefPtr<SeekPromise>
   Seek(int64_t aTime, int64_t aUnused) override;
@@ -125,16 +125,17 @@ private:
   // Drain the current decoder.
   void DrainDecoder(TrackType aTrack);
   void NotifyNewOutput(TrackType aTrack, MediaData* aSample);
   void NotifyInputExhausted(TrackType aTrack);
   void NotifyDrainComplete(TrackType aTrack);
   void NotifyError(TrackType aTrack);
   void NotifyWaitingForData(TrackType aTrack);
   void NotifyEndOfStream(TrackType aTrack);
+  void NotifyDecodingRequested(TrackType aTrack);
 
   void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
 
   // Initializes mLayersBackendType if possible.
   void InitLayersBackendType();
 
   // DecoderCallback proxies the MediaDataDecoderCallback calls to these
   // functions.
@@ -186,23 +187,23 @@ private:
 
   struct DecoderData {
     DecoderData(MediaFormatReader* aOwner,
                 MediaData::Type aType,
                 uint32_t aDecodeAhead)
       : mOwner(aOwner)
       , mType(aType)
       , mDecodeAhead(aDecodeAhead)
-      , mForceDecodeAhead(false)
       , mUpdateScheduled(false)
       , mDemuxEOS(false)
       , mWaitingForData(false)
       , mReceivedNewData(false)
       , mDiscontinuity(true)
       , mDecoderInitialized(false)
+      , mDecodingRequested(false)
       , mOutputRequested(false)
       , mInputExhausted(false)
       , mError(false)
       , mNeedDraining(false)
       , mDraining(false)
       , mDrainComplete(false)
       , mNumSamplesInput(0)
       , mNumSamplesOutput(0)
@@ -221,17 +222,16 @@ private:
     // TaskQueue on which decoder can choose to decode.
     // Only non-null up until the decoder is created.
     nsRefPtr<FlushableTaskQueue> mTaskQueue;
     // Callback that receives output and error notifications from the decoder.
     nsAutoPtr<DecoderCallback> mCallback;
 
     // Only accessed from reader's task queue.
     uint32_t mDecodeAhead;
-    bool mForceDecodeAhead;
     bool mUpdateScheduled;
     bool mDemuxEOS;
     bool mWaitingForData;
     bool mReceivedNewData;
     bool mDiscontinuity;
 
     // Pending seek.
     MozPromiseRequestHolder<MediaTrackDemuxer::SeekPromise> mSeekRequest;
@@ -244,16 +244,17 @@ private:
     {
       MOZ_ASSERT(mOwner->OnTaskQueue());
       return !mWaitingPromise.IsEmpty();
     }
 
     // MediaDataDecoder handler's variables.
     // False when decoder is created. True when decoder Init() promise is resolved.
     bool mDecoderInitialized;
+    bool mDecodingRequested;
     bool mOutputRequested;
     bool mInputExhausted;
     bool mError;
     bool mNeedDraining;
     bool mDraining;
     bool mDrainComplete;
     // If set, all decoded samples prior mTimeThreshold will be dropped.
     // Used for internal seeking when a change of stream is detected.
@@ -263,31 +264,31 @@ private:
     // state machine upon request.
     nsTArray<nsRefPtr<MediaData>> mOutput;
     uint64_t mNumSamplesInput;
     uint64_t mNumSamplesOutput;
     uint64_t mNumSamplesOutputTotal;
 
     // These get overriden in the templated concrete class.
     // Indicate if we have a pending promise for decoded frame.
+    // Rejecting the promise will stop the reader from decoding ahead.
     virtual bool HasPromise() = 0;
     virtual void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
                                const char* aMethodName) = 0;
 
     void ResetDemuxer()
     {
       // Clear demuxer related data.
       mDemuxRequest.DisconnectIfExists();
       mTrackDemuxer->Reset();
     }
 
     void ResetState()
     {
       MOZ_ASSERT(mOwner->OnTaskQueue());
-      mForceDecodeAhead = false;
       mDemuxEOS = false;
       mWaitingForData = false;
       mReceivedNewData = false;
       mDiscontinuity = true;
       mQueuedSamples.Clear();
       mOutputRequested = false;
       mInputExhausted = false;
       mNeedDraining = false;
@@ -329,16 +330,17 @@ private:
       return !mPromise.IsEmpty();
     }
 
     void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
                        const char* aMethodName) override
     {
       MOZ_ASSERT(mOwner->OnTaskQueue());
       mPromise.Reject(aReason, aMethodName);
+      mDecodingRequested = false;
     }
   };
 
   DecoderDataWithPromise<AudioDataPromise> mAudio;
   DecoderDataWithPromise<VideoDataPromise> mVideo;
 
   // Returns true when the decoder for this track needs input.
   bool NeedInput(DecoderData& aDecoder);
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -674,17 +674,17 @@ RTCPeerConnection.prototype = {
     // This entry-point handles both new and legacy call sig. Decipher which one
     let onSuccess;
     if (typeof optionsOrOnSuccess == "function") {
       onSuccess = optionsOrOnSuccess;
     } else {
       options = optionsOrOnSuccess;
     }
     return this._legacyCatch(onSuccess, onError, () => {
-      // TODO: Remove old constraint-like RTCOptions support soon (Bug 1064223).
+      // TODO: Remove error on constraint-like RTCOptions next cycle (1197021).
       // Note that webidl bindings make o.mandatory implicit but not o.optional.
       function convertLegacyOptions(o) {
         // Detect (mandatory OR optional) AND no other top-level members.
         let lcy = ((o.mandatory && Object.keys(o.mandatory).length) || o.optional) &&
             Object.keys(o).length == (o.mandatory? 1 : 0) + (o.optional? 1 : 0);
         if (!lcy) {
           return false;
         }
@@ -711,20 +711,21 @@ RTCPeerConnection.prototype = {
           if (o[k] === undefined) {
             delete o[k];
           }
         });
         return true;
       }
 
       if (options && convertLegacyOptions(options)) {
-        this.logWarning(
-          "Mandatory/optional in createOffer options is deprecated! Use " +
+        this.logError(
+          "Mandatory/optional in createOffer options no longer works! Use " +
             JSON.stringify(options) + " instead (note the case difference)!",
           null, 0);
+        options = {};
       }
 
       let origin = Cu.getWebIDLCallerPrincipal().origin;
       return this._chain(() => {
         let p = Promise.all([this.getPermission(), this._certificateReady])
           .then(() => new this._win.Promise((resolve, reject) => {
             this._onCreateOfferSuccess = resolve;
             this._onCreateOfferFailure = reject;
--- a/dom/media/gtest/TestMP4Demuxer.cpp
+++ b/dom/media/gtest/TestMP4Demuxer.cpp
@@ -421,8 +421,18 @@ TEST(MP4Demuxer, GetNextKeyframe)
         binding->mVideoTrack->GetNextRandomAccessPoint(&time);
         EXPECT_EQ(time.ToMicroseconds(), 1000000);
         binding->mTaskQueue->BeginShutdown();
       },
       DO_FAIL
     );
   });
 }
+
+TEST(MP4Demuxer, ZeroInMoov)
+{
+  nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding("short-zero-in-moov.mp4");
+  binding->RunTestAndWait([binding] () {
+    // It demuxes without error. That is sufficient.
+    binding->mTaskQueue->BeginShutdown();
+  });
+}
+
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -40,16 +40,17 @@ if CONFIG['MOZ_RUST']:
 
 TEST_HARNESS_FILES.gtest += [
     '../test/gizmo-frag.mp4',
     '../test/gizmo.mp4',
     'dash_dashinit.mp4',
     'mediasource_test.mp4',
     'noise.mp3',
     'noise_vbr.mp3',
+    'short-zero-in-moov.mp4',
     'test.webm',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/dom/media',
     '/dom/media/eme',
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..577318c8fa8aaf3bc8541844c07d3a5092ea489c
GIT binary patch
literal 13655
zc%1E92UJtb);^&tAiathqzFh!sL}*Pnt*`P6(J1>1QL?adly6yse&R(2c?LpAk6}Z
zD2g;ex}XS1^&%?eKjC`sMc;e>dTV*t`u}y8JDD?kX7=7Qd(U@fGA9WD08l5g9|23k
zy8{3fK*_-*hww(h-3bbC000=Ah!_k2$b4}}BgmjkIUVihX6c~r`}(*226xh=UP1eX
z=jMIoloX)SP!yhsfx_h#p+q@(1x2V63<XCi%7YCCGN6F0iJ7jxv;tJyN(YogV^Cm&
z4xZqL!#I(laxj>@v>Xghk#-@I397QPK0ZD&-dHpSk3)FK;EB$%lwM?9$nH2$22UVk
z@g5{qC<=i@pfuo6BF0HW9*V{wad?!Q23!@U3WFj%5I8>)Mg!(6uL|>pgT~!48ZH=L
zD9H;6a>`Hw$q!TouMR}C23!UPDuEZMJJuJ2cA!{<gBlJ*goiUm1Fi%`xe)R02nSFV
z4kZ&YI2@J)atD16qETd!L3z4sz`!9O(EfN2jD{Rs3J!-lAxLBg0?7?aph)~~z?0yB
zcXA?O$QsgeP_hdV)Bp|1L2-Dz8^Q%FIs91(CE>6r%wH8Ss0VSY6BO1RL8c4@>p{j4
zaR^WdtViO!hzLIi6yBYHAcJKT7$Y(ff%O1QfPzE>MaGGUaL16qXdxX4ejtxUYsi5-
z0*xS0+(0@Yu?R{}Xe<%4<(Ll!>+C{Cf*hWJ@o;d)6TsHrD+!>g8^#Z`ts$of`^GxB
zV?8wF6rdy&#sh=$B5NqXpj*9DVoJo2TtIaq%HdCUDeXj*28!qebw`4MrMLwaH00!E
zU{FtrGa4`%C6Fah3~%KKUkxP{kRg#V1Pui!mH^HYhzM{JL0bq<5CD|v1VRA-5`{Sv
z2`F!Fj8U(0cJA?uzuRt}HqX_bbca3NxPSRPZ=yY|CygT@nlizBImhqhnL`js0ALRt
zvVpOFcvE=4`5;~AXPBU`hiGOB_LW7~^R}4OVu++e`VoYZ#ZLcKC25<QDx<adOst~*
z4g84!^+#92sS7us_2<?+u_v5pJ#6hWo22tH(<yGsID4`3E<!&B!#MAG<W_It(0P7@
zBm_f@&03xrdXKrveyrM&zQ8=fCD}%0QN1nzZM#Dth~9z4I0KfVdvKi*RbVVH6Zf?!
zIo^rb++J6c7eZ}*L;J~K{Avd0=Dht{VirVTwd^3ii0j31X4UYi!KEFSb{vSiO4wL8
zuuPd6i=h@QrG|3rO^h>(PC58me1QvKE)RE-18Do^8w#E0`7S4LF;>rTov{5XeVxuQ
zcwt3zqkED{x=FCQ%LQ7u=!ZGNk=0uJfOn`z*Z-N=lp*RCQ-0v2cnv*Yhg{};qi_SP
z(Z|m0tc`^D3r0rc1tuHZQ|B)xPt^Ncn}cgdhjykAPA6oeFcR=SQ%k=i1mLl3ie$?@
zwLjy$mhMg}`gQ%71m#L<T=QqWC7YokN4^2x=p45UR2uK?+Dd9iWCA^PiW(2k$>6UI
zy7#E_ScQk1{fC5yZ+uL#c!rvtl=^fxzoU0vyk;lfK0w*{81u=Iyr$)W$1)k-%Cd8>
z)|Fi*nq<r)g3cHk3-Dy^<dlsn{1`U|QQRZwXw_pi_C7>3aw-&hrbwTUVLjawppwAn
zEJ%JG&#+-Tm5MRC`arCi=+K^bVED{tBOuSl(txfqUJYJk;p&VvviKnI@-TL!?6vO5
z&68EDCb{-5`?$EyWi0qjFHJnxzffis=cKpl{t~}eW{5ha$NY3}>?dsvwa1aCh51x8
z&x%X3UE<Rj9@SEtp@$@%({tG6mL9U<e@pMJNa|YDlBimaB5aRCONPNkg%5Wx4UFve
zYPTe_Um1K}r&LjqmCkSC>cFJES2go2hh}kjo{|}Uw~8dsNp3D1Gh7K*lsA3xDPKmp
z^&083$4YLz%J%zOUV-O$`2e7a_u{&i<-~lI89$kPzg{x5Rh+l|#8K{3E4jOFie+hu
z59XWqm(44A%jl4A8lH3eZSHg;?l~$b?~vkekIgC^br0yPI(<+iF2^MXc1M(-e|_T4
ztcGtXyyiyl<EL}N<pr&m$SS0$guvt|20O>LR{hf4@iQ0b8Msl;Hb<V@T{Aq`c0n?g
z-Cj6<X0oiZav;b~iFCoPR4Y!};_+#7wsY6r%O$0(RM`jDq_Z$W*c+dT=UyJ-X*U@5
z^IpCPPp+U+cqUz2Lib1t%adeedL?KMm(Woya_PZX;Dbh-S(|=cXZfnRpM(5cejj_{
z(aX}@j$QX8{FXD9C&H5J_s)#%7|utvcS(PycOE>Pn~`ZLNdNLFNjaK{BM1TY#7ChX
zA-t1k+hc%ZHker*r9CV7oTLmYi3%i2q3g83xR3x7Kp`4xN0_3rtZ2_fG3Qy1B0$h9
zc!YyjlMg8@8F+dhi)tgzpVeN|SwFm%TqT#i$-j18Mad)WkQv=IH*b?m`K+!`trH^|
z&HWDJpD}7$3<FogifjC2%0&(GY$Pr_+<DZ((qePw$rYY65gp~P1tWP(`#VR=E=xTv
zY;0*fu*)PXKQRSTlsS~_EOCVY3@hiSw{UOk)dt&RuNOjre-<4SlKK{M#V7Iism#Kq
z%hJ<Q_oeF`d}kI!D(KBS>%6!^mv~$CFgzBio-Xv1BbZO1YjrxKhqmeobBt(PM`KL$
zhEBozI~MyU79Q8J^At)p70~Nk6S}sB$Bz$$tuZ<9c)XJD`?ScCGaVRks&1egIs4&t
z+wgRnQX;_^{lQZ_+4tSL+O!(dJtq<J($><_QfulOlRV)oI{P#4Rh_vQ$Bt#DT}Q`^
z>U-68lbqV6VB=Z}_Z0cUX|B>3<xl1t<iF@p>E2nf+qCb)WxUI}Zd!e7u*|#ow)wQd
zdH*M>V{@x#^v@<=4q-XF7Gu)oQKZ{8mgFlUd(1M-cvs939o^O8k>+aZRo(`fp$g~n
z`SHEl-K#4#e$_?I{jcvN*Y`-d3yx;A4UC(MEk6I^)9wA}wYDI2-p!JdlCaJryiQ{)
zZ5m7P!!bj<?q7b(E0FpiJ>a^x(%WZgHi&t;e;4ynaN%~+&eT;GN|uNOcTsThZut5j
zev@|6CY1Jh!W;94uGWKqt&`vGun)0>oBrCi3FWc<5}&Et`}@ioPzlmD*2b~tJW7yU
zN<#uer-s+Ax>bmjy6H`Slo=O0+48!U?PI!a%<=KN%&IkysSX)=l{LQ~l<eU3$*63;
zt*3Hg|2^_#m|Qy5;u7D<w`M|bDr6kKUPL(>s!P;X+;WB9udeH^Pnawpc1D>_SxyXh
ze;vw#IuO-;q>X6u&;o)zeGD%pr1h7u3!7aVwb)%fJD2Al-HRznpPKfnz;n(f8Zz8j
z_Ucqz&SO?tLwj?ix(I~j$!gPHS$ccdu8KJWxTo`Q>7!}R+0N5#4^lP5Xyi}z@+M3l
z4v2QUfAe$jTT3JOvuB1Hx6FJeT8d>evclg!2`PEwpY1GkG21-4r#*;FkEZWjG#Qop
z?VUiz89Rl#DcdWKFc%f%Waciq9F{WPXY{O}6m~Wj%=HlPtkK%R@<&>x6A7!kJ~QmC
ztV-RX*%NpLXY6n{vL8s26~iUvOD{mRnl25+d}L$L>|G8YlU4T+SHt)f^Oo6v4(^}5
zq4NUJs*~#pXMec=UU37SePNV!ynOVqa&7pMMN`v<ZlX)2Oy2z24>#`i+wT^cVU|&H
z<vR|$$U$mLg!9;{=y%sk)MWI_$Mhpg?F)2Px|Bt4Ts+X%`?e+z?IrNrU1i0Ufe1Cb
zYDbUZ^bX!DLGgq({kDbkkieTuEvJ_vpO&Sj_~;s&HM8wqtBohQcz$xLyJVEsvVn->
zNu8jU|AN<f$9=(MkDF}VZA-+5;uI);BeV7D`2JgseL}}@3y@GcfEPG2Sj0ahCiLts
z0(`f__=j%3ohxy>Z9!Ahcv5I4L@#OduAJ2vn<Ea<30;_b-C3PwX~oY?dChU#G7OC-
zK1>v3?;#%!kyF!V^-W2?xHfwDY>0;u!@XM*{kv|_gF76oKBj3&A-o|frQ0!5Q01s?
zw4|WN2$NdT0fzUt9vwP^i#1;?=K8{!9sXYS+Qp~zT=J5`XI<h>K5Cat)qirTxyF}U
z<!kLck6Z1Uw6o)ll6|<*>hOj9YK3IB7k(Bo*EG!Z7&UvEZ*vJ0+3AYj=il{AtLgen
zq(FETlM1bw3hm9F6LLA%w8w_-<hm)9Tvw0+U($n84N^6;hya$b2`p_8qeRht26bXe
z6_bVfPy?@znbpzUNg3o|9izbdkk8rbp<wQ+3acJAC4$|3-{S+Bh7I&cl*sIh+<h~?
zP5;$`N-q@15V*CV4pkhou;>L;Py*Hl<F&e#G4>}6cw*UB>nnvT3iQawVRpLu`?OIn
zg3_IyOQ(qz$`{AFV4py_qxVYo04@6QD}wT`5Xy5A2)oB!;%|<Ik8J!sOa4EDAVq(&
z)S=*|Svwo$dg8$*K;E~LBdW_)3@+H(`*J0=;?@KCE0@YvvX;aLi3$a=-bXnxS|r(`
z52#92;y&i)$2^EGF`UkhvgPqYE}am=!NRA3T%r>!7?Hl|zMED#iXBu<H;d%5teJZj
z@c6u09cRw##U7Q4r#saY&j&OaH1T%rbd8RBCGXY#^fYZm;~w#}r>>z9zVJ-h^P?Gt
z%pak{(Tke!E0Eh<WfF{S1d@T|NtY!K83T6t_5z=in>jm~2gA#R461u)*_-zZ2{1TP
zT%u`WZ`pf1Fjh4Q>W9nz)F#p{P?5tC(+xoOY>xh)#QXm#?S88Da|RCn8S=+q$WJ7C
zI@6?H3ezk;Si%w)@ZvJHfzC9`L;U8?kMtiz!;U|t4ru}}y^!p1^5I6{ifCo)q5A$k
zI?ISpGcK3#%AX<u2vQBme1P2*QZ-|aKNn$-71tAoXp|jS5DuSheSc6!E~Nf?f@t$t
zMCoD;)0f2g157-P(_iP;=Z>4Vu)L6%npqo-FnnhxwVX(xVOp?EpvkH5W$if6vKA(`
z!ki~l9<=|eQPQrZN}U6TVEm@@cble0I-+J*MjiI>v8BwFc43xJz0i)}5RN;ZQ=*b^
zTPUet8PFD-cOlJNO!3HH_bNHUE4@f|Ilj3Mn$t}G#!mdX8kBpSEhOfv%J(<$dNW?+
za`}Gt#l06}tx}danlKDO+M~Y~^6dnvtNR)Ct;HV%Q=}^eOx87Lcf>Lq5bXfm4TiPa
zo6I-fbI%+SQfIR`@k*4MO4Je7`I>M$a$a-eaNdzM+k{2AXu?gM(1ybG_NIByV}<jz
z>6UV?LtpBGrHT~s{U?tSEH2d+mUtSkfA-(7Hn`B<NO;H)(0mL(K6wOTz#?<GxBk=-
zLIk$CK8~Mwp=@u$vHSN=hb4Iw?pYbGHP;@<47k^-7vRr-e@Tgt1DafLyasbJ#^pCt
z7o+o5K(rg$d&H>Ibt8UtmTfP4c9u1xX7$`xI-<H><hr2fj;r5;$(QEv1C`T}I^%^(
zLYMVV%aECcSc(o^@YxLg`APWa5MK7D)JMOMxj)}aUG3M8ztZQkjfywYEbu+pYZhSg
zYYW~^yPy7?{y}gJ2-D7tH7wG0xoFH_y}5Bvi_w(S(iG;o->ibF56E?W-MxQrmX^9A
zcR!P)b_JAZad*E3j!k)VMiJZ8Wu<gs@QvR1M9skSX=l=N&Vv>B^JBNudKe;y^Vf%}
zP5VOZ>sDFF2RWGf^bN2LRrmG;>bi$`PEs!)ASyR^7b$#j_mVPf@Sjd*Fq`)MQoF<5
z|MBr>W7c+_3j1^QMYsyNHgiNe!W!!uOLjG_9rLVk^eYu$ay=mU(W;L2<IqAwI^!q3
zaBJ*FD+GQi_o(`N5q|;Xd;Z(zTq#s#XheUp!1xQuxnT`@pDVCj!=b5<Fe}-P<G!5?
zGIh0Fsl_syX$qMeIr)d|l0?NrR^E-?GdmH8e3$=;<zw<|+1v4LbW>IGZVy+}F>hL;
zC3M^lJS8*su_p6B+&tS^+hOEi&%2LFat~eZ((MXWOod#m2xI5OE4Vmm#&~d8mZwzE
ze?Rw=iL5yH0zB``f;aMhib>Y2Coxx1+Y)zdp(?6UovKR3qE+aJjqA}mP1?hx<mFH2
z+7i&+`$IcezeIHW+PJn8q^{|w^r=JtjQL$k%md;D&DHzj+5-7Hx(8)8IGUWn4+|ge
z{94|()6XvN;Iu)svkP_Eq+~Y%@0T0LYCQKh`(77(5h=1#d7*=Fk+rO>Y8?rfn9f_o
zvg+EL<uPq%`q&p#+zboQ?<|~Tk5(>oZyOMPk`(92_GYAsZ0M_A%7C*EA1m0ca(HZ3
zQnBOW)#}o=OQ;)+)M!LOlNHB>&!1j9G0uy0D|F5p243D_%ilWi?g)Ob&OB|fD2!J1
zyf8<2@B-<izto0{L0NZ%{)EJ<xSf(%WsAo<MaD~(q#|~u_hZ=Pv%_TM9MDDXOYzkH
zxWz-!zBv+WtWIm!vhhHv5LYONnCUg6Zf%C+UC!DQxeR)v$ks?(wgH8%NyBoFkr7s=
z>ph-2r<F5W4}Sh0cR^9PxOmeetaE~7p<Q9xTKidw0IJ=aO+P<b{~S`z2>m$&gg;~c
zigL^>_iRhi%~F0BRoYa$U<%0-`i=gj@~=C6JK^C!X<!sgE0FA#Z>P)_I|ZJ#V~&ts
z|4f!V;=J?>>*w9}?bg#X0|$FH&sV9&FW6+qsGPUrkQy(_v2$l}CRJ63+(q3FuNSOl
zlt-G<sNI~jccxQq!H8NbBj77frZmz`f>W*A>5Eq7-#G|OmoV`hih9R9uwQ(%bS-NW
zCEZf)(@euQuV4Fet$`MKH~dShiV0^z(&gDBVvFvM0&;Q=W&C+u3zxrYBnQ){Cc{&#
zdi!;%9m_t8zcfid?{n?+s~onYlZop&M`k5#Mpe8=%g%k7i9IZ=;j_$W6h)g6eMUg$
z;cLr`*cBO%s6wU@>+Jkoh1{XDe9?b`?ZwtJjU+KWs3uL)%rHrqA31tOp7I=N@YiO(
zo&Ltnobnv$xc3fVqC(yG%Kf>0rs{$X964BUGyizw*U4c!?QU=S8FldB0IWf>A5%{L
zxqUTf;U@@^9-+*MLHDj5RJrZkA7_$us_BqS+1XLSTT>FE$2C(w1P+c*O3)1LG^cqS
zWU;y$bjC@(eY7U=fgKB->cs@9+fNvLXc#gyj|$KBCXFE>DW;R9PmbBdWTa@c2EI@z
z*T#H!c6*_5!0V2plg+M0QHdbU&1>AFuhjh49iAqRSl=3R5w4J@;_T*XaAebFv&w3r
z6UXshiwfQwAa2BaVAaU6%I$z_<puK~ng?l_5zqbK2{D9LFxLgMbiG8Xsg*Y|TD!=q
zoO-^Q%BQ~+VLx=j_|rWe;-woEL2=f>K5IN~JfS+UKK-zL1yMCoaj@_9aq}r>zlntg
z3(*-_<_j%ajgh|}R^5L=Zae+-VfBY|5>qK>LSY%}YS3$g!@;jOawwnK*U$Zm`F8r*
z+x*94Qn6IDbE`-&(_+A#P!lR&rZJWx^=H3AzMcL)m~SmDb26nO1)tZhM6U%O!=;X?
z)0xF|3o`!-`F8sILf(8cZZF_0@L)QW!>;W{WbZXsTSbvfGvl{nS{UR7L~LNqn@5!=
zRx}4UpKpXLZ#2$tUfI-K+|-=;x)=VMJm_EX{EQBh$bMmd1((iTJ!U4Oe!$9AJP@D*
z#NKfPwADWv9QVK~!7?uxKUn(=qsfRgMv4h>Fc^mNuI+udq4{n-<mSpDRKc5`=)l9g
z2q6_-(8@V}m<uYH^>2vN|0kjs5@4L7Ff>C2@sO|>OQO}ii{2%r^h%;FBSevX>~cE}
z@kwy*aP$<Z==PnxrgVet(SYz_Jq@0bARoP!3lS0$a~eIhcdVv|PL_J%O1Y5PxL2Lp
zm^9bl$rh7ln-v=74&~+b>blfzX&KeGA{={5FEW(HzOyX30Ipql-3aa^)tphqjeKg+
z{Tp|LqN12Ox2;pb7UieeVlICg{XdS<-%0`iK&R-A$9sc3&fVJu{e3evI318-00L0n
ze-Y$+sUOQ)|9hX*06^78CL-KG{uJ45t524HwFbHRFPi^FzYxl0VXG*DL6b>fE`Y(2
z$bV^2?9zPGr80F#V-X+&bw~f`I}A*mfaRmDg0u@7NBpCO@|*qbl2(-8@EagJ&^Qc5
z2J*!n>)}Mv_IBSgx_y`;=-=A}&_s;WHaD2Oh&brC0oIbpNF2zgk;o+UHkoM3-xmHu
zC@79E00tmq@Si09g?Kk9U!=o8t2z)gz`QvI@Hm6{^?q&bFSt<3M1dDx`Z&&Z2temD
z^QL`Y6Ge+e-U{m<ee9(Cv4Y|)INI&?lw^bYOLhmaB}ntFedo9QkMbXSRR2x8IM^5J
zTOHN6_8)UfQU~Syw|NX2rBMe(UV_OLEVqGa;P(WH0uwFBfBDv(0*Q>mZyP&^hn=Dz
zQo&n=Lks}8K)?7D0ANoJ00_kcfGFh;CXxROtf{`aFubh}0@?1}pS9l?wZ1R@Cs@~j
zx3bpnx{$U14D0Jh0N}XRzk@Xi@8z*w@&s5$Z-aH=H(0Zh+`lvW-$2^!8>F3ofV8zc
zK>_hEZc_oQe+(5Qc?=1?1tRLu(9nHgBMq2yYH@ApY@|>UEm%Xv&PoSn5K5e(+b~Kg
zbN+=RDoQxDw&8~c_#QWZlqrdJTRjB>bl-TFA8-YZ1p@X5A^*Mkj~Jvs1V%LxoB_=(
zmjG@P0N@AbT`(U2_C*7L7>Gdt>4hd!LTcxZA^#Ctq3!bwVuOev5OCY)S{nO1m_&=o
ecuI$R(1<PNtvNA9csnU7%E0Ah;4nE##s2`fl)MT6
--- a/dom/media/mediasink/AudioSink.h
+++ b/dom/media/mediasink/AudioSink.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(AudioSink_h__)
 #define AudioSink_h__
 
+#include "mozilla/MozPromise.h"
 #include "mozilla/nsRefPtr.h"
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 
 class MediaData;
 template <class T> class MediaQueue;
 
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -40,16 +40,20 @@ DecodedAudioDataSink::DecodedAudioDataSi
   , mLastGoodPosition(0)
   , mInfo(aInfo)
   , mChannel(aChannel)
   , mStopAudioThread(false)
   , mPlaying(true)
 {
 }
 
+DecodedAudioDataSink::~DecodedAudioDataSink()
+{
+}
+
 void
 DecodedAudioDataSink::SetState(State aState)
 {
   AssertOnAudioThread();
   mPendingState = Some(aState);
 }
 
 void
--- a/dom/media/mediasink/DecodedAudioDataSink.h
+++ b/dom/media/mediasink/DecodedAudioDataSink.h
@@ -2,27 +2,31 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(DecodedAudioDataSink_h__)
 #define DecodedAudioDataSink_h__
 
 #include "AudioSink.h"
+#include "MediaEventSource.h"
 #include "MediaInfo.h"
 #include "mozilla/nsRefPtr.h"
 #include "nsISupportsImpl.h"
 
 #include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/ReentrantMonitor.h"
 
 namespace mozilla {
+
+class AudioStream;
+
 namespace media {
 
 class DecodedAudioDataSink : public AudioSink {
 public:
 
   DecodedAudioDataSink(MediaQueue<MediaData>& aAudioQueue,
                        int64_t aStartTime,
                        const AudioInfo& aInfo,
@@ -54,17 +58,17 @@ private:
   enum State {
     AUDIOSINK_STATE_INIT,
     AUDIOSINK_STATE_PLAYING,
     AUDIOSINK_STATE_COMPLETE,
     AUDIOSINK_STATE_SHUTDOWN,
     AUDIOSINK_STATE_ERROR
   };
 
-  virtual ~DecodedAudioDataSink() {}
+  virtual ~DecodedAudioDataSink();
 
   void DispatchTask(already_AddRefed<nsIRunnable>&& event);
   void SetState(State aState);
   void ScheduleNextLoop();
   void ScheduleNextLoopCrossThread();
 
   void OnAudioQueueEvent();
   void ConnectListener();
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -17,21 +17,16 @@
 #include "MP4Stream.h"
 #include "mp4_demuxer/AtomType.h"
 #include "mp4_demuxer/ByteReader.h"
 #endif
 #include "SourceBufferResource.h"
 
 extern PRLogModuleInfo* GetMediaSourceSamplesLog();
 
-/* Polyfill __func__ on MSVC to pass to the log. */
-#ifdef _MSC_VER
-#define __func__ __FUNCTION__
-#endif
-
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
 #define MSE_DEBUG(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Debug, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
 #define MSE_DEBUGV(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Verbose, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
 
 namespace mozilla {
 
 ContainerParser::ContainerParser(const nsACString& aType)
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -41,17 +41,16 @@ extern PRLogModuleInfo* GetMediaSourceLo
 #define EOS_FUZZ_US 125000
 
 namespace mozilla {
 
 MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
   : MediaDecoderReader(aDecoder)
   , mLastAudioTime(0)
   , mLastVideoTime(0)
-  , mForceVideoDecodeAhead(false)
   , mOriginalSeekTime(-1)
   , mPendingSeekTime(-1)
   , mWaitingForSeekData(false)
   , mSeekToEnd(false)
   , mTimeThreshold(0)
   , mDropAudioBeforeThreshold(false)
   , mDropVideoBeforeThreshold(false)
   , mAudioDiscontinuity(false)
@@ -302,19 +301,17 @@ MediaSourceReader::OnAudioNotDecoded(Not
   if (mLastAudioTime - lastAudioTime >= EOS_FUZZ_US) {
     // No decoders are available to switch to. We will re-attempt from the last
     // failing position.
     mLastAudioTime = lastAudioTime;
   }
 }
 
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
-MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe,
-                                    int64_t aTimeThreshold,
-                                    bool aForceDecodeAhead)
+MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty(), "No sample requests allowed while seeking");
   MOZ_DIAGNOSTIC_ASSERT(mVideoPromise.IsEmpty(), "No duplicate sample requests");
   nsRefPtr<VideoDataPromise> p = mVideoPromise.Ensure(__func__);
   MSE_DEBUGV("RequestVideoData(%d, %lld), mLastVideoTime=%lld",
              aSkipToNextKeyframe, aTimeThreshold, mLastVideoTime);
   if (!mVideoTrack) {
@@ -328,17 +325,16 @@ MediaSourceReader::RequestVideoData(bool
     mDropVideoBeforeThreshold = true;
   }
   if (IsSeeking()) {
     MSE_DEBUG("called mid-seek. Rejecting.");
     mVideoPromise.Reject(CANCELED, __func__);
     return p;
   }
   MOZ_DIAGNOSTIC_ASSERT(!mVideoSeekRequest.Exists());
-  mForceVideoDecodeAhead = aForceDecodeAhead;
 
   SwitchSourceResult ret = SwitchVideoSource(&mLastVideoTime);
   switch (ret) {
     case SOURCE_NEW:
       GetVideoReader()->ResetDecode();
       mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mLastVideoTime), 0)
                              ->Then(OwnerThread(), __func__, this,
                                     &MediaSourceReader::CompleteVideoSeekAndDoRequest,
@@ -362,18 +358,17 @@ MediaSourceReader::RequestVideoData(bool
 
   return p;
 }
 
 void
 MediaSourceReader::DoVideoRequest()
 {
   mVideoRequest.Begin(GetVideoReader()->RequestVideoData(mDropVideoBeforeThreshold,
-                                                         GetReaderVideoTime(mTimeThreshold),
-                                                         mForceVideoDecodeAhead)
+                                                         GetReaderVideoTime(mTimeThreshold))
                       ->Then(OwnerThread(), __func__, this,
                              &MediaSourceReader::OnVideoDecoded,
                              &MediaSourceReader::OnVideoNotDecoded));
 }
 
 void
 MediaSourceReader::OnVideoDecoded(VideoData* aSample)
 {
@@ -889,19 +884,16 @@ MediaSourceReader::ResetDecode()
   // Do the same for any data wait promises.
   mAudioWaitPromise.RejectIfExists(WaitForDataRejectValue(MediaData::AUDIO_DATA, WaitForDataRejectValue::CANCELED), __func__);
   mVideoWaitPromise.RejectIfExists(WaitForDataRejectValue(MediaData::VIDEO_DATA, WaitForDataRejectValue::CANCELED), __func__);
 
   // Reset miscellaneous seeking state.
   mWaitingForSeekData = false;
   mPendingSeekTime = -1;
 
-  // Reset force video decode ahead.
-  mForceVideoDecodeAhead = false;
-
   // Reset all the readers.
   if (GetAudioReader()) {
     GetAudioReader()->ResetDecode();
   }
   if (GetVideoReader()) {
     GetVideoReader()->ResetDecode();
   }
 
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -44,17 +44,17 @@ public:
   // registered TrackBuffers essential for initialization.
   void PrepareInitialization();
 
   bool IsWaitingMediaResources() override;
   bool IsWaitingOnCDMResource() override;
 
   nsRefPtr<AudioDataPromise> RequestAudioData() override;
   nsRefPtr<VideoDataPromise>
-  RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold, bool aForceDecodeAhead) override;
+  RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold) override;
 
   virtual size_t SizeOfVideoQueueInFrames() override;
   virtual size_t SizeOfAudioQueueInFrames() override;
 
   virtual void ReleaseMediaResources() override;
 
   void OnAudioDecoded(AudioData* aSample);
   void OnAudioNotDecoded(NotDecodedReason aReason);
@@ -250,18 +250,16 @@ private:
 #ifdef MOZ_EME
   nsRefPtr<CDMProxy> mCDMProxy;
 #endif
 
   // These are read and written on the decode task queue threads.
   int64_t mLastAudioTime;
   int64_t mLastVideoTime;
 
-  bool mForceVideoDecodeAhead;
-
   MozPromiseRequestHolder<SeekPromise> mAudioSeekRequest;
   MozPromiseRequestHolder<SeekPromise> mVideoSeekRequest;
   MozPromiseHolder<SeekPromise> mSeekPromise;
 
   // Temporary seek information while we wait for the data
   // to be added to the track buffer.
   int64_t mOriginalSeekTime;
   int64_t mPendingSeekTime;
--- a/dom/media/mediasource/ResourceQueue.cpp
+++ b/dom/media/mediasource/ResourceQueue.cpp
@@ -7,21 +7,16 @@
 #include "ResourceQueue.h"
 #include "nsDeque.h"
 #include "MediaData.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Logging.h"
 
 extern PRLogModuleInfo* GetSourceBufferResourceLog();
 
-/* Polyfill __func__ on MSVC to pass to the log. */
-#ifdef _MSC_VER
-#define __func__ __FUNCTION__
-#endif
-
 #define SBR_DEBUG(arg, ...) MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Debug, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 #define SBR_DEBUGV(arg, ...) MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Verbose, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
 namespace mozilla {
 
 ResourceItem::ResourceItem(MediaByteBuffer* aData)
   : mData(aData)
 {
--- a/dom/media/mediasource/SourceBufferDecoder.cpp
+++ b/dom/media/mediasource/SourceBufferDecoder.cpp
@@ -6,20 +6,16 @@
 
 #include "MediaSourceUtils.h"
 #include "SourceBufferDecoder.h"
 #include "mozilla/Logging.h"
 #include "AbstractMediaDecoder.h"
 #include "MediaDecoderReader.h"
 
 extern PRLogModuleInfo* GetMediaSourceLog();
-/* Polyfill __func__ on MSVC to pass to the log. */
-#ifdef _MSC_VER
-#define __func__ __FUNCTION__
-#endif
 
 #define MSE_DEBUG(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Debug, ("SourceBufferDecoder(%p:%s)::%s: " arg, this, mResource->GetContentType().get(), __func__, ##__VA_ARGS__))
 
 namespace mozilla {
 
 class ReentrantMonitor;
 
 namespace layers {
--- a/dom/media/omx/AudioOffloadPlayer.cpp
+++ b/dom/media/omx/AudioOffloadPlayer.cpp
@@ -740,14 +740,13 @@ void AudioOffloadPlayer::WakeLockCreate(
 
 void AudioOffloadPlayer::WakeLockRelease()
 {
   MOZ_ASSERT(NS_IsMainThread());
   AUDIO_OFFLOAD_LOG(LogLevel::Debug, ("%s", __FUNCTION__));
   if (mWakeLock) {
     ErrorResult rv;
     mWakeLock->Unlock(rv);
-    NS_WARN_IF_FALSE(!rv.Failed(), "Failed to unlock the wakelock.");
     mWakeLock = nullptr;
   }
 }
 
 } // namespace mozilla
--- a/dom/media/omx/MediaCodecReader.cpp
+++ b/dom/media/omx/MediaCodecReader.cpp
@@ -348,18 +348,17 @@ MediaCodecReader::RequestAudioData()
     DispatchAudioTask();
   }
   MOZ_ASSERT(mAudioTrack.mAudioPromise.IsEmpty());
   return mAudioTrack.mAudioPromise.Ensure(__func__);
 }
 
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
 MediaCodecReader::RequestVideoData(bool aSkipToNextKeyframe,
-                                   int64_t aTimeThreshold,
-                                   bool aForceDecodeAhead)
+                                   int64_t aTimeThreshold)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(HasVideo());
 
   int64_t threshold = sInvalidTimestampUs;
   if (aSkipToNextKeyframe && IsValidTimestampUs(aTimeThreshold)) {
     threshold = aTimeThreshold;
   }
--- a/dom/media/omx/MediaCodecReader.h
+++ b/dom/media/omx/MediaCodecReader.h
@@ -78,18 +78,17 @@ protected:
 public:
 
   // Flush the TaskQueue, flush MediaCodec and raise the mDiscontinuity.
   virtual nsresult ResetDecode() override;
 
   // Disptach a DecodeVideoFrameTask to decode video data.
   virtual nsRefPtr<VideoDataPromise>
   RequestVideoData(bool aSkipToNextKeyframe,
-                   int64_t aTimeThreshold,
-                   bool aForceDecodeAhead) override;
+                   int64_t aTimeThreshold) override;
 
   // Disptach a DecodeAduioDataTask to decode video data.
   virtual nsRefPtr<AudioDataPromise> RequestAudioData() override;
 
   virtual bool HasAudio();
   virtual bool HasVideo();
 
   virtual nsRefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
--- a/dom/media/omx/RtspMediaCodecReader.cpp
+++ b/dom/media/omx/RtspMediaCodecReader.cpp
@@ -77,23 +77,20 @@ nsRefPtr<MediaDecoderReader::AudioDataPr
 RtspMediaCodecReader::RequestAudioData()
 {
   EnsureActive();
   return MediaCodecReader::RequestAudioData();
 }
 
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
 RtspMediaCodecReader::RequestVideoData(bool aSkipToNextKeyframe,
-                                       int64_t aTimeThreshold,
-                                       bool aForceDecodeAhead)
+                                       int64_t aTimeThreshold)
 {
   EnsureActive();
-  return MediaCodecReader::RequestVideoData(aSkipToNextKeyframe,
-                                            aTimeThreshold,
-                                            aForceDecodeAhead);
+  return MediaCodecReader::RequestVideoData(aSkipToNextKeyframe, aTimeThreshold);
 }
 
 nsRefPtr<MediaDecoderReader::MetadataPromise>
 RtspMediaCodecReader::AsyncReadMetadata()
 {
   mRtspResource->DisablePlayoutDelay();
   EnsureActive();
 
--- a/dom/media/omx/RtspMediaCodecReader.h
+++ b/dom/media/omx/RtspMediaCodecReader.h
@@ -48,18 +48,17 @@ public:
     return media::TimeIntervals::Invalid();
   }
 
   virtual void SetIdle() override;
 
   // Disptach a DecodeVideoFrameTask to decode video data.
   virtual nsRefPtr<VideoDataPromise>
   RequestVideoData(bool aSkipToNextKeyframe,
-                   int64_t aTimeThreshold,
-                   bool aForceDecodeAhead) override;
+                   int64_t aTimeThreshold) override;
 
   // Disptach a DecodeAudioDataTask to decode audio data.
   virtual nsRefPtr<AudioDataPromise> RequestAudioData() override;
 
   virtual nsRefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata()
     override;
 
   virtual void HandleResourceAllocated() override;
--- a/dom/media/platforms/apple/AppleVDADecoder.h
+++ b/dom/media/platforms/apple/AppleVDADecoder.h
@@ -82,17 +82,17 @@ public:
   }
 
   void DispatchOutputTask(already_AddRefed<nsIRunnable> aTask)
   {
     nsCOMPtr<nsIRunnable> task = aTask;
     if (mIsShutDown || mIsFlushing) {
       return;
     }
-    mTaskQueue->Dispatch(task.forget());
+    mTaskQueue->Dispatch(task.forget(), AbstractThread::DontAssertDispatchSuccess);
   }
 
   nsresult OutputFrame(CFRefPtr<CVPixelBufferRef> aImage,
                        AppleFrameRef aFrameRef);
 
 protected:
   // Flush and Drain operation, always run
   virtual void ProcessFlush();
--- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
@@ -27,16 +27,17 @@ struct AvFormatLib
 
 template <int V> class FFmpegDecoderModule
 {
 public:
   static already_AddRefed<PlatformDecoderModule> Create();
 };
 
 static const AvFormatLib sLibs[] = {
+  { "libavformat-ffmpeg.so.56", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.56", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.55", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.54", FFmpegDecoderModule<54>::Create, 54 },
   { "libavformat.so.53", FFmpegDecoderModule<53>::Create, 53 },
   { "libavformat.56.dylib", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.55.dylib", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.54.dylib", FFmpegDecoderModule<54>::Create, 54 },
   { "libavformat.53.dylib", FFmpegDecoderModule<53>::Create, 53 },
--- a/dom/media/test/test_media_selection.html
+++ b/dom/media/test/test_media_selection.html
@@ -15,16 +15,17 @@ if (SpecialPowers.Services.appinfo.name 
 }
 
 var manager = new MediaTestManager;
 
 function maketest(attach_media, name, type, check_metadata) {
   return function (token) {
     var e = document.createElement('video');
     e.preload = "metadata";
+    token = name + "-" + token;
     manager.started(token);
     var errorRun = false;
     if (check_metadata) {
       e.addEventListener('loadedmetadata', function () {
           ok(e.readyState >= HTMLMediaElement.HAVE_METADATA,
              'test ' +  token + ' readyState ' + e.readyState + ' expected >= ' + HTMLMediaElement.HAVE_METADATA);
           is(e.currentSrc.substring(e.currentSrc.length - name.length), name, 'test ' + token);
           // The load can go idle due to cache size limits
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -84,16 +84,17 @@ skip-if = buildapp == 'b2g' || buildapp 
 [test_peerConnection_bug825703.html]
 [test_peerConnection_bug827843.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_bug834153.html]
 [test_peerConnection_bug1013809.html]
 skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
 [test_peerConnection_bug1042791.html]
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || os == 'android' # bug 1043403 # Bug 1141029 Mulet parity with B2G Desktop for TC
+[test_peerConnection_bug1064223.html]
 [test_peerConnection_capturedVideo.html]
 tags=capturestream
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_captureStream_canvas_2d.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_captureStream_canvas_webgl.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 # [test_peerConnection_certificates.html] # bug 1180968
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -1249,72 +1249,16 @@ PeerConnectionWrapper.prototype = {
    */
   countTracksInConstraint : function(type, constraints) {
     if (!Array.isArray(constraints)) {
       return 0;
     }
     return constraints.reduce((sum, c) => sum + (c[type] ? 1 : 0), 0);
   },
 
-  /**
-   * Checks for audio in given offer options.
-   *
-   * @param options
-   *        The options to be examined.
-   */
-  audioInOfferOptions : function(options) {
-    if (!options) {
-      return 0;
-    }
-
-    var offerToReceiveAudio = options.offerToReceiveAudio;
-
-    // TODO: Remove tests of old constraint-like RTCOptions soon (Bug 1064223).
-    if (options.mandatory && options.mandatory.OfferToReceiveAudio !== undefined) {
-      offerToReceiveAudio = options.mandatory.OfferToReceiveAudio;
-    } else if (options.optional && options.optional[0] &&
-               options.optional[0].OfferToReceiveAudio !== undefined) {
-      offerToReceiveAudio = options.optional[0].OfferToReceiveAudio;
-    }
-
-    if (offerToReceiveAudio) {
-      return 1;
-    } else {
-      return 0;
-    }
-  },
-
-  /**
-   * Checks for video in given offer options.
-   *
-   * @param options
-   *        The options to be examined.
-   */
-  videoInOfferOptions : function(options) {
-    if (!options) {
-      return 0;
-    }
-
-    var offerToReceiveVideo = options.offerToReceiveVideo;
-
-    // TODO: Remove tests of old constraint-like RTCOptions soon (Bug 1064223).
-    if (options.mandatory && options.mandatory.OfferToReceiveVideo !== undefined) {
-      offerToReceiveVideo = options.mandatory.OfferToReceiveVideo;
-    } else if (options.optional && options.optional[0] &&
-               options.optional[0].OfferToReceiveVideo !== undefined) {
-      offerToReceiveVideo = options.optional[0].OfferToReceiveVideo;
-    }
-
-    if (offerToReceiveVideo) {
-      return 1;
-    } else {
-      return 0;
-    }
-  },
-
   checkLocalMediaTracks : function() {
     var observed = {};
     info(this + " Checking local tracks " + JSON.stringify(this.expectedLocalTrackInfoById));
     this._pc.getSenders().forEach(sender => {
       this.checkTrackIsExpected(sender.track, this.expectedLocalTrackInfoById, observed);
     });
 
     Object.keys(this.expectedLocalTrackInfoById).forEach(
@@ -1381,32 +1325,32 @@ PeerConnectionWrapper.prototype = {
     } else {
       this.remoteRequiresTrickleIce = requiresTrickleIce;
     }
 
     //TODO: how can we check for absence/presence of m=application?
 
     var audioTracks =
         this.countTracksInConstraint('audio', offerConstraintsList) ||
-      this.audioInOfferOptions(offerOptions);
+        ((offerOptions && offerOptions.offerToReceiveAudio) ? 1 : 0);
 
     info("expected audio tracks: " + audioTracks);
     if (audioTracks == 0) {
       ok(!desc.sdp.includes("m=audio"), "audio m-line is absent from SDP");
     } else {
       ok(desc.sdp.includes("m=audio"), "audio m-line is present in SDP");
       ok(desc.sdp.includes("a=rtpmap:109 opus/48000/2"), "OPUS codec is present in SDP");
       //TODO: ideally the rtcp-mux should be for the m=audio, and not just
       //      anywhere in the SDP (JS SDP parser bug 1045429)
       ok(desc.sdp.includes("a=rtcp-mux"), "RTCP Mux is offered in SDP");
     }
 
     var videoTracks =
         this.countTracksInConstraint('video', offerConstraintsList) ||
-      this.videoInOfferOptions(offerOptions);
+        ((offerOptions && offerOptions.offerToReceiveVideo) ? 1 : 0);
 
     info("expected video tracks: " + videoTracks);
     if (videoTracks == 0) {
       ok(!desc.sdp.includes("m=video"), "video m-line is absent from SDP");
     } else {
       ok(desc.sdp.includes("m=video"), "video m-line is present in SDP");
       if (this.h264) {
         ok(desc.sdp.includes("a=rtpmap:126 H264/90000"), "H.264 codec is present in SDP");
@@ -1762,21 +1706,21 @@ PeerConnectionWrapper.prototype = {
     isnot(numIceConnections, 0, "Number of ICE connections according to stats is not zero");
     if (answer.sdp.includes('a=group:BUNDLE')) {
       is(numIceConnections, 1, "stats reports exactly 1 ICE connection");
     } else {
       // This code assumes that no media sections have been rejected due to
       // codec mismatch or other unrecoverable negotiation failures.
       var numAudioTracks =
           this.countTracksInConstraint('audio', offerConstraintsList) ||
-        this.audioInOfferOptions(offerOptions);
+          ((offerOptions && offerOptions.offerToReceiveAudio) ? 1 : 0);
 
       var numVideoTracks =
           this.countTracksInConstraint('video', offerConstraintsList) ||
-        this.videoInOfferOptions(offerOptions);
+          ((offerOptions && offerOptions.offerToReceiveVideo) ? 1 : 0);
 
       var numDataTracks = this.dataChannels.length;
 
       var numAudioVideoDataTracks = numAudioTracks + numVideoTracks + numDataTracks;
       info("expected audio + video + data tracks: " + numAudioVideoDataTracks);
       is(numAudioVideoDataTracks, numIceConnections, "stats ICE connections matches expected A/V tracks");
     }
   },
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_bug1064223.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="pc.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1064223",
+    title: "CreateOffer fails without streams or modern RTCOfferOptions"
+  });
+
+  runNetworkTest(function () {
+    var pc = new mozRTCPeerConnection();
+    var options = { mandatory: { OfferToReceiveVideo: true } }; // obsolete
+
+    pc.createOffer(options).then(() => ok(false, "createOffer must fail"),
+                                 e => is(e.name, "InternalError",
+                                         "createOffer must fail"))
+    .catch(e => ok(false, e.message))
+    .then(() => {
+      pc.close();
+      networkTestFinished();
+    })
+    .catch(e => ok(false, e.message));
+  });
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html
+++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html
@@ -9,17 +9,15 @@
   createHTML({
     bug: "850275",
     title: "Simple offer media constraint test with audio"
   });
 
   runNetworkTest(function() {
     var test = new PeerConnectionTest();
     test.setMediaConstraints([], [{audio: true}]);
-    // TODO: Stop using old constraint-like RTCOptions soon (Bug 1064223).
-    // Watch out for case-difference when fixing: { offerToReceiveAudio: true }
-    test.setOfferOptions({ mandatory: { OfferToReceiveAudio: true } });
+    test.setOfferOptions({ offerToReceiveAudio: true });
     test.run();
   });
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html
+++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html
@@ -9,17 +9,15 @@
   createHTML({
     bug: "850275",
     title: "Simple offer media constraint test with video"
   });
 
   runNetworkTest(function() {
     var test = new PeerConnectionTest();
     test.setMediaConstraints([], [{video: true}]);
-    // TODO: Stop using old constraint-like RTCOptions soon (Bug 1064223).
-    // Watch out for case-difference when fixing: { offerToReceiveVideo: true }
-    test.setOfferOptions({ optional: [{ OfferToReceiveVideo: true }] });
+    test.setOfferOptions({ offerToReceiveVideo: true });
     test.run();
   });
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/webspeech/recognition/models/dict/en-US.dic
+++ b/dom/media/webspeech/recognition/models/dict/en-US.dic
@@ -132986,16 +132986,17 @@ zerilli	Z ER IY L IY
 zeringue	Z EH R IH NG
 zerkle	Z IH R K AH L
 zerlina	Z ER L IY N AH
 zerlinda	Z ER L IY N D AH
 zermeno	Z ER M EH N OW
 zern	Z IH R N
 zero	Z IH R OW
 0	Z IH R OW
+0(2)	OW
 zero's	Z IH R OW Z
 zero's(2)	Z IY R OW Z
 zero(2)	Z IY R OW
 zeroed	Z IH R OW D
 zeroed(2)	Z IY R OW D
 zeroes	Z IH R OW Z
 zeroes(2)	Z IY R OW Z
 zeroing	Z IY R OW IH NG
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -27,33 +27,31 @@ EXPORTS += [
     'nsJSNPRuntime.h',
     'nsNPAPIPluginInstance.h',
     'nsPluginDirServiceProvider.h',
     'nsPluginHost.h',
     'nsPluginInstanceOwner.h',
     'nsPluginLogging.h',
     'nsPluginNativeWindow.h',
     'nsPluginNativeWindowGtk.h',
-    'nsPluginPlayPreviewInfo.h',
     'nsPluginsCID.h',
     'nsPluginsDir.h',
     'nsPluginTags.h',
 ]
 
 EXPORTS.mozilla += [
     'PluginPRLibrary.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsJSNPRuntime.cpp',
     'nsNPAPIPluginInstance.cpp',
     'nsNPAPIPluginStreamListener.cpp',
     'nsPluginInstanceOwner.cpp',
     'nsPluginModule.cpp',
-    'nsPluginPlayPreviewInfo.cpp',
     'nsPluginStreamListenerPeer.cpp',
     'nsPluginTags.cpp',
     'PluginPRLibrary.cpp',
 ]
 
 SOURCES += [
     'nsNPAPIPlugin.cpp', # Conflict with X11 headers
     'nsPluginHost.cpp',  # Conflict with NS_NPAPIPLUGIN_CALLBACK
--- a/dom/plugins/base/nsIPluginHost.idl
+++ b/dom/plugins/base/nsIPluginHost.idl
@@ -7,41 +7,26 @@
 #include "nsISupports.idl"
 #include "nsIPluginTag.idl"
 
 %{C++
 #define MOZ_PLUGIN_HOST_CONTRACTID \
   "@mozilla.org/plugin/host;1"
 %}
 
-[scriptable, uuid(57069ada-2845-46ef-b57f-233596d1c02c)]
-interface nsIPluginPlayPreviewInfo : nsISupports
-{
-  readonly attribute AUTF8String mimeType;
-  readonly attribute boolean     ignoreCTP;
-  readonly attribute AUTF8String redirectURL;
-  readonly attribute AUTF8String whitelist;
-
-  /**
-   * Checks if pageURI and objectURI matches once of the entries in
-   * the whitelist. If whitelist is empty, returns true. 
-   */
-  boolean checkWhitelist(in AUTF8String pageURI, in AUTF8String objectURI);
-};
-
 [scriptable, function, uuid(9c311778-7c2c-4ad8-b439-b8a2786a20dd)]
 interface nsIClearSiteDataCallback : nsISupports
 {
     /**
      * callback with the result from a call to clearSiteData
      */
     void callback(in nsresult rv);
 };
 
-[scriptable, uuid(0f73bbd2-fc89-41df-b31b-38c09903d187)]
+[scriptable, uuid(f938f5ba-7093-42cd-a559-af8039d99204)]
 interface nsIPluginHost : nsISupports
 {
   /**
    * Causes the plugins directory to be searched again for new plugin
    * libraries.
    */
   void reloadPlugins();
 
@@ -98,37 +83,16 @@ interface nsIPluginHost : nsISupports
    * @param domain: the domain to test. If this argument is null, test if data
    *                is stored for any site. The base domain for the given domain
    *                will be determined; if any data for the base domain or its
    *                subdomains is found, return true.
    */
   boolean siteHasData(in nsIPluginTag plugin, in AUTF8String domain);
 
   /**
-   * Registers the play preview plugin mode for specific mime type
-   *
-   * @param mimeType: specifies plugin mime type.
-   * @param ignoreCTP: if true, the play preview ignores CTP rules, e.g.
-                       whitelisted websites, will not notify about plugin
-                       presence in the address bar.
-   * @param redirectURL: specifies url for the overlay iframe
-   * @param whitelist: specifies plugin whitelist in form of comma separated
-   *                   "[@page_url object_url|@page_url|object_url]" entries,
-   *                    e.g. @http://example.org/* http://example.org/t.swf
-   */
-  void registerPlayPreviewMimeType(in AUTF8String mimeType,
-                                   [optional] in boolean ignoreCTP,
-                                   [optional] in AUTF8String redirectURL,
-                                   [optional] in AUTF8String whitelist);
-
-  void unregisterPlayPreviewMimeType(in AUTF8String mimeType);
-
-  nsIPluginPlayPreviewInfo getPlayPreviewInfo(in AUTF8String mimeType);
-
-  /**
    * Get the "permission string" for the plugin.  This is a string that can be
    * passed to the permission manager to see whether the plugin is allowed to
    * run, for example.  This will typically be based on the plugin's "nice name"
    * and its blocklist state.
    *
    * @mimeType The MIME type we're interested in.
    * @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
    */
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1593,68 +1593,16 @@ nsPluginHost::UnregisterFakePlugin(const
       mFakePlugins.RemoveElementAt(i);
       return NS_OK;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPluginHost::RegisterPlayPreviewMimeType(const nsACString& mimeType,
-                                          bool ignoreCTP,
-                                          const nsACString& redirectURL,
-                                          const nsACString& whitelist)
-{
-  nsAutoCString mt(mimeType);
-  nsAutoCString url(redirectURL);
-  if (url.Length() == 0) {
-    // using default play preview iframe URL, if redirectURL is not specified
-    url.AssignLiteral("data:application/x-moz-playpreview;,");
-    url.Append(mimeType);
-  }
-  nsAutoCString wl(whitelist);
-
-  nsRefPtr<nsPluginPlayPreviewInfo> playPreview =
-    new nsPluginPlayPreviewInfo(mt.get(), ignoreCTP, url.get(), wl.get());
-  mPlayPreviewMimeTypes.AppendElement(playPreview);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPluginHost::UnregisterPlayPreviewMimeType(const nsACString& mimeType)
-{
-  nsAutoCString mimeTypeToRemove(mimeType);
-  for (uint32_t i = mPlayPreviewMimeTypes.Length(); i > 0; i--) {
-    nsRefPtr<nsPluginPlayPreviewInfo> pp = mPlayPreviewMimeTypes[i - 1];
-    if (PL_strcasecmp(pp.get()->mMimeType.get(), mimeTypeToRemove.get()) == 0) {
-      mPlayPreviewMimeTypes.RemoveElementAt(i - 1);
-      break;
-    }
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPluginHost::GetPlayPreviewInfo(const nsACString& mimeType,
-                                 nsIPluginPlayPreviewInfo** aResult)
-{
-  nsAutoCString mimeTypeToFind(mimeType);
-  for (uint32_t i = 0; i < mPlayPreviewMimeTypes.Length(); i++) {
-    nsRefPtr<nsPluginPlayPreviewInfo> pp = mPlayPreviewMimeTypes[i];
-    if (PL_strcasecmp(pp.get()->mMimeType.get(), mimeTypeToFind.get()) == 0) {
-      *aResult = new nsPluginPlayPreviewInfo(pp.get());
-      NS_ADDREF(*aResult);
-      return NS_OK;
-    }
-  }
-  *aResult = nullptr;
-  return NS_ERROR_NOT_AVAILABLE;
-}
-
 // FIXME-jsplugins Is this method actually needed?
 NS_IMETHODIMP
 nsPluginHost::GetFakePlugin(const nsACString & aMimeType,
                             nsIFakePluginTag** aResult)
 {
   nsRefPtr<nsFakePluginTag> result = FindFakePluginForType(aMimeType, false);
   if (result) {
     result.forget(aResult);
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -7,17 +7,16 @@
 #define nsPluginHost_h_
 
 #include "nsIPluginHost.h"
 #include "nsIObserver.h"
 #include "nsCOMPtr.h"
 #include "prlink.h"
 #include "prclist.h"
 #include "nsIPluginTag.h"
-#include "nsPluginPlayPreviewInfo.h"
 #include "nsPluginsDir.h"
 #include "nsPluginDirServiceProvider.h"
 #include "nsAutoPtr.h"
 #include "nsWeakPtr.h"
 #include "nsIPrompt.h"
 #include "nsWeakReference.h"
 #include "MainThreadUtils.h"
 #include "nsTArray.h"
@@ -364,17 +363,16 @@ private:
 
   // On certain platforms, we only want to load certain plugins. This function
   // centralizes loading rules.
   bool ShouldAddPlugin(nsPluginTag* aPluginTag);
 
   nsRefPtr<nsPluginTag> mPlugins;
   nsRefPtr<nsPluginTag> mCachedPlugins;
   nsRefPtr<nsInvalidPluginTag> mInvalidPlugins;
-  nsTArray< nsRefPtr<nsPluginPlayPreviewInfo> > mPlayPreviewMimeTypes;
 
   nsTArray< nsRefPtr<nsFakePluginTag> > mFakePlugins;
 
   bool mPluginsLoaded;
 
   // set by pref plugin.override_internal_types
   bool mOverrideInternalTypes;
 
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -2132,16 +2132,18 @@ nsEventStatus nsPluginInstanceOwner::Pro
         pPluginEvent = &pluginEvent;
         break;
       case NS_BLUR_CONTENT:
         pluginEvent.event = WM_KILLFOCUS;
         pluginEvent.wParam = 0;
         pluginEvent.lParam = 0;
         pPluginEvent = &pluginEvent;
         break;
+      default:
+        break;
     }
   }
 
   if (pPluginEvent && !pPluginEvent->event) {
     // Don't send null events to plugins.
     NS_WARNING("nsPluginFrame ProcessEvent: trying to send null event to plugin.");
     return rv;
   }
@@ -2166,16 +2168,18 @@ nsEventStatus nsPluginInstanceOwner::Pro
     case eMouseEventClass:
       {
         switch (anEvent.mMessage)
           {
           case NS_MOUSE_CLICK:
           case NS_MOUSE_DOUBLECLICK:
             // Button up/down events sent instead.
             return rv;
+          default:
+            break;
           }
 
         // Get reference point relative to plugin origin.
         const nsPresContext* presContext = mPluginFrame->PresContext();
         nsPoint appPoint =
           nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mPluginFrame) -
           mPluginFrame->GetContentRectRelativeToSelf().TopLeft();
         nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
@@ -2258,16 +2262,18 @@ nsEventStatus nsPluginInstanceOwner::Pro
                   event.button = 1;
                   break;
                 }
               // information lost:
               event.subwindow = None;
               event.same_screen = True;
             }
             break;
+          default:
+            break;
           }
       }
       break;
 
    //XXX case eMouseScrollEventClass: not received.
 
    case eKeyboardEventClass:
       if (anEvent.mPluginEvent)
@@ -2289,16 +2295,18 @@ nsEventStatus nsPluginInstanceOwner::Pro
                 event.type = XKeyPress;
               break;
             case NS_KEY_PRESS:
               event.type = XKeyPress;
               break;
             case NS_KEY_UP:
               event.type = KeyRelease;
               break;
+            default:
+              break;
             }
 #endif
 
           // Information that could be obtained from pluginEvent but we may not
           // want to promise to provide:
           event.subwindow = None;
           event.x = 0;
           event.y = 0;
@@ -2312,30 +2320,31 @@ nsEventStatus nsPluginInstanceOwner::Pro
           // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
           // gdk_keymap_get_entries_for_keyval will be useful, but the
           // mappings will not be unique.
           NS_WARNING("Synthesized key event not sent to plugin");
         }
       break;
 
     default:
-      switch (anEvent.mMessage)
-        {
+      switch (anEvent.mMessage) {
         case NS_FOCUS_CONTENT:
         case NS_BLUR_CONTENT:
           {
             XFocusChangeEvent &event = pluginEvent.xfocus;
             event.type =
               anEvent.mMessage == NS_FOCUS_CONTENT ? FocusIn : FocusOut;
             // information lost:
             event.mode = -1;
             event.detail = NotifyDetailNone;
           }
           break;
-        }
+        default:
+          break;
+      }
     }
 
   if (!pluginEvent.type) {
     return rv;
   }
 
   // Fill in (useless) generic event information.
   XAnyEvent& event = pluginEvent.xany;
@@ -2366,16 +2375,18 @@ nsEventStatus nsPluginInstanceOwner::Pro
     case eMouseEventClass:
       {
         switch (anEvent.mMessage)
           {
           case NS_MOUSE_CLICK:
           case NS_MOUSE_DOUBLECLICK:
             // Button up/down events sent instead.
             return rv;
+          default:
+            break;
           }
 
         // Get reference point relative to plugin origin.
         const nsPresContext* presContext = mPluginFrame->PresContext();
         nsPoint appPoint =
           nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mPluginFrame) -
           mPluginFrame->GetContentRectRelativeToSelf().TopLeft();
         nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
@@ -2407,16 +2418,18 @@ nsEventStatus nsPluginInstanceOwner::Pro
               event.inSize = sizeof(ANPEvent);
               event.eventType = kMouse_ANPEventType;
               event.data.mouse.action = kUp_ANPMouseAction;
               event.data.mouse.x = pluginPoint.x;
               event.data.mouse.y = pluginPoint.y;
               mInstance->HandleEvent(&event, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
             }
             break;
+          default:
+            break;
           }
       }
       break;
 
     case eKeyboardEventClass:
      {
        const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
        LOG("Firing eKeyboardEventClass %d %d\n",
deleted file mode 100644
--- a/dom/plugins/base/nsPluginPlayPreviewInfo.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/* -*- 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 "nsPluginPlayPreviewInfo.h"
-#include "nsWildCard.h"
-
-using namespace mozilla;
-
-nsPluginPlayPreviewInfo::nsPluginPlayPreviewInfo(const char* aMimeType,
-                                                 bool aIgnoreCTP,
-                                                 const char* aRedirectURL,
-                                                 const char* aWhitelist)
-  : mMimeType(aMimeType), mIgnoreCTP(aIgnoreCTP), mRedirectURL(aRedirectURL),
-    mWhitelist(aWhitelist) {}
-
-nsPluginPlayPreviewInfo::nsPluginPlayPreviewInfo(
-  const nsPluginPlayPreviewInfo* aSource)
-{
-  MOZ_ASSERT(aSource);
-
-  mMimeType = aSource->mMimeType;
-  mIgnoreCTP = aSource->mIgnoreCTP;
-  mRedirectURL = aSource->mRedirectURL;
-  mWhitelist = aSource->mWhitelist;
-}
-
-nsPluginPlayPreviewInfo::~nsPluginPlayPreviewInfo()
-{
-}
-
-NS_IMPL_ISUPPORTS(nsPluginPlayPreviewInfo, nsIPluginPlayPreviewInfo)
-
-NS_IMETHODIMP
-nsPluginPlayPreviewInfo::GetMimeType(nsACString& aMimeType)
-{
-  aMimeType = mMimeType;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPluginPlayPreviewInfo::GetIgnoreCTP(bool* aIgnoreCTP)
-{
-  *aIgnoreCTP = mIgnoreCTP;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPluginPlayPreviewInfo::GetRedirectURL(nsACString& aRedirectURL)
-{
-  aRedirectURL = mRedirectURL;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPluginPlayPreviewInfo::GetWhitelist(nsACString& aWhitelist)
-{
-  aWhitelist = mWhitelist;
-  return NS_OK;
-}
-
-/* static */ nsresult
-nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
-                                        const nsACString& aObjectURI,
-                                        const nsACString& aWhitelist,
-                                        bool *_retval)
-{
-  if (aWhitelist.Length() == 0) {
-    // Considering empty whitelist as '*' entry.
-    *_retval = true;
-    return NS_OK;
-  }
-
-  // Parses whitelist as comma separated entries of
-  //   [@page_url object_url|@page_url|object_url]
-  // where page_url and object_url pattern matches for aPageURI
-  // and aObjectURI, and performs matching as the same time.
-  nsACString::const_iterator start, end;
-  aWhitelist.BeginReading(start);
-  aWhitelist.EndReading(end);
-
-  nsAutoCString pageURI(aPageURI);
-  nsAutoCString objectURI(aObjectURI);
-  nsACString::const_iterator pos = start, entryStart, entryEnd;
-  nsACString::const_iterator pagePatternStart, pagePatternEnd;
-  nsACString::const_iterator objectPatternStart, objectPatternEnd;
-  int matchResult;
-  bool matched, didMatching;
-  while (pos != end) {
-    matched = true;
-    didMatching = false;
-    entryStart = pos;
-    // Looking for end of the entry.
-    while (pos != end && *pos != ',') {
-      pos++;
-    }
-    entryEnd = pos;
-    if (entryStart != entryEnd && *entryStart == '@') {
-      // Pattern for aPageURL is found, finding a space or end of the entry.
-      pagePatternStart = entryStart;
-      pagePatternStart++;
-      pagePatternEnd = pagePatternStart;
-      while (pagePatternEnd != entryEnd && *pagePatternEnd != ' ') {
-        pagePatternEnd++;
-      }
-      nsAutoCString pagePattern(Substring(pagePatternStart, pagePatternEnd));
-      matchResult = NS_WildCardMatch(pageURI.get(), pagePattern.get(), true);
-      matched &= matchResult == MATCH;
-      didMatching = true;
-      objectPatternStart = pagePatternEnd;
-    } else {
-      objectPatternStart = entryStart;
-    }
-    while (objectPatternStart != entryEnd && *objectPatternStart == ' ') {
-      objectPatternStart++;
-    }
-    if (objectPatternStart != entryEnd) {
-      // Pattern for aObjectURL is found, removing trailing spaces.
-      objectPatternEnd = entryEnd;
-      --objectPatternEnd;
-      while (objectPatternStart != objectPatternEnd &&
-             *objectPatternEnd == ' ') {
-        objectPatternEnd--;
-      };
-      objectPatternEnd++;
-      nsAutoCString objectPattern(Substring(objectPatternStart,
-                                            objectPatternEnd));
-      matchResult = NS_WildCardMatch(objectURI.get(), objectPattern.get(), true);
-      matched &= matchResult == MATCH;
-      didMatching = true;
-    }
-    // Ignoring match result for empty entries.
-    if (didMatching && matched) {
-      *_retval = true;
-      return NS_OK;
-    }
-    if (pos == end) {
-      break;
-    }
-    pos++;
-  }
-
-  *_retval = false;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
-                                        const nsACString& aObjectURI,
-                                        bool *_retval)
-{
-  return CheckWhitelist(aPageURI, aObjectURI, mWhitelist, _retval);
-}
deleted file mode 100644
--- a/dom/plugins/base/nsPluginPlayPreviewInfo.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsPluginPlayPreviewInfo_h_
-#define nsPluginPlayPreviewInfo_h_
-
-#include "nsString.h"
-#include "nsIPluginHost.h"
-
-class nsPluginPlayPreviewInfo : public nsIPluginPlayPreviewInfo
-{
-  virtual ~nsPluginPlayPreviewInfo();
-
-public:
-   NS_DECL_ISUPPORTS
-   NS_DECL_NSIPLUGINPLAYPREVIEWINFO
-
-  nsPluginPlayPreviewInfo(const char* aMimeType,
-                          bool aIgnoreCTP,
-                          const char* aRedirectURL,
-                          const char* aWhitelist);
-  explicit nsPluginPlayPreviewInfo(const nsPluginPlayPreviewInfo* aSource);
-
-  /** This function checks aPageURI and aObjectURI against the whitelist
-   *  specified in aWhitelist. This is public static function because this
-   *  whitelist checking code needs to be accessed without any instances of
-   *  nsIPluginPlayPreviewInfo. In particular, the Shumway whitelist is
-   *  obtained directly from prefs and compared using this code for telemetry
-   *  purposes.
-   */
-  static nsresult CheckWhitelist(const nsACString& aPageURI,
-                                 const nsACString& aObjectURI,
-                                 const nsACString& aWhitelist,
-                                 bool *_retval);
-
-  nsCString mMimeType;
-  bool      mIgnoreCTP;
-  nsCString mRedirectURL;
-  nsCString mWhitelist;
-};
-
-
-#endif // nsPluginPlayPreviewInfo_h_
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -99,28 +99,24 @@ struct RunnableMethodTraits<PluginInstan
  * We can't use gfxPlatform::CreateDrawTargetForSurface() because calling
  * gfxPlatform::GetPlatform() instantiates the prefs service, and that's not
  * allowed from processes other than the main process. So we have our own
  * version here.
  */
 static RefPtr<DrawTarget>
 CreateDrawTargetForSurface(gfxASurface *aSurface)
 {
-  SurfaceFormat format;
-  if (aSurface->GetContentType() == gfxContentType::ALPHA) {
-    format = SurfaceFormat::A8;
-  } else if (aSurface->GetContentType() == gfxContentType::COLOR) {
-    format = SurfaceFormat::B8G8R8X8;
-  } else {
-    format = SurfaceFormat::B8G8R8A8;
-  }
+  SurfaceFormat format = aSurface->GetSurfaceFormat();
   RefPtr<DrawTarget> drawTarget =
     Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(),
                                              aSurface->GetSize(),
                                              &format);
+  if (!drawTarget) {
+    NS_RUNTIMEABORT("CreateDrawTargetForSurface failed in plugin");
+  }
   aSurface->SetData(&kDrawTarget, drawTarget, nullptr);
   return drawTarget;
 }
 
 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
                                          const nsCString& aMimeType,
                                          const uint16_t& aMode,
                                          const InfallibleTArray<nsCString>& aNames,
@@ -3252,21 +3248,38 @@ PluginInstanceChild::PaintRectToSurface(
                      DrawOptions(1.f, CompositionOp::OP_SOURCE));
         dt->PopClip();
         dt->Flush();
     }
 
     PaintRectToPlatformSurface(plPaintRect, renderSurface);
 
     if (renderSurface != aSurface) {
+      RefPtr<DrawTarget> dt;
+      if (aSurface == mCurrentSurface &&
+          aSurface->GetType() == gfxSurfaceType::Image &&
+          aSurface->GetSurfaceFormat() == SurfaceFormat::B8G8R8X8) {
+        gfxImageSurface* imageSurface = static_cast<gfxImageSurface*>(aSurface);
+        // Bug 1196927 - Reinterpret target surface as BGRA to fill alpha with opaque.
+        // Certain backends (i.e. Skia) may not truly support BGRX formats, so they must
+        // be emulated by filling the alpha channel opaque as if it was BGRA data. Cairo
+        // leaves the alpha zeroed out for BGRX, so we cause Cairo to fill it as opaque
+        // by handling the copy target as a BGRA surface.
+        dt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
+                                              imageSurface->Data(),
+                                              imageSurface->GetSize(),
+                                              imageSurface->Stride(),
+                                              SurfaceFormat::B8G8R8A8);
+      } else {
         // Copy helper surface content to target
-        RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(aSurface);
-        RefPtr<SourceSurface> surface =
-            gfxPlatform::GetSourceSurfaceForSurface(dt, renderSurface);
-        dt->CopySurface(surface, aRect, aRect.TopLeft());
+        dt = CreateDrawTargetForSurface(aSurface);
+      }
+      RefPtr<SourceSurface> surface =
+        gfxPlatform::GetSourceSurfaceForSurface(dt, renderSurface);
+      dt->CopySurface(surface, aRect, aRect.TopLeft());
     }
 }
 
 void
 PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
                                                   gfxASurface* aSurface)
 {
     MOZ_ASSERT(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA,
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -162,36 +162,17 @@ PluginInstanceParent::InitMetadata(const
         return false;
     }
     // Ensure that the src attribute is absolute
     nsRefPtr<nsPluginInstanceOwner> owner = GetOwner();
     if (!owner) {
         return false;
     }
     nsCOMPtr<nsIURI> baseUri(owner->GetBaseURI());
-    nsresult rv = NS_MakeAbsoluteURI(mSrcAttribute, aSrcAttribute, baseUri);
-    if (NS_FAILED(rv)) {
-        return false;
-    }
-    // Check the whitelist
-    nsAutoCString baseUrlSpec;
-    rv = baseUri->GetSpec(baseUrlSpec);
-    if (NS_FAILED(rv)) {
-        return false;
-    }
-    auto whitelist = Preferences::GetCString(kShumwayWhitelistPref);
-    // Empty whitelist is interpreted by CheckWhitelist as "allow everything,"
-    // which is not valid for our use case and should be treated as a failure.
-    if (whitelist.IsEmpty()) {
-        return false;
-    }
-    rv = nsPluginPlayPreviewInfo::CheckWhitelist(baseUrlSpec, mSrcAttribute,
-                                                 whitelist,
-                                                 &mIsWhitelistedForShumway);
-    return NS_SUCCEEDED(rv);
+    return NS_SUCCEEDED(NS_MakeAbsoluteURI(mSrcAttribute, aSrcAttribute, baseUri));
 }
 
 void
 PluginInstanceParent::ActorDestroy(ActorDestroyReason why)
 {
 #if defined(OS_WIN)
     if (why == AbnormalShutdown) {
         // If the plugin process crashes, this is the only
--- a/dom/push/moz.build
+++ b/dom/push/moz.build
@@ -33,15 +33,18 @@ XPCSHELL_TESTS_MANIFESTS += [
 EXPORTS.mozilla.dom += [
     'PushManager.h',
 ]
 
 UNIFIED_SOURCES += [
     'PushManager.cpp',
 ]
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../workers',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/security/SRICheck.cpp
+++ b/dom/security/SRICheck.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SRICheck.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "nsContentUtils.h"
+#include "nsIChannel.h"
 #include "nsICryptoHash.h"
 #include "nsIDocument.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsWhitespaceTokenizer.h"
@@ -36,48 +37,58 @@ namespace mozilla {
 namespace dom {
 
 /**
  * Returns whether or not the sub-resource about to be loaded is eligible
  * for integrity checks. If it's not, the checks will be skipped and the
  * sub-resource will be loaded.
  */
 static nsresult
-IsEligible(nsIURI* aRequestURI, const CORSMode aCORSMode,
+IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode,
            const nsIDocument* aDocument)
 {
-  NS_ENSURE_ARG_POINTER(aRequestURI);
+  NS_ENSURE_ARG_POINTER(aChannel);
   NS_ENSURE_ARG_POINTER(aDocument);
 
-  nsAutoCString requestSpec;
-  nsresult rv = aRequestURI->GetSpec(requestSpec);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec);
-
   // Was the sub-resource loaded via CORS?
   if (aCORSMode != CORS_NONE) {
     SRILOG(("SRICheck::IsEligible, CORS mode"));
     return NS_OK;
   }
 
+  nsCOMPtr<nsIURI> finalURI;
+  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalURI));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIURI> originalURI;
+  rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoCString requestSpec;
+  rv = originalURI->GetSpec(requestSpec);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (MOZ_LOG_TEST(GetSriLog(), mozilla::LogLevel::Debug)) {
+    nsAutoCString documentSpec, finalSpec;
+    aDocument->GetDocumentURI()->GetAsciiSpec(documentSpec);
+    if (finalURI) {
+      finalURI->GetSpec(finalSpec);
+    }
+    SRILOG(("SRICheck::IsEligible, documentURI=%s; requestURI=%s; finalURI=%s",
+            documentSpec.get(), requestSpec.get(), finalSpec.get()));
+  }
+
   // Is the sub-resource same-origin?
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   if (NS_SUCCEEDED(ssm->CheckSameOriginURI(aDocument->GetDocumentURI(),
-                                           aRequestURI, false))) {
+                                           finalURI, false))) {
     SRILOG(("SRICheck::IsEligible, same-origin"));
     return NS_OK;
   }
-  if (MOZ_LOG_TEST(GetSriLog(), mozilla::LogLevel::Debug)) {
-    nsAutoCString documentURI;
-    aDocument->GetDocumentURI()->GetAsciiSpec(documentURI);
-    // documentURI will be empty if GetAsciiSpec failed
-    SRILOG(("SRICheck::IsEligible, NOT same origin: documentURI=%s; requestURI=%s",
-            documentURI.get(), requestSpec.get()));
-  }
+  SRILOG(("SRICheck::IsEligible, NOT same origin"));
 
+  NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec);
   const char16_t* params[] = { requestSpecUTF16.get() };
   nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
                                   NS_LITERAL_CSTRING("Sub-resource Integrity"),
                                   aDocument,
                                   nsContentUtils::eSECURITY_PROPERTIES,
                                   "IneligibleResource",
                                   params, ArrayLength(params));
   return NS_ERROR_SRI_NOT_ELIGIBLE;
@@ -222,49 +233,53 @@ SRICheck::IntegrityMetadata(const nsAStr
       SRILOG(("SRICheck::IntegrityMetadata, no valid metadata found"));
     }
   }
   return NS_OK;
 }
 
 /* static */ nsresult
 SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
-                          nsIURI* aRequestURI,
+                          nsIChannel* aChannel,
                           const CORSMode aCORSMode,
                           const nsAString& aString,
                           const nsIDocument* aDocument)
 {
   NS_ConvertUTF16toUTF8 utf8Hash(aString);
-  return VerifyIntegrity(aMetadata, aRequestURI, aCORSMode, utf8Hash.Length(),
+  return VerifyIntegrity(aMetadata, aChannel, aCORSMode, utf8Hash.Length(),
                          (uint8_t*)utf8Hash.get(), aDocument);
 }
 
 /* static */ nsresult
 SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
-                          nsIURI* aRequestURI,
+                          nsIChannel* aChannel,
                           const CORSMode aCORSMode,
                           uint32_t aStringLen,
                           const uint8_t* aString,
                           const nsIDocument* aDocument)
 {
   if (MOZ_LOG_TEST(GetSriLog(), mozilla::LogLevel::Debug)) {
     nsAutoCString requestURL;
-    aRequestURI->GetAsciiSpec(requestURL);
-    // requestURL will be empty if GetAsciiSpec fails
+    nsCOMPtr<nsIURI> originalURI;
+    if (NS_SUCCEEDED(aChannel->GetOriginalURI(getter_AddRefs(originalURI))) &&
+        originalURI) {
+      originalURI->GetAsciiSpec(requestURL);
+      // requestURL will be empty if GetAsciiSpec fails
+    }
     SRILOG(("SRICheck::VerifyIntegrity, url=%s (length=%u)",
             requestURL.get(), aStringLen));
   }
 
   MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller
 
   // IntegrityMetadata() checks this and returns "no metadata" if
   // it's disabled so we should never make it this far
   MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
 
-  if (NS_FAILED(IsEligible(aRequestURI, aCORSMode, aDocument))) {
+  if (NS_FAILED(IsEligible(aChannel, aCORSMode, aDocument))) {
     return NS_OK; // ignore non-CORS resources for forward-compatibility
   }
   if (!aMetadata.IsValid()) {
     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                     NS_LITERAL_CSTRING("Sub-resource Integrity"),
                                     aDocument,
                                     nsContentUtils::eSECURITY_PROPERTIES,
                                     "NoValidMetadata");
--- a/dom/security/SRICheck.h
+++ b/dom/security/SRICheck.h
@@ -6,18 +6,18 @@
 
 #ifndef mozilla_dom_SRICheck_h
 #define mozilla_dom_SRICheck_h
 
 #include "mozilla/CORSMode.h"
 #include "nsCOMPtr.h"
 #include "SRIMetadata.h"
 
+class nsIChannel;
 class nsIDocument;
-class nsIHttpChannel;
 class nsIScriptSecurityManager;
 class nsIStreamLoader;
 class nsIURI;
 
 namespace mozilla {
 namespace dom {
 
 class SRICheck final
@@ -34,27 +34,27 @@ public:
                                     const nsIDocument* aDocument,
                                     SRIMetadata* outMetadata);
 
   /**
    * Process the integrity attribute of the element.  A result of false
    * must prevent the resource from loading.
    */
   static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
-                                  nsIURI* aRequestURI,
+                                  nsIChannel* aChannel,
                                   const CORSMode aCORSMode,
                                   const nsAString& aString,
                                   const nsIDocument* aDocument);
 
   /**
    * Process the integrity attribute of the element.  A result of false
    * must prevent the resource from loading.
    */
   static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
-                                  nsIURI* aRequestURI,
+                                  nsIChannel* aChannel,
                                   const CORSMode aCORSMode,
                                   uint32_t aStringLen,
                                   const uint8_t* aString,
                                   const nsIDocument* aDocument);
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/security/nsCORSListenerProxy.cpp
+++ b/dom/security/nsCORSListenerProxy.cpp
@@ -543,16 +543,28 @@ nsCORSListenerProxy::CheckRequestApprove
 
   // Test that things worked on a HTTP level
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
   if (!http) {
     LogBlockedRequest(aRequest, "CORSRequestNotHttp", nullptr);
     return NS_ERROR_DOM_BAD_URI;
   }
 
+  nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(aRequest);
+  NS_ENSURE_STATE(internal);
+  bool responseSynthesized = false;
+  if (NS_SUCCEEDED(internal->GetResponseSynthesized(&responseSynthesized)) &&
+      responseSynthesized) {
+    // For synthesized responses, we don't need to perform any checks.
+    // Note: This would be unsafe if we ever changed our behavior to allow
+    // service workers to intercept CORS preflights.
+    MOZ_ASSERT(!mIsPreflight);
+    return NS_OK;
+  }
+
   // Check the Access-Control-Allow-Origin header
   nsAutoCString allowedOriginHeader;
   rv = http->GetResponseHeader(
     NS_LITERAL_CSTRING("Access-Control-Allow-Origin"), allowedOriginHeader);
   if (NS_FAILED(rv)) {
     LogBlockedRequest(aRequest, "CORSMissingAllowOrigin", nullptr);
     return rv;
   }
@@ -1320,16 +1332,21 @@ NS_StartCORSPreflight(nsIChannel* aReque
   NS_ASSERTION(preHttp, "Failed to QI to nsIHttpChannel!");
 
   rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Preflight requests should never be intercepted by service workers.
   nsCOMPtr<nsIHttpChannelInternal> preInternal = do_QueryInterface(preflightChannel);
   if (preInternal) {
+    // NOTE: We ignore CORS checks on synthesized responses (see the CORS
+    // preflights, then we need to extend the GetResponseSynthesized() check in
+    // nsCORSListenerProxy::CheckRequestApproved()). If we change our behavior
+    // here and allow service workers to intercept CORS preflights, then that
+    // check won't be safe any more.
     preInternal->ForceNoIntercept();
   }
   
   // Set up listener which will start the original channel
   nsCOMPtr<nsIStreamListener> preflightListener =
     new nsCORSPreflightListener(aRequestChannel, aListener, nullptr, aPrincipal,
                                 method, aWithCredentials);
   NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);
--- a/dom/security/test/sri/iframe_script_crossdomain.html
+++ b/dom/security/test/sri/iframe_script_crossdomain.html
@@ -39,16 +39,30 @@
   function bad_onloadCalled() {
     window.onloadCalled = true;
   }
 
   function good_onerrorCalled() {
     window.onerrorCalled = true;
   }
 
+  function good_incorrect301Loaded() {
+    ok(true, "A non-CORS load redirected to a different origin was loaded correctly despite an incorrect hash value.");
+  }
+  function bad_incorrect301Blocked() {
+    ok(false, "Non-CORS loads redirecting to a different origin should be loaded despite an incorrect hash value!");
+  }
+
+  function good_correct301Loaded() {
+    ok(true, "A non-CORS load redirected to a different origin was loaded correctly.");
+  }
+  function bad_correct301Blocked() {
+    ok(false, "Non-CORS loads redirecting to a different origin should be loaded!");
+  }
+
   window.onload = function() {
     SimpleTest.finish()
   }
 </script>
 
 <!-- cors-enabled. should be loaded -->
 <script src="http://example.com/tests/dom/security/test/sri/script_crossdomain1.js"
         crossorigin=""
@@ -68,16 +82,28 @@
         onerror="bad_nonsriBlocked()"></script>
 
 <!-- non-cors with invalid metadata. should trigger onload -->
 <script src="http://example.com/tests/dom/security/test/sri/script_crossdomain4.js"
         integrity="sha256-bogus"
         onload="good_nonCORSInvalidLoaded()"
         onerror="bad_nonCORSInvalidBlocked()"></script>
 
+<!-- non-cors that's same-origin initially but redirected to another origin -->
+<script src="script_301.js"
+        integrity="sha384-invalid"
+        onerror="bad_incorrect301Blocked()"
+        onload="good_incorrect301Loaded()"></script>
+
+<!-- non-cors that's same-origin initially but redirected to another origin -->
+<script src="script_301.js"
+        integrity="sha384-1NpiDI6decClMaTWSCAfUjTdx1BiOffsCPgH4lW5hCLwmHk0VyV/g6B9Sw2kD2K3"
+        onerror="bad_correct301Blocked()"
+        onload="good_correct301Loaded()"></script>
+
 <script>
   ok(window.hasCORSLoaded, "CORS-enabled resource with a correct hash");
   ok(!window.hasNonCORSLoaded, "Correct hash, but non-CORS, should be blocked");
   ok(!window.onloadCalled, "Failed loads should not call onload when they're cross-domain");
   ok(window.onerrorCalled, "Failed loads should call onerror when they're cross-domain");
 </script>
 </body>
 </html>
copy from dom/security/test/sri/iframe_style_sameorigin.html
copy to dom/security/test/sri/iframe_style_crossdomain.html
--- a/dom/security/test/sri/iframe_style_sameorigin.html
+++ b/dom/security/test/sri/iframe_style_crossdomain.html
@@ -1,74 +1,51 @@
 <!DOCTYPE HTML>
 <!-- Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/ -->
 <html>
 <head>
   <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">
-    function check_styles() {
-      var redText = document.getElementById('red-text');
-      var blackText = document.getElementById('black-text');
-      var redTextColor = window.getComputedStyle(redText, null).getPropertyValue('color');
-      var blackTextColor = window.getComputedStyle(blackText, null).getPropertyValue('color');
-      ok(redTextColor == 'rgb(255, 0, 0)', "The first part should be red.");
-      ok(blackTextColor == 'rgb(0, 0, 0)', "The second part should still be black.");
-    }
-
     SimpleTest.waitForExplicitFinish();
     window.onload = function() {
-      check_styles();
       SimpleTest.finish();
     }
   </script>
   <script>
     function good_correctHashLoaded() {
-      ok(true, "A stylesheet was correctly loaded when integrity matched");
+      ok(true, "A non-CORS cross-domain stylesheet was correctly loaded when integrity matched.");
     }
     function bad_correctHashBlocked() {
-      ok(false, "We should load stylesheets with hashes that match!");
+      ok(false, "We should load non-CORS cross-domain stylesheets with hashes that match!");
     }
 
-    function good_emptyIntegrityLoaded() {
-      ok(true, "A stylesheet was correctly loaded when the integrity attribute was empty");
+    function good_incorrectHashLoaded() {
+      ok(true, "A non-CORS cross-domain stylesheet was correctly loaded even when integrity didn't match.");
     }
-    function bad_emptyIntegrityBlocked() {
-      ok(false, "We should load stylesheets with empty integrity attributes!");
+    function bad_incorrectHashBlocked() {
+      ok(false, "We should load non-CORS cross-domain stylesheets even when hashes don't match!");
     }
 
-    function good_incorrectHashBlocked() {
-      ok(true, "A stylesheet was correctly blocked, because the hash digest was wrong");
-    }
-    function bad_incorrectHashLoaded() {
-      ok(false, "We should not load stylesheets with hashes that do not match the content!");
-    }
   </script>
 
-  <!-- valid sha256 hash. should trigger onload -->
-  <link rel="stylesheet" href="style1.css"
+  <!-- valid non-CORS sha256 hash. should trigger onload -->
+  <link rel="stylesheet" href="style_301.css"
         integrity="sha256-qs8lnkunWoVldk5d5E+652yth4VTSHohlBKQvvgGwa8="
         onerror="bad_correctHashBlocked()"
         onload="good_correctHashLoaded()">
 
-  <!-- empty metadata. should trigger onload -->
-  <link rel="stylesheet" href="style2.css"
-        integrity=""
-        onerror="bad_emptyIntegrityBlocked()"
-        onload="good_emptyIntegrityLoaded()">
-
-  <!-- invalid sha256 hash. should trigger onerror -->
-  <link rel="stylesheet" href="style3.css"
+  <!-- invalid non-CORS sha256 hash. should trigger onload -->
+  <link rel="stylesheet" href="style_301.css?again"
         integrity="sha256-bogus"
-        onerror="good_incorrectHashBlocked()"
-        onload="bad_incorrectHashLoaded()">
+        onerror="bad_incorrectHashBlocked()"
+        onload="good_incorrectHashLoaded()">
 </head>
 <body>
-<p><span id="red-text">This should be red </span> and
-  <span id="black-text">this should stay black.</p>
+<p><span id="red-text">This should be red.</span></p>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 </pre>
 </body>
 </html>
--- a/dom/security/test/sri/mochitest.ini
+++ b/dom/security/test/sri/mochitest.ini
@@ -1,30 +1,35 @@
 [DEFAULT]
 support-files =
   iframe_script_crossdomain.html
   iframe_script_sameorigin.html
   iframe_sri_disabled.html
+  iframe_style_crossdomain.html
   iframe_style_sameorigin.html
   script_crossdomain1.js
   script_crossdomain1.js^headers^
   script_crossdomain2.js
   script_crossdomain3.js
   script_crossdomain3.js^headers^
   script_crossdomain4.js
   script_crossdomain4.js^headers^
+  script_crossdomain5.js
+  script_crossdomain5.js^headers^
   script.js
   script.js^headers^
+  script_301.js
+  script_301.js^headers^
   script_302.js
   script_302.js^headers^
   script_401.js
   script_401.js^headers^
   style1.css
   style2.css
   style3.css
+  style_301.css
+  style_301.css^headers^
 
 [test_script_sameorigin.html]
-
 [test_script_crossdomain.html]
-
 [test_sri_disabled.html]
-
+[test_style_crossdomain.html]
 [test_style_sameorigin.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_301.js
@@ -0,0 +1,1 @@
+var load=false;
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_301.js^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: http://example.com/tests/dom/security/test/sri/script_crossdomain5.js
copy from dom/security/test/sri/script_crossdomain4.js
copy to dom/security/test/sri/script_crossdomain5.js
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain5.js^headers^
@@ -0,0 +1,1 @@
+Access-Control-Allow-Origin: *
copy from dom/security/test/sri/style1.css
copy to dom/security/test/sri/style_301.css
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/style_301.css^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: http://example.com/tests/dom/security/test/sri/style1.css
copy from dom/security/test/sri/test_style_sameorigin.html
copy to dom/security/test/sri/test_style_crossdomain.html
--- a/dom/security/test/sri/test_style_sameorigin.html
+++ b/dom/security/test/sri/test_style_crossdomain.html
@@ -1,18 +1,18 @@
 <!DOCTYPE HTML>
 <!-- Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/ -->
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Same-origin stylesheet tests for Bug 992096</title>
+  <title>Cross-domain stylesheet tests for Bug 1196740</title>
   <script>
     SpecialPowers.setBoolPref("security.sri.enable", true);
   </script>
 </head>
 <body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096">Mozilla Bug 992096</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196740">Mozilla Bug 1196740</a>
 <div>
-  <iframe src="iframe_style_sameorigin.html" height="100%" width="90%" frameborder="0"></iframe>
+  <iframe src="iframe_style_crossdomain.html" height="100%" width="90%" frameborder="0"></iframe>
 </div>
 </body>
 </html>
--- a/dom/smil/TimeEvent.cpp
+++ b/dom/smil/TimeEvent.cpp
@@ -12,17 +12,17 @@
 
 namespace mozilla {
 namespace dom {
 
 TimeEvent::TimeEvent(EventTarget* aOwner,
                      nsPresContext* aPresContext,
                      InternalSMILTimeEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalSMILTimeEvent(false, 0))
+          aEvent ? aEvent : new InternalSMILTimeEvent(false, NS_EVENT_NULL))
   , mDetail(mEvent->AsSMILTimeEvent()->detail)
 {
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
   }
 
--- a/dom/smil/nsSMILTimedElement.cpp
+++ b/dom/smil/nsSMILTimedElement.cpp
@@ -77,22 +77,25 @@ nsSMILTimedElement::InstanceTimeComparat
 // Helper class: AsyncTimeEventRunner
 
 namespace
 {
   class AsyncTimeEventRunner : public nsRunnable
   {
   protected:
     nsRefPtr<nsIContent> mTarget;
-    uint32_t             mMsg;
+    EventMessage         mMsg;
     int32_t              mDetail;
 
   public:
-    AsyncTimeEventRunner(nsIContent* aTarget, uint32_t aMsg, int32_t aDetail)
-      : mTarget(aTarget), mMsg(aMsg), mDetail(aDetail)
+    AsyncTimeEventRunner(nsIContent* aTarget, EventMessage aMsg,
+                         int32_t aDetail)
+      : mTarget(aTarget)
+      , mMsg(aMsg)
+      , mDetail(aDetail)
     {
     }
 
     NS_IMETHOD Run()
     {
       InternalSMILTimeEvent event(true, mMsg);
       event.detail = mDetail;
 
@@ -2360,17 +2363,17 @@ nsSMILTimedElement::NotifyChangedInterva
 
   for (uint32_t i = 0; i < times.Length(); ++i) {
     times[i]->HandleChangedInterval(container, aBeginObjectChanged,
                                     aEndObjectChanged);
   }
 }
 
 void
-nsSMILTimedElement::FireTimeEventAsync(uint32_t aMsg, int32_t aDetail)
+nsSMILTimedElement::FireTimeEventAsync(EventMessage aMsg, int32_t aDetail)
 {
   if (!mAnimationElement)
     return;
 
   nsCOMPtr<nsIRunnable> event =
     new AsyncTimeEventRunner(mAnimationElement, aMsg, aDetail);
   NS_DispatchToMainThread(event);
 }
--- a/dom/smil/nsSMILTimedElement.h
+++ b/dom/smil/nsSMILTimedElement.h
@@ -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/. */
 
 #ifndef NS_SMILTIMEDELEMENT_H_
 #define NS_SMILTIMEDELEMENT_H_
 
+#include "mozilla/EventForwards.h"
 #include "mozilla/Move.h"
 #include "nsSMILInterval.h"
 #include "nsSMILInstanceTime.h"
 #include "nsSMILMilestone.h"
 #include "nsSMILTimeValueSpec.h"
 #include "nsSMILRepeatCount.h"
 #include "nsSMILTypes.h"
 #include "nsTArray.h"
@@ -534,17 +535,18 @@ protected:
   //      a consistent state to receive callbacks, and
   // (ii) after calling these methods we must assume that the state of the
   //      element may have changed.
   void              NotifyNewInterval();
   void              NotifyChangedInterval(nsSMILInterval* aInterval,
                                           bool aBeginObjectChanged,
                                           bool aEndObjectChanged);
 
-  void              FireTimeEventAsync(uint32_t aMsg, int32_t aDetail);
+  void              FireTimeEventAsync(mozilla::EventMessage aMsg,
+                                       int32_t aDetail);
   const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
   const nsSMILInterval* GetPreviousInterval() const;
   bool              HasPlayed() const { return !mOldIntervals.IsEmpty(); }
   bool              HasClientInFillRange() const;
   bool              EndHasEventConditions() const;
   bool              AreEndTimesDependentOn(
                       const nsSMILInstanceTime* aBase) const;
 
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -465,17 +465,17 @@ void
 SVGSVGElement::SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv)
 {
   if (aZoomAndPan == SVG_ZOOMANDPAN_DISABLE ||
       aZoomAndPan == SVG_ZOOMANDPAN_MAGNIFY) {
     mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this);
     return;
   }
 
-  rv.ThrowRangeError(MSG_INVALID_ZOOMANDPAN_VALUE_ERROR, &aZoomAndPan);
+  rv.ThrowRangeError(MSG_INVALID_ZOOMANDPAN_VALUE_ERROR);
 }
 
 //----------------------------------------------------------------------
 // helper methods for implementing SVGZoomEvent:
 
 void
 SVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y)
 {
--- a/dom/tests/mochitest/fetch/test_fetch_cors.js
+++ b/dom/tests/mochitest/fetch/test_fetch_cors.js
@@ -734,20 +734,23 @@ function testModeCors() {
       req.url += "&preflightStatus=" + test.preflightStatus;
     if (test.responseHeaders)
       req.url += "&responseHeaders=" + escape(test.responseHeaders.toSource());
     if (test.exposeHeaders)
       req.url += "&exposeHeaders=" + escape(test.exposeHeaders);
     if (test.preflightBody)
       req.url += "&preflightBody=" + escape(test.preflightBody);
 
-    var request = new Request(req.url, { method: req.method, mode: "cors",
-                                         headers: req.headers, body: req.body });
-    fetches.push((function(test, request) {
-      return fetch(request).then(function(res) {
+    fetches.push((function(test) {
+      return new Promise(function(resolve) {
+        resolve(new Request(req.url, { method: req.method, mode: "cors",
+                                         headers: req.headers, body: req.body }));
+      }).then(function(request) {
+        return fetch(request);
+      }).then(function(res) {
         ok(test.pass, "Expected test to pass for " + test.toSource());
         if (test.status) {
           is(res.status, test.status, "wrong status in test for " + test.toSource());
           is(res.statusText, test.statusMessage, "wrong status text for " + test.toSource());
         }
         else {
           is(res.status, 200, "wrong status in test for " + test.toSource());
           is(res.statusText, "OK", "wrong status text for " + test.toSource());
@@ -762,31 +765,31 @@ function testModeCors() {
             else {
               is(res.headers.get(header), test.responseHeaders[header],
                  "|Headers.get()|wrong response header (" + header + ") in test for " +
                  test.toSource());
             }
           }
         }
 
-        return res.text().then(function(v) {
-          if (test.method !== "HEAD") {
-            is(v, "<res>hello pass</res>\n",
-               "wrong responseText in test for " + test.toSource());
-          }
-          else {
-            is(v, "",
-               "wrong responseText in HEAD test for " + test.toSource());
-          }
-        });
-      }, function(e) {
-          ok(!test.pass, "Expected test failure for " + test.toSource());
-          ok(e instanceof TypeError, "Exception should be TypeError for " + test.toSource());
+        return res.text();
+      }).then(function(v) {
+        if (test.method !== "HEAD") {
+          is(v, "<res>hello pass</res>\n",
+             "wrong responseText in test for " + test.toSource());
+        }
+        else {
+          is(v, "",
+             "wrong responseText in HEAD test for " + test.toSource());
+        }
+      }).catch(function(e) {
+        ok(!test.pass, "Expected test failure for " + test.toSource());
+        ok(e instanceof TypeError, "Exception should be TypeError for " + test.toSource());
       });
-    })(test, request));
+    })(test));
   }
 
   return Promise.all(fetches);
 }
 
 function testCrossOriginCredentials() {
   var tests = [
            { pass: 1,
--- a/dom/tests/mochitest/fetch/test_request.js
+++ b/dom/tests/mochitest/fetch/test_request.js
@@ -214,16 +214,41 @@ function testMethod() {
   var r = new Request("", { method: "patch", body: "hello" });
 }
 
 function testUrlFragment() {
   var req = new Request("./request#withfragment");
   is(req.url, (new URL("./request", self.location.href)).href, "request.url should be serialized with exclude fragment flag set");
 }
 
+function testUrlMalformed() {
+  try {
+    var req = new Request("http:// example.com");
+    ok(false, "Creating a Request with a malformed URL should throw a TypeError");
+  } catch(e) {
+    is(e.name, "TypeError", "Creating a Request with a malformed URL should throw a TypeError");
+  }
+}
+
+function testUrlCredentials() {
+  try {
+    var req = new Request("http://user@example.com");
+    ok(false, "URLs with credentials should be rejected");
+  } catch(e) {
+    is(e.name, "TypeError", "URLs with credentials should be rejected");
+  }
+
+  try {
+    var req = new Request("http://user:password@example.com");
+    ok(false, "URLs with credentials should be rejected");
+  } catch(e) {
+    is(e.name, "TypeError", "URLs with credentials should be rejected");
+  }
+}
+
 function testBodyUsed() {
   var req = new Request("./bodyused", { method: 'post', body: "Sample body" });
   is(req.bodyUsed, false, "bodyUsed is initially false.");
   return req.text().then((v) => {
     is(v, "Sample body", "Body should match");
     is(req.bodyUsed, true, "After reading body, bodyUsed should be true.");
   }).then((v) => {
     return req.blob().then((v) => {
@@ -466,16 +491,18 @@ function testRequestConsumedByFailedCons
   }
   ok(!r1.bodyUsed, 'Initial request should not be consumed by failed Request constructor');
 }
 
 function runTest() {
   testDefaultCtor();
   testSimpleUrlParse();
   testUrlFragment();
+  testUrlCredentials();
+  testUrlMalformed();
   testMethod();
   testBug1109574();
   testHeaderGuard();
   testModeCorsPreflightEnumValue();
   testBug1154268();
   testRequestConsumedByFailedConstructor();
 
   return Promise.resolve()
--- a/dom/webidl/HTMLObjectElement.webidl
+++ b/dom/webidl/HTMLObjectElement.webidl
@@ -124,19 +124,16 @@ interface MozObjectLoadingContent {
   [ChromeOnly]
   const unsigned long PLUGIN_CLICK_TO_PLAY        = 8;
   // The plugin is vulnerable (update available)
   [ChromeOnly]
   const unsigned long PLUGIN_VULNERABLE_UPDATABLE = 9;
   // The plugin is vulnerable (no update available)
   [ChromeOnly]
   const unsigned long PLUGIN_VULNERABLE_NO_UPDATE = 10;
-  // The plugin is in play preview mode
-  [ChromeOnly]
-  const unsigned long PLUGIN_PLAY_PREVIEW         = 11;
 
   /**
    * The actual mime type (the one we got back from the network
    * request) for the element.
    */
   [ChromeOnly]
   readonly attribute DOMString actualType;
 
@@ -158,35 +155,35 @@ interface MozObjectLoadingContent {
 
   [ChromeOnly]
   sequence<MozPluginParameter> getPluginAttributes();
 
   [ChromeOnly]
   sequence<MozPluginParameter> getPluginParameters();
 
   /**
-   * This method will play a plugin that has been stopped by the
-   * click-to-play plugins or play-preview features.
+   * This method will play a plugin that has been stopped by the click-to-play
+   * feature.
    */
   [ChromeOnly, Throws]
   void playPlugin();
 
   /**
    * Forces a re-evaluation and reload of the tag, optionally invalidating its
    * click-to-play state.  This can be used when the MIME type that provides a
    * type has changed, for instance, to force the tag to re-evalulate the
    * handler to use.
    */
   [ChromeOnly, Throws]
   void reload(boolean aClearActivation);
 
   /**
    * This attribute will return true if the current content type has been
    * activated, either explicitly or by passing checks that would have it be
-   * click-to-play or play-preview.
+   * click-to-play.
    */
   [ChromeOnly]
   readonly attribute boolean activated;
 
   /**
    * The URL of the data/src loaded in the object. This may be null (i.e.
    * an <embed> with no src).
    */
@@ -201,22 +198,16 @@ interface MozObjectLoadingContent {
 
   /**
    * If this object currently owns a running plugin, regardless of whether or
    * not one is pending spawn/despawn.
    */
   [ChromeOnly]
   readonly attribute boolean hasRunningPlugin;
 
-  /**
-   * This method will disable the play-preview plugin state.
-   */
-  [ChromeOnly, Throws]
-  void cancelPlayPreview();
-
   [ChromeOnly, Throws]
   readonly attribute unsigned long runID;
 };
 
 /**
  * Name:Value pair type used for passing parameters to NPAPI or javascript
  * plugins.
  */
--- a/dom/workers/ServiceWorkerContainer.cpp
+++ b/dom/workers/ServiceWorkerContainer.cpp
@@ -3,16 +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/. */
 
 #include "ServiceWorkerContainer.h"
 
 #include "nsIDocument.h"
 #include "nsIServiceWorkerManager.h"
+#include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsServiceManagerUtils.h"
 
@@ -95,16 +96,43 @@ ServiceWorkerContainer::RemoveReadyPromi
 }
 
 JSObject*
 ServiceWorkerContainer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return ServiceWorkerContainerBinding::Wrap(aCx, this, aGivenProto);
 }
 
+static nsresult
+CheckForSlashEscapedCharsInPath(nsIURI* aURI)
+{
+  MOZ_ASSERT(aURI);
+
+  // A URL that can't be downcast to a standard URL is an invalid URL and should
+  // be treated as such and fail with SecurityError.
+  nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
+  if (NS_WARN_IF(!url)) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsAutoCString path;
+  nsresult rv = url->GetFilePath(path);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  ToLowerCase(path);
+  if (path.Find("%2f") != kNotFound ||
+      path.Find("%5c") != kNotFound) {
+    return NS_ERROR_DOM_TYPE_ERR;
+  }
+
+  return NS_OK;
+}
+
 already_AddRefed<Promise>
 ServiceWorkerContainer::Register(const nsAString& aScriptURL,
                                  const RegistrationOptions& aOptions,
                                  ErrorResult& aRv)
 {
   nsCOMPtr<nsISupports> promise;
 
   nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
@@ -139,16 +167,21 @@ ServiceWorkerContainer::Register(const n
   nsresult rv;
   nsCOMPtr<nsIURI> scriptURI;
   rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptURL, nullptr, baseURI);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aRv.ThrowTypeError(MSG_INVALID_URL, &aScriptURL);
     return nullptr;
   }
 
+  aRv = CheckForSlashEscapedCharsInPath(scriptURI);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+
   // In ServiceWorkerContainer.register() the scope argument is parsed against
   // different base URLs depending on whether it was passed or not.
   nsCOMPtr<nsIURI> scopeURI;
 
   // Step 4. If none passed, parse against script's URL
   if (!aOptions.mScope.WasPassed()) {
     NS_NAMED_LITERAL_STRING(defaultScope, "./");
     rv = NS_NewURI(getter_AddRefs(scopeURI), defaultScope,
@@ -166,16 +199,21 @@ ServiceWorkerContainer::Register(const n
                    nullptr, baseURI);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       nsAutoCString spec;
       baseURI->GetSpec(spec);
       NS_ConvertUTF8toUTF16 wSpec(spec);
       aRv.ThrowTypeError(MSG_INVALID_SCOPE, &aOptions.mScope.Value(), &wSpec);
       return nullptr;
     }
+
+    aRv = CheckForSlashEscapedCharsInPath(scopeURI);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return nullptr;
+    }
   }
 
   // The spec says that the "client" passed to Register() must be the global
   // where the ServiceWorkerContainer was retrieved from.
   nsCOMPtr<nsPIDOMWindow> window = GetOwner();
   MOZ_ASSERT(window);
   aRv = swm->Register(window, scopeURI, scriptURI, getter_AddRefs(promise));
   if (aRv.Failed()) {
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -569,17 +569,17 @@ public:
 
   void
   UpdateFailed(nsresult aStatus) override
   {
     mPromise->MaybeReject(aStatus);
   }
 
   void
-  UpdateFailed(const ErrorEventInit& aErrorDesc) override
+  UpdateFailed(JSExnType aExnType, const ErrorEventInit& aErrorDesc) override
   {
     AutoJSAPI jsapi;
     jsapi.Init(mWindow);
 
     JSContext* cx = jsapi.cx();
 
     JS::Rooted<JS::Value> fnval(cx);
     if (!ToJSValue(cx, aErrorDesc.mFilename, &fnval)) {
@@ -593,17 +593,18 @@ public:
     if (!ToJSValue(cx, aErrorDesc.mMessage, &msgval)) {
       JS_ClearPendingException(cx);
       mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
       return;
     }
     JS::Rooted<JSString*> msg(cx, msgval.toString());
 
     JS::Rooted<JS::Value> error(cx);
-    if (!JS::CreateError(cx, JSEXN_ERR, nullptr, fn, aErrorDesc.mLineno,
+    if ((aExnType < JSEXN_ERR) ||
+        !JS::CreateError(cx, aExnType, nullptr, fn, aErrorDesc.mLineno,
                          aErrorDesc.mColno, nullptr, msg, &error)) {
       JS_ClearPendingException(cx);
       mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
       return;
     }
 
     mPromise->MaybeReject(cx, error);
   }
@@ -970,23 +971,27 @@ public:
   }
 
   void
   ComparisonResult(nsresult aStatus, bool aInCacheAndEqual,
                    const nsAString& aNewCacheName,
                    const nsACString& aMaxScope) override
   {
     nsRefPtr<ServiceWorkerRegisterJob> kungFuDeathGrip = this;
-    if (mCanceled) {
+    if (NS_WARN_IF(mCanceled)) {
       Fail(NS_ERROR_DOM_TYPE_ERR);
       return;
     }
 
     if (NS_WARN_IF(NS_FAILED(aStatus))) {
-      Fail(NS_ERROR_DOM_TYPE_ERR);
+      if (aStatus == NS_ERROR_DOM_SECURITY_ERR) {
+        Fail(aStatus);
+      } else {
+        Fail(NS_ERROR_DOM_TYPE_ERR);
+      }
       return;
     }
 
     if (aInCacheAndEqual) {
       Succeed();
       Done(NS_OK);
       return;
     }
@@ -1096,27 +1101,27 @@ public:
       data->mSetOfScopesBeingUpdated.Remove(aScopeKey);
     }
     Fail(NS_ERROR_DOM_ABORT_ERR);
   }
 
   // Public so our error handling code can use it.
   // Callers MUST hold a strong ref before calling this!
   void
-  Fail(const ErrorEventInit& aError)
+  Fail(JSExnType aExnType, const ErrorEventInit& aError)
   {
     MOZ_ASSERT(mCallback);
     nsRefPtr<ServiceWorkerUpdateFinishCallback> callback = mCallback.forget();
     // With cancellation support, we may only be running with one reference
     // from another object like a stream loader or something.
     // UpdateFailed may do something with that, so hold a ref to ourself since
     // FailCommon relies on it.
     // FailCommon does check for cancellation, but let's be safe here.
     nsRefPtr<ServiceWorkerRegisterJob> kungFuDeathGrip = this;
-    callback->UpdateFailed(aError);
+    callback->UpdateFailed(aExnType, aError);
     FailCommon(NS_ERROR_DOM_JS_EXCEPTION);
   }
 
   // Public so our error handling code can continue with a successful worker.
   void
   ContinueInstall()
   {
     // mRegistration will be null if we have already Fail()ed.
@@ -2922,17 +2927,18 @@ ServiceWorkerManager::HandleError(JSCont
                                   nsIPrincipal* aPrincipal,
                                   const nsCString& aScope,
                                   const nsString& aWorkerURL,
                                   nsString aMessage,
                                   nsString aFilename,
                                   nsString aLine,
                                   uint32_t aLineNumber,
                                   uint32_t aColumnNumber,
-                                  uint32_t aFlags)
+                                  uint32_t aFlags,
+                                  JSExnType aExnType)
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(!JSREPORT_IS_WARNING(aFlags));
 
   nsAutoCString scopeKey;
   nsresult rv = PrincipalToScopeKey(aPrincipal, scopeKey);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -2962,17 +2968,17 @@ ServiceWorkerManager::HandleError(JSCont
     init.mFilename = aFilename;
     init.mLineno = aLineNumber;
     init.mColno = aColumnNumber;
 
   NS_WARNING(nsPrintfCString(
               "Script error caused ServiceWorker registration to fail: %s:%u '%s'",
               NS_ConvertUTF16toUTF8(aFilename).get(), aLineNumber,
               NS_ConvertUTF16toUTF8(aMessage).get()).get());
-    regJob->Fail(init);
+    regJob->Fail(aExnType, init);
   }
 
   return true;
 }
 
 void
 ServiceWorkerRegistrationInfo::FinishActivate(bool aSuccess)
 {
--- a/dom/workers/ServiceWorkerManager.h
+++ b/dom/workers/ServiceWorkerManager.h
@@ -143,17 +143,17 @@ public:
   void UpdateSucceeded(ServiceWorkerRegistrationInfo* aInfo)
   { }
 
   virtual
   void UpdateFailed(nsresult aStatus)
   { }
 
   virtual
-  void UpdateFailed(const ErrorEventInit& aDesc)
+  void UpdateFailed(JSExnType aExnType, const ErrorEventInit& aDesc)
   { }
 };
 
 /*
  * Wherever the spec treats a worker instance and a description of said worker
  * as the same thing; i.e. "Resolve foo with
  * _GetNewestWorker(serviceWorkerRegistration)", we represent the description
  * by this class and spawn a ServiceWorker in the right global when required.
@@ -370,17 +370,18 @@ public:
               nsIPrincipal* aPrincipal,
               const nsCString& aScope,
               const nsString& aWorkerURL,
               nsString aMessage,
               nsString aFilename,
               nsString aLine,
               uint32_t aLineNumber,
               uint32_t aColumnNumber,
-              uint32_t aFlags);
+              uint32_t aFlags,
+              JSExnType aExnType);
 
   void
   GetAllClients(nsIPrincipal* aPrincipal,
                 const nsCString& aScope,
                 nsTArray<ServiceWorkerClientInfo>& aControlledDocuments);
 
   void
   MaybeClaimClient(nsIDocument* aDocument,
--- a/dom/workers/ServiceWorkerScriptCache.cpp
+++ b/dom/workers/ServiceWorkerScriptCache.cpp
@@ -361,17 +361,17 @@ public:
 
   void
   NetworkFinished(nsresult aStatus)
   {
     AssertIsOnMainThread();
 
     mNetworkFinished = true;
 
-    if (NS_FAILED(aStatus)) {
+    if (NS_WARN_IF(NS_FAILED(aStatus))) {
       if (mCC) {
         mCC->Abort();
       }
 
       ComparisonFinished(aStatus, false);
       return;
     }
 
@@ -381,17 +381,17 @@ public:
   void
   CacheFinished(nsresult aStatus, bool aInCache)
   {
     AssertIsOnMainThread();
 
     mCacheFinished = true;
     mInCache = aInCache;
 
-    if (NS_FAILED(aStatus)) {
+    if (NS_WARN_IF(NS_FAILED(aStatus))) {
       if (mCN) {
         mCN->Abort();
       }
 
       ComparisonFinished(aStatus, false);
       return;
     }
 
@@ -402,17 +402,17 @@ public:
   MaybeCompare()
   {
     AssertIsOnMainThread();
 
     if (!mNetworkFinished || (mCC && !mCacheFinished)) {
       return;
     }
 
-    if (!mCC || !mInCache) {
+    if (NS_WARN_IF(!mCC || !mInCache)) {
       ComparisonFinished(NS_OK, false);
       return;
     }
 
     ComparisonFinished(NS_OK, mCC->Buffer().Equals(mCN->Buffer()));
   }
 
   // This class manages 2 promises: 1 is to retrieve Cache object, and 2 is to
@@ -531,17 +531,17 @@ private:
   }
 
   void
   ComparisonFinished(nsresult aStatus, bool aIsEqual)
   {
     AssertIsOnMainThread();
     MOZ_ASSERT(mCallback);
 
-    if (NS_FAILED(aStatus)) {
+    if (NS_WARN_IF(NS_FAILED(aStatus))) {
       Fail(aStatus);
       return;
     }
 
     if (aIsEqual) {
       mCallback->ComparisonResult(aStatus, aIsEqual, EmptyString(), mMaxScope);
       Cleanup();
       return;
@@ -690,17 +690,21 @@ CompareNetwork::OnStreamComplete(nsIStre
   AssertIsOnMainThread();
 
   // If no channel, Abort() has been called.
   if (!mChannel) {
     return NS_OK;
   }
 
   if (NS_WARN_IF(NS_FAILED(aStatus))) {
-    mManager->NetworkFinished(aStatus);
+    if (aStatus == NS_ERROR_REDIRECT_LOOP) {
+      mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
+    } else {
+      mManager->NetworkFinished(aStatus);
+    }
     return NS_OK;
   }
 
   nsCOMPtr<nsIRequest> request;
   nsresult rv = aLoader->GetRequest(getter_AddRefs(request));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mManager->NetworkFinished(rv);
     return NS_OK;
@@ -710,28 +714,42 @@ CompareNetwork::OnStreamComplete(nsIStre
   if (httpChannel) {
     bool requestSucceeded;
     rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mManager->NetworkFinished(rv);
       return NS_OK;
     }
 
-    if (!requestSucceeded) {
+    if (NS_WARN_IF(!requestSucceeded)) {
       mManager->NetworkFinished(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
     nsAutoCString maxScope;
     // Note: we explicitly don't check for the return value here, because the
-    // absense of the header is not an error condition.
+    // absence of the header is not an error condition.
     unused << httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Service-Worker-Allowed"),
                                              maxScope);
 
     mManager->SetMaxScope(maxScope);
+
+    nsAutoCString mimeType;
+    rv = httpChannel->GetContentType(mimeType);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
+      return rv;
+    }
+
+    if (!mimeType.LowerCaseEqualsLiteral("text/javascript") &&
+        !mimeType.LowerCaseEqualsLiteral("application/x-javascript") &&
+        !mimeType.LowerCaseEqualsLiteral("application/javascript")) {
+      mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
+      return rv;
+    }
   }
   else {
     // The only supported request schemes are http, https, and app.
     // Above, we check to ensure that the request is http or https
     // based on the channel qi.  Here we test the scheme to ensure
     // that it is app.  Otherwise, bail.
     nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
     if (NS_WARN_IF(!channel)) {
@@ -747,24 +765,22 @@ CompareNetwork::OnStreamComplete(nsIStre
 
     nsAutoCString scheme;
     rv = uri->GetScheme(scheme);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mManager->NetworkFinished(rv);
       return NS_OK;
     }
 
-    if (!scheme.LowerCaseEqualsLiteral("app")) {
+    if (NS_WARN_IF(!scheme.LowerCaseEqualsLiteral("app"))) {
       mManager->NetworkFinished(NS_ERROR_FAILURE);
       return NS_OK;      
     }
   }
 
-  // FIXME(nsm): "Extract mime type..."
-
   char16_t* buffer = nullptr;
   size_t len = 0;
 
   rv = nsScriptLoader::ConvertToUTF16(httpChannel, aString, aLen,
                                       NS_LITERAL_STRING("UTF-8"), nullptr,
                                       buffer, len);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mManager->NetworkFinished(rv);
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1142,17 +1142,17 @@ public:
       xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
       return false;
     }
 
     nsRefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
     nsresult rv =
       event->InitMessageEvent(NS_LITERAL_STRING("message"),
                               false /* non-bubbling */,
-                              true /* cancelable */,
+                              false /* non-cancelable */,
                               messageData,
                               EmptyString(),
                               EmptyString(),
                               nullptr);
     if (mEventSource) {
       nsRefPtr<ServiceWorkerClient> client =
         new ServiceWorkerWindowClient(aTarget, *mEventSource);
       event->SetSource(client);
@@ -1361,28 +1361,29 @@ class ReportErrorRunnable final : public
 {
   nsString mMessage;
   nsString mFilename;
   nsString mLine;
   uint32_t mLineNumber;
   uint32_t mColumnNumber;
   uint32_t mFlags;
   uint32_t mErrorNumber;
+  JSExnType mExnType;
 
 public:
   // aWorkerPrivate is the worker thread we're on (or the main thread, if null)
   // aTarget is the worker object that we are going to fire an error at
   // (if any).
   static bool
   ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
               bool aFireAtScope, WorkerPrivate* aTarget,
               const nsString& aMessage, const nsString& aFilename,
               const nsString& aLine, uint32_t aLineNumber,
               uint32_t aColumnNumber, uint32_t aFlags,
-              uint32_t aErrorNumber, uint64_t aInnerWindowId)
+              uint32_t aErrorNumber, JSExnType aExnType, uint64_t aInnerWindowId)
   {
     if (aWorkerPrivate) {
       aWorkerPrivate->AssertIsOnWorkerThread();
     }
     else {
       AssertIsOnMainThread();
     }
 
@@ -1477,35 +1478,36 @@ public:
       }
     }
 
     // Now fire a runnable to do the same on the parent's thread if we can.
     if (aWorkerPrivate) {
       nsRefPtr<ReportErrorRunnable> runnable =
         new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
                                 aLineNumber, aColumnNumber, aFlags,
-                                aErrorNumber);
+                                aErrorNumber, aExnType);
       return runnable->Dispatch(aCx);
     }
 
     // Otherwise log an error to the error console.
     LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
                       aFlags, aInnerWindowId);
     return true;
   }
 
 private:
   ReportErrorRunnable(WorkerPrivate* aWorkerPrivate, const nsString& aMessage,
                       const nsString& aFilename, const nsString& aLine,
                       uint32_t aLineNumber, uint32_t aColumnNumber,
-                      uint32_t aFlags, uint32_t aErrorNumber)
+                      uint32_t aFlags, uint32_t aErrorNumber,
+                      JSExnType aExnType)
   : WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
     mMessage(aMessage), mFilename(aFilename), mLine(aLine),
     mLineNumber(aLineNumber), mColumnNumber(aColumnNumber), mFlags(aFlags),
-    mErrorNumber(aErrorNumber)
+    mErrorNumber(aErrorNumber), mExnType(aExnType)
   { }
 
   virtual void
   PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
                bool aDispatchResult) override
   {
     aWorkerPrivate->AssertIsOnWorkerThread();
 
@@ -1539,17 +1541,17 @@ private:
         if (aWorkerPrivate->IsServiceWorker() && !JSREPORT_IS_WARNING(mFlags)) {
           nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
           MOZ_ASSERT(swm);
           bool handled = swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
                                           aWorkerPrivate->SharedWorkerName(),
                                           aWorkerPrivate->ScriptURL(),
                                           mMessage,
                                           mFilename, mLine, mLineNumber,
-                                          mColumnNumber, mFlags);
+                                          mColumnNumber, mFlags, mExnType);
           if (handled) {
             return true;
           }
         }
 
         aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
                                                       mLine, mLineNumber,
                                                       mColumnNumber, mFlags);
@@ -1568,17 +1570,17 @@ private:
     // Don't fire this event if the JS object has been disconnected from the
     // private object.
     if (!workerIsAcceptingEvents) {
       return true;
     }
 
     return ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mMessage,
                        mFilename, mLine, mLineNumber, mColumnNumber, mFlags,
-                       mErrorNumber, innerWindowId);
+                       mErrorNumber, mExnType, innerWindowId);
   }
 };
 
 class TimerRunnable final : public WorkerRunnable
 {
 public:
   explicit TimerRunnable(WorkerPrivate* aWorkerPrivate)
   : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
@@ -6378,16 +6380,17 @@ WorkerPrivate::ReportError(JSContext* aC
   NS_ASSERTION(mErrorHandlerRecursionCount == 0 ||
                mErrorHandlerRecursionCount == 1,
                "Bad recursion logic!");
 
   JS_ClearPendingException(aCx);
 
   nsString message, filename, line;
   uint32_t lineNumber, columnNumber, flags, errorNumber;
+  JSExnType exnType = JSEXN_ERR;
 
   if (aReport) {
     // ErrorEvent objects don't have a |name| field the way ES |Error| objects
     // do. Traditionally (and mostly by accident), the |message| field of
     // ErrorEvent has corresponded to |Name: Message| of the original Error
     // object. Things have been cleaned up in the JS engine, so now we need to
     // format this string explicitly.
     JS::Rooted<JSString*> messageStr(aCx,
@@ -6399,16 +6402,18 @@ WorkerPrivate::ReportError(JSContext* aC
       }
     }
     filename = NS_ConvertUTF8toUTF16(aReport->filename);
     line = aReport->uclinebuf;
     lineNumber = aReport->lineno;
     columnNumber = aReport->uctokenptr - aReport->uclinebuf;
     flags = aReport->flags;
     errorNumber = aReport->errorNumber;
+    MOZ_ASSERT(aReport->exnType >= JSEXN_NONE && aReport->exnType < JSEXN_LIMIT);
+    exnType = JSExnType(aReport->exnType);
   }
   else {
     lineNumber = columnNumber = errorNumber = 0;
     flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
   }
 
   if (message.IsEmpty()) {
     message = NS_ConvertUTF8toUTF16(aMessage);
@@ -6420,17 +6425,17 @@ WorkerPrivate::ReportError(JSContext* aC
   // if there was an error in the close handler or if we ran out of memory.
   bool fireAtScope = mErrorHandlerRecursionCount == 1 &&
                      !mCloseHandlerStarted &&
                      errorNumber != JSMSG_OUT_OF_MEMORY &&
                      JS::CurrentGlobalOrNull(aCx);
 
   if (!ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
                                         filename, line, lineNumber,
-                                        columnNumber, flags, errorNumber, 0)) {
+                                        columnNumber, flags, errorNumber, exnType, 0)) {
     JS_ReportPendingException(aCx);
   }
 
   mErrorHandlerRecursionCount--;
 }
 
 int32_t
 WorkerPrivate::SetTimeout(JSContext* aCx,
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -242,10 +242,11 @@ skip-if = toolkit == "android" || toolki
 [test_strict_mode_warning.html]
 [test_third_party_iframes.html]
 [test_unregister.html]
 [test_workerUnregister.html]
 [test_workerUpdate.html]
 [test_workerupdatefoundevent.html]
 [test_opaque_intercept.html]
 [test_fetch_event_client_postmessage.html]
+[test_escapedSlashes.html]
 [test_eventsource_intercept.html]
 [test_not_intercept_plugin.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/test_escapedSlashes.html
@@ -0,0 +1,102 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for escaped slashes in navigator.serviceWorker.register</title>
+  <script type="text/javascript" src="http://mochi.test:8888/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://mochi.test:8888/tests/SimpleTest/test.css" />
+  <base href="https://mozilla.org/">
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+var tests = [
+  { status:  true,
+    scriptURL: "a.js?foo%2fbar",
+    scopeURL: null },
+  { status:  false,
+    scriptURL: "foo%2fbar",
+    scopeURL: null },
+  { status:  true,
+    scriptURL: "a.js?foo%2Fbar",
+    scopeURL: null },
+  { status:  false,
+    scriptURL: "foo%2Fbar",
+    scopeURL: null },
+  { status:  true,
+    scriptURL: "a.js?foo%5cbar",
+    scopeURL: null },
+  { status:  false,
+    scriptURL: "foo%5cbar",
+    scopeURL: null },
+  { status:  true,
+    scriptURL: "a.js?foo%2Cbar",
+    scopeURL: null },
+  { status:  false,
+    scriptURL: "foo%5Cbar",
+    scopeURL: null },
+  { status:  true,
+    scriptURL: "ok.js",
+    scopeURL: "/scope?foo%2fbar"},
+  { status:  false,
+    scriptURL: "ok.js",
+    scopeURL: "/foo%2fbar"},
+  { status:  true,
+    scriptURL: "ok.js",
+    scopeURL: "/scope?foo%2Fbar"},
+  { status:  false,
+    scriptURL: "ok.js",
+    scopeURL: "foo%2Fbar"},
+  { status:  true,
+    scriptURL: "ok.js",
+    scopeURL: "/scope?foo%5cbar"},
+  { status:  false,
+    scriptURL: "ok.js",
+    scopeURL: "foo%5cbar"},
+  { status:  true,
+    scriptURL: "ok.js",
+    scopeURL: "/scope?foo%5Cbar"},
+  { status:  false,
+    scriptURL: "ok.js",
+    scopeURL: "foo%5Cbar"},
+];
+
+function runTest() {
+  if (!tests.length) {
+    SimpleTest.finish();
+    return;
+  }
+
+  var test = tests.shift();
+  navigator.serviceWorker.register(test.scriptURL, test.scopeURL)
+    .then(reg => {
+      ok(false, "Register should fail");
+    }, err => {
+      if (!test.status) {
+        is(err.name, "TypeError", "Registration should fail with TypeError");
+      } else {
+        ok(test.status, "Register should fail");
+      }
+    })
+    .then(runTest);
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = function() {
+  SpecialPowers.pushPrefEnv({"set": [
+    ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.testing.enabled", true],
+    ["dom.serviceWorkers.enabled", true],
+  ]}, runTest);
+};
+
+</script>
+</body>
+</html>
--- a/dom/workers/test/serviceworkers/test_installation_simple.html
+++ b/dom/workers/test/serviceworkers/test_installation_simple.html
@@ -85,19 +85,19 @@
         ok(false, "404 response should fail with TypeError");
       }, function(e) {
         ok(e.name === "TypeError", "404 response should fail with TypeError");
       });
   }
 
   function redirectError() {
     return navigator.serviceWorker.register("redirect_serviceworker.sjs", { scope: "redirect_error/" }).then(function(swr) {
-        ok(false, "redirection should fail with TypeError");
+        ok(false, "redirection should fail");
       }, function (e) {
-        ok(e.name === "TypeError", "redirection should fail with TypeError");
+        ok(e.name === "SecurityError", "redirection should fail with SecurityError");
       });
   }
 
   function parseError() {
     var p = navigator.serviceWorker.register("parse_error_worker.js", { scope: "parse_error/" });
     return p.then(function(wr) {
       ok(false, "Registration should fail with parse error");
       return navigator.serviceWorker.getRegistration("parse_error/").then(function(swr) {
--- a/dom/xml/moz.build
+++ b/dom/xml/moz.build
@@ -26,16 +26,19 @@ UNIFIED_SOURCES += [
     'nsXMLElement.cpp',
     'nsXMLFragmentContentSink.cpp',
     'nsXMLPrettyPrinter.cpp',
     'ProcessingInstruction.cpp',
     'XMLDocument.cpp',
     'XMLStylesheetProcessingInstruction.cpp',
 ]
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/base',
     '/dom/html',
--- a/dom/xslt/xml/moz.build
+++ b/dom/xslt/xml/moz.build
@@ -4,16 +4,19 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'txXMLParser.cpp',
     'txXMLUtils.cpp',
 ]
 
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wshadow']
+
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
     '../xpath',
     '../xslt',
     '/dom/base',
 ]
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -464,16 +464,18 @@ nsEditorEventListener::HandleEvent(nsIDO
       return HandleText(aEvent);
     // compositionstart
     case NS_COMPOSITION_START:
       return HandleStartComposition(aEvent);
     // compositionend
     case NS_COMPOSITION_END:
       HandleEndComposition(aEvent);
       return NS_OK;
+    default: