Merge m-c to f-t
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 18 Oct 2016 19:57:44 -0700
changeset 318587 f52b380bc02e1022631ab8dcd43ed246930974c3
parent 318586 12a9cca092f816fabb67cc8a139e0cbd5b1cea37 (current diff)
parent 318521 90d8afaddf9150853b0b68b35b30c1e54a8683e7 (diff)
child 318588 c63097845cfbadc8f4fdc61ed5bd6a34bb67cd68
push id82960
push usercbook@mozilla.com
push dateWed, 19 Oct 2016 15:04:04 +0000
treeherdermozilla-inbound@c48c53e3492e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone52.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 f-t
.eslintrc
accessible/.eslintrc
accessible/tests/browser/.eslintrc
browser/.eslintrc
browser/base/content/test/alerts/.eslintrc
browser/base/content/test/chrome/.eslintrc
browser/base/content/test/general/.eslintrc
browser/base/content/test/newtab/.eslintrc
browser/base/content/test/plugins/.eslintrc
browser/base/content/test/plugins/browser_plugin_infolink.js
browser/base/content/test/popupNotifications/.eslintrc
browser/base/content/test/referrer/.eslintrc
browser/base/content/test/social/.eslintrc
browser/components/contextualidentity/test/browser/.eslintrc
browser/components/customizableui/test/.eslintrc
browser/components/dirprovider/tests/unit/.eslintrc
browser/components/downloads/test/browser/.eslintrc
browser/components/downloads/test/unit/.eslintrc
browser/components/extensions/.eslintrc
browser/components/extensions/test/browser/.eslintrc
browser/components/extensions/test/xpcshell/.eslintrc
browser/components/feeds/test/.eslintrc
browser/components/feeds/test/chrome/.eslintrc
browser/components/feeds/test/unit/.eslintrc
browser/components/migration/tests/unit/.eslintrc
browser/components/newtab/tests/browser/.eslintrc
browser/components/newtab/tests/xpcshell/.eslintrc
browser/components/originattributes/test/browser/.eslintrc
browser/components/places/tests/browser/.eslintrc
browser/components/places/tests/chrome/.eslintrc
browser/components/places/tests/unit/.eslintrc
browser/components/preferences/in-content/tests/.eslintrc
browser/components/privatebrowsing/test/browser/.eslintrc
browser/components/safebrowsing/content/test/.eslintrc
browser/components/search/test/.eslintrc
browser/components/selfsupport/test/.eslintrc
browser/components/sessionstore/test/.eslintrc
browser/components/sessionstore/test/unit/.eslintrc
browser/components/shell/test/.eslintrc
browser/components/shell/test/unit/.eslintrc
browser/components/tests/browser/.eslintrc
browser/components/translation/test/.eslintrc
browser/components/translation/test/unit/.eslintrc
browser/components/uitour/test/.eslintrc
browser/experiments/test/xpcshell/.eslintrc
browser/extensions/formautofill/.eslintrc
browser/extensions/formautofill/test/browser/.eslintrc
browser/extensions/pdfjs/test/.eslintrc
browser/modules/test/.eslintrc
browser/modules/test/unit/social/.eslintrc
browser/modules/test/xpcshell/.eslintrc
devtools/.eslintrc
devtools/.eslintrc.mochitests
devtools/.eslintrc.xpcshell
devtools/client/aboutdebugging/test/.eslintrc
devtools/client/animationinspector/test/.eslintrc
devtools/client/animationinspector/test/unit/.eslintrc
devtools/client/canvasdebugger/test/.eslintrc
devtools/client/commandline/test/.eslintrc
devtools/client/debugger/new/test/mochitest/.eslintrc
devtools/client/debugger/test/.eslintrc
devtools/client/dom/.eslintrc
devtools/client/dom/test/.eslintrc
devtools/client/framework/test/.eslintrc
devtools/client/inspector/.eslintrc
devtools/client/inspector/components/test/.eslintrc
devtools/client/inspector/computed/test/.eslintrc
devtools/client/inspector/fonts/test/.eslintrc
devtools/client/inspector/markup/test/.eslintrc
devtools/client/inspector/rules/test/.eslintrc
devtools/client/inspector/shared/test/.eslintrc
devtools/client/inspector/test/.eslintrc
devtools/client/jsonview/.eslintrc
devtools/client/jsonview/test/.eslintrc
devtools/client/memory/test/browser/.eslintrc
devtools/client/memory/test/unit/.eslintrc
devtools/client/netmonitor/.eslintrc
devtools/client/netmonitor/har/test/.eslintrc
devtools/client/netmonitor/test/.eslintrc
devtools/client/performance/test/.eslintrc
devtools/client/performance/test/unit/.eslintrc
devtools/client/projecteditor/test/.eslintrc
devtools/client/promisedebugger/test/.eslintrc
devtools/client/responsive.html/test/browser/.eslintrc
devtools/client/responsive.html/test/unit/.eslintrc
devtools/client/responsivedesign/test/.eslintrc
devtools/client/scratchpad/test/.eslintrc
devtools/client/shadereditor/test/.eslintrc
devtools/client/shared/components/.eslintrc
devtools/client/shared/components/test/browser/.eslintrc
devtools/client/shared/components/test/mochitest/.eslintrc
devtools/client/shared/shim/test/.eslintrc
devtools/client/shared/test/.eslintrc
devtools/client/shared/test/unit/.eslintrc
devtools/client/sourceeditor/.eslintrc
devtools/client/sourceeditor/test/.eslintrc
devtools/client/storage/test/.eslintrc
devtools/client/styleeditor/test/.eslintrc
devtools/client/webaudioeditor/test/.eslintrc
devtools/client/webconsole/net/.eslintrc
devtools/client/webconsole/net/test/mochitest/.eslintrc
devtools/client/webconsole/net/test/unit/.eslintrc
devtools/client/webconsole/new-console-output/test/.eslintrc
devtools/client/webconsole/test/.eslintrc
devtools/client/webide/test/.eslintrc
devtools/server/tests/browser/.eslintrc
devtools/server/tests/mochitest/.eslintrc
devtools/server/tests/unit/.eslintrc
devtools/shared/heapsnapshot/tests/unit/.eslintrc
devtools/shared/platform/content/.eslintrc
devtools/shared/platform/content/test/.eslintrc
devtools/shared/security/tests/unit/.eslintrc
devtools/shared/tests/browser/.eslintrc
devtools/shared/tests/unit/.eslintrc
devtools/shared/transport/tests/unit/.eslintrc
devtools/shared/webconsole/test/unit/.eslintrc
devtools/shared/worker/tests/browser/.eslintrc
dom/animation/test/chrome/test_observers_for_script_animation.html
dom/base/test/chrome/file_bug391728.html
dom/base/test/chrome/file_bug391728_2.html
dom/base/test/chrome/test_bug391728.html
dom/base/test/test_bug425013.html
dom/interfaces/notification/nsIDOMDesktopNotification.idl
dom/notification/ChromeNotifications.js
dom/notification/ChromeNotifications.manifest
dom/security/test/csp/file_bug768029.sjs
dom/security/test/hsts/browser_hsts-priming_main.js
dom/tests/mochitest/notification/chrome.ini
dom/tests/mochitest/notification/test_notification_noresend.html
dom/webidl/ChromeNotifications.webidl
js/src/tests/ecma_6/TypedArray/from_proxy.js
mobile/android/components/extensions/.eslintrc
mobile/android/components/extensions/test/mochitest/.eslintrc
security/manager/.eslintrc.json
security/manager/pki/resources/content/editcerts.js
security/manager/ssl/tests/.eslintrc.json
security/manager/ssl/tests/mochitest/browser/.eslintrc.json
security/manager/ssl/tests/mochitest/mixedcontent/.eslintrc.json
security/manager/ssl/tests/mochitest/stricttransportsecurity/.eslintrc.json
security/manager/ssl/tests/unit/.eslintrc.json
security/manager/ssl/tests/unit/test_signed_apps/sslcontrol.xpi
security/manager/tools/.eslintrc.json
storage/.eslintrc
testing/mochitest/browser.eslintrc
testing/mochitest/chrome.eslintrc
testing/mochitest/mochitest.eslintrc
testing/xpcshell/xpcshell.eslintrc
toolkit/.eslintrc
toolkit/components/aboutmemory/tests/.eslintrc
toolkit/components/aboutperformance/tests/browser/.eslintrc
toolkit/components/addoncompat/tests/browser/.eslintrc
toolkit/components/alerts/test/.eslintrc
toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc
toolkit/components/autocomplete/tests/unit/.eslintrc
toolkit/components/captivedetect/test/unit/.eslintrc
toolkit/components/commandlines/test/unit/.eslintrc
toolkit/components/commandlines/test/unit_unix/.eslintrc
toolkit/components/commandlines/test/unit_win/.eslintrc
toolkit/components/contentprefs/tests/mochitest/.eslintrc
toolkit/components/contentprefs/tests/unit/.eslintrc
toolkit/components/contentprefs/tests/unit_cps2/.eslintrc
toolkit/components/crashes/tests/xpcshell/.eslintrc
toolkit/components/crashmonitor/test/unit/.eslintrc
toolkit/components/ctypes/tests/chrome/.eslintrc
toolkit/components/ctypes/tests/unit/.eslintrc
toolkit/components/downloads/test/unit/.eslintrc
toolkit/components/extensions/.eslintrc
toolkit/components/extensions/test/mochitest/.eslintrc
toolkit/components/extensions/test/xpcshell/.eslintrc
toolkit/components/feeds/test/.eslintrc
toolkit/components/filepicker/test/unit/.eslintrc
toolkit/components/filewatcher/tests/xpcshell/.eslintrc
toolkit/components/formautofill/test/browser/.eslintrc
toolkit/components/formautofill/test/chrome/.eslintrc
toolkit/components/formautofill/test/xpcshell/.eslintrc
toolkit/components/jsdownloads/test/browser/.eslintrc
toolkit/components/jsdownloads/test/data/.eslintrc
toolkit/components/jsdownloads/test/unit/.eslintrc
toolkit/components/lz4/tests/xpcshell/.eslintrc
toolkit/components/mediasniffer/test/unit/.eslintrc
toolkit/components/narrate/.eslintrc
toolkit/components/narrate/test/.eslintrc
toolkit/components/osfile/tests/mochi/.eslintrc
toolkit/components/osfile/tests/xpcshell/.eslintrc
toolkit/components/passwordmgr/.eslintrc
toolkit/components/passwordmgr/test/.eslintrc
toolkit/components/passwordmgr/test/browser/.eslintrc
toolkit/components/passwordmgr/test/unit/.eslintrc
toolkit/components/perf/.eslintrc
toolkit/components/perfmonitoring/tests/browser/.eslintrc
toolkit/components/places/tests/.eslintrc
toolkit/components/places/tests/bookmarks/.eslintrc
toolkit/components/places/tests/browser/.eslintrc
toolkit/components/places/tests/chrome/.eslintrc
toolkit/components/places/tests/expiration/.eslintrc
toolkit/components/places/tests/favicons/.eslintrc
toolkit/components/places/tests/history/.eslintrc
toolkit/components/places/tests/migration/.eslintrc
toolkit/components/places/tests/network/.eslintrc
toolkit/components/places/tests/queries/.eslintrc
toolkit/components/places/tests/unifiedcomplete/.eslintrc
toolkit/components/places/tests/unit/.eslintrc
toolkit/components/promiseworker/tests/xpcshell/.eslintrc
toolkit/components/prompts/test/.eslintrc
toolkit/components/remotebrowserutils/tests/browser/.eslintrc
toolkit/components/satchel/test/.eslintrc
toolkit/components/satchel/test/browser/.eslintrc
toolkit/components/satchel/test/unit/.eslintrc
toolkit/components/search/tests/xpcshell/.eslintrc
toolkit/components/social/test/xpcshell/.eslintrc
toolkit/components/sqlite/tests/xpcshell/.eslintrc
toolkit/components/startup/tests/browser/.eslintrc
toolkit/components/startup/tests/unit/.eslintrc
toolkit/components/telemetry/tests/unit/.eslintrc
toolkit/components/terminator/tests/xpcshell/.eslintrc
toolkit/components/thumbnails/test/.eslintrc
toolkit/components/timermanager/tests/unit/.eslintrc
toolkit/components/url-classifier/tests/mochitest/.eslintrc
toolkit/components/url-classifier/tests/unit/.eslintrc
toolkit/components/urlformatter/tests/unit/.eslintrc
toolkit/components/viewsource/test/.eslintrc
toolkit/components/viewsource/test/browser/.eslintrc
toolkit/components/workerloader/tests/.eslintrc
toolkit/components/xulstore/tests/chrome/.eslintrc
toolkit/components/xulstore/tests/xpcshell/.eslintrc
toolkit/content/tests/browser/.eslintrc
toolkit/content/tests/chrome/.eslintrc
toolkit/content/tests/unit/.eslintrc
toolkit/content/tests/widgets/.eslintrc
toolkit/crashreporter/test/browser/.eslintrc
toolkit/crashreporter/test/unit/.eslintrc
toolkit/crashreporter/test/unit_ipc/.eslintrc
toolkit/forgetaboutsite/test/browser/.eslintrc
toolkit/forgetaboutsite/test/unit/.eslintrc
toolkit/identity/tests/chrome/.eslintrc
toolkit/identity/tests/unit/.eslintrc
toolkit/modules/addons/.eslintrc
toolkit/modules/subprocess/.eslintrc
toolkit/modules/subprocess/test/xpcshell/.eslintrc
toolkit/modules/tests/browser/.eslintrc
toolkit/modules/tests/chrome/.eslintrc
toolkit/modules/tests/mochitest/.eslintrc
toolkit/modules/tests/xpcshell/.eslintrc
toolkit/mozapps/downloads/tests/chrome/.eslintrc
toolkit/mozapps/downloads/tests/unit/.eslintrc
toolkit/mozapps/extensions/.eslintrc
toolkit/mozapps/extensions/test/browser/.eslintrc
toolkit/mozapps/extensions/test/mochitest/.eslintrc
toolkit/mozapps/extensions/test/xpcshell/.eslintrc
toolkit/mozapps/extensions/test/xpinstall/.eslintrc
toolkit/mozapps/update/tests/chrome/.eslintrc
toolkit/mozapps/update/tests/unit_aus_update/.eslintrc
toolkit/mozapps/update/tests/unit_base_updater/.eslintrc
toolkit/mozapps/update/tests/unit_service_updater/.eslintrc
toolkit/pluginproblem/content/pluginFinderBinding.css
toolkit/profile/test/.eslintrc
toolkit/themes/mobile/mozapps/plugins/contentPluginDownload.png
toolkit/themes/mobile/mozapps/plugins/contentPluginMissing.png
toolkit/themes/osx/mochitests/.eslintrc
toolkit/themes/shared/plugins/contentPluginDownload.png
toolkit/themes/shared/plugins/contentPluginMissing.png
toolkit/xre/test/.eslintrc
tools/lint/eslint/eslint-plugin-mozilla/lib/rules/.eslintrc
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,8 +1,11 @@
+# Allow linting of .eslintrc.js files.
+!**/.eslintrc.js
+
 # Always ignore node_modules.
 **/node_modules/**/*.*
 
 # Exclude expected objdirs.
 obj*/**
 
 # We ignore all these directories by default, until we get them enabled.
 # If you are enabling a directory, please add directory specific exclusions
rename from .eslintrc
rename to .eslintrc.js
--- a/.eslintrc
+++ b/.eslintrc.js
@@ -1,12 +1,14 @@
-{
+"use strict";
+
+module.exports = {
   // When adding items to this file please check for effects on sub-directories.
   "plugins": [
     "mozilla"
   ],
   "rules": {
     "mozilla/import-globals": 1,
   },
   "env": {
     "es6": true
   },
-}
+};
--- a/.gdbinit
+++ b/.gdbinit
@@ -6,16 +6,22 @@
 #
 #  add-auto-load-safe-path ~/moz
 
 # Don't stop for the SIG32/33/etc signals that Flash produces
 handle SIG32 noprint nostop pass
 handle SIG33 noprint nostop pass
 handle SIGPIPE noprint nostop pass
 
+# Don't stop for certain other signals where it's not useful,
+# such as the SIG64 signals triggered by the Linux
+# sandboxing code on older kernels.
+handle SIG38 noprint nostop pass
+handle SIG64 noprint nostop pass
+
 # Show the concrete types behind nsIFoo
 set print object on
 
 # run when using the auto-solib-add trick
 def prun
         tbreak main
         run
 	set auto-solib-add 0
rename from accessible/.eslintrc
rename to accessible/.eslintrc.js
--- a/accessible/.eslintrc
+++ b/accessible/.eslintrc.js
@@ -1,15 +1,17 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../.eslintrc"
+    "../.eslintrc.js"
   ],
   "globals": {
     "Cc": true,
     "Ci": true,
     "Components": true,
     "console": true,
     "Cu": true,
     "dump": true,
     "Services": true,
     "XPCOMUtils": true
   }
-}
+};
rename from accessible/tests/browser/.eslintrc
rename to accessible/tests/browser/.eslintrc.js
--- a/accessible/tests/browser/.eslintrc
+++ b/accessible/tests/browser/.eslintrc.js
@@ -1,11 +1,13 @@
-{
+"use strict";
+
+module.exports = { // eslint-disable-line no-undef
   "extends": [
-    "../../../testing/mochitest/browser.eslintrc"
+    "../../../testing/mochitest/browser.eslintrc.js"
   ],
   // All globals made available in the test environment.
   "globals": {
     // Content scripts have global 'content' object
     "content": true,
 
     "add_task": true,
 
@@ -41,17 +43,17 @@
     "loadFrameScripts": true,
     "Logger": true,
     "MOCHITESTS_DIR": true,
     "waitForEvent": true,
     "waitForMultipleEvents": true,
     "invokeSetAttribute": true,
     "invokeSetStyle": true,
     "invokeFocus": true,
-    "findAccessibleChildByID": true,
+    "findAccessibleChildByID": true
   },
   "rules": {
     "mozilla/mark-test-function-used": 1,
     "mozilla/no-aArgs": 1,
     "mozilla/no-cpows-in-tests": 1,
     "mozilla/reject-importGlobalProperties": 1,
     "mozilla/var-only-at-top-level": 1,
 
@@ -207,11 +209,11 @@
     "no-octal-escape": 0,
     "no-undef-init": 2,
     "no-unexpected-multiline": 2,
     "object-curly-spacing": 0,
     "no-unused-expressions": 0,
     "no-void": 0,
     "no-wrap-func": 0,
     "operator-assignment": 0,
-    "operator-linebreak": [2, "after"],
+    "operator-linebreak": [2, "after"]
   }
-}
+};
--- a/b2g/components/AlertsHelper.jsm
+++ b/b2g/components/AlertsHelper.jsm
@@ -51,23 +51,20 @@ const kDesktopNotificationClose = "deskt
 
 const kTopicAlertClickCallback = "alertclickcallback";
 const kTopicAlertShow          = "alertshow";
 const kTopicAlertFinished      = "alertfinished";
 
 const kMozChromeNotificationEvent  = "mozChromeNotificationEvent";
 const kMozContentNotificationEvent = "mozContentNotificationEvent";
 
-const kMessageAppNotificationSend    = "app-notification-send";
-const kMessageAppNotificationReturn  = "app-notification-return";
 const kMessageAlertNotificationSend  = "alert-notification-send";
 const kMessageAlertNotificationClose = "alert-notification-close";
 
 const kMessages = [
-  kMessageAppNotificationSend,
   kMessageAlertNotificationSend,
   kMessageAlertNotificationClose
 ];
 
 var AlertsHelper = {
 
   _listeners: {},
 
@@ -127,45 +124,16 @@ var AlertsHelper = {
       topic = kTopicAlertFinished;
     }
 
     if (listener.cookie) {
       try {
         listener.observer.observe(null, topic, listener.cookie);
       } catch (e) { }
     } else {
-      try {
-        listener.mm.sendAsyncMessage(kMessageAppNotificationReturn, {
-          uid: uid,
-          topic: topic,
-          target: listener.target
-        });
-      } catch (e) {
-        // we get an exception if the app is not launched yet
-        if (detail.type !== kDesktopNotificationShow) {
-          // excluding the 'show' event: there is no reason a unlaunched app
-          // would want to be notified that a notification is shown. This
-          // happens when a notification is still displayed at reboot time.
-          gSystemMessenger.sendMessage(kNotificationSystemMessageName, {
-              clicked: (detail.type === kDesktopNotificationClick),
-              title: listener.title,
-              body: listener.text,
-              imageURL: listener.imageURL,
-              lang: listener.lang,
-              dir: listener.dir,
-              id: listener.id,
-              tag: listener.tag,
-              timestamp: listener.timestamp,
-              data: listener.dataObj
-            },
-            Services.io.newURI(listener.target, null, null),
-            Services.io.newURI(listener.manifestURL, null, null)
-          );
-        }
-      }
       if (detail.type === kDesktopNotificationClose && listener.dbId) {
         notificationStorage.delete(listener.manifestURL, listener.dbId);
       }
     }
 
     // we"re done with this notification
     if (detail.type === kDesktopNotificationClose) {
       delete this._listeners[uid];
@@ -275,61 +243,32 @@ var AlertsHelper = {
 
     let dataObj = this.deserializeStructuredClone(data.dataStr);
     this.registerListener(data.name, data.cookie, data.alertListener);
     this.showNotification(data.imageURL, data.title, data.text,
                           data.textClickable, data.cookie, data.name, data.dir,
                           data.lang, dataObj, null, data.inPrivateBrowsing);
   },
 
-  showAppNotification: function(aMessage) {
-    let data = aMessage.data;
-    let details = data.details;
-    let dataObject = this.deserializeStructuredClone(details.data);
-    let listener = {
-      mm: aMessage.target,
-      title: data.title,
-      text: data.text,
-      manifestURL: details.manifestURL,
-      imageURL: data.imageURL,
-      lang: details.lang || undefined,
-      id: details.id || undefined,
-      dbId: details.dbId || undefined,
-      dir: details.dir || undefined,
-      tag: details.tag || undefined,
-      timestamp: details.timestamp || undefined,
-      dataObj: dataObject || undefined
-    };
-    this.registerAppListener(data.uid, listener);
-    this.showNotification(data.imageURL, data.title, data.text,
-                          details.textClickable, null, data.uid, details.dir,
-                          details.lang, dataObject, details.manifestURL,
-                          details.timestamp, details.mozbehavior);
-  },
-
   closeAlert: function(name) {
     SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, {
       type: kDesktopNotificationClose,
       id: name
     });
   },
 
   receiveMessage: function(aMessage) {
     if (!aMessage.target.assertAppHasPermission(kDesktopNotificationPerm)) {
       Cu.reportError("Desktop-notification message " + aMessage.name +
                      " from a content process with no " + kDesktopNotificationPerm +
                      " privileges.");
       return;
     }
 
     switch(aMessage.name) {
-      case kMessageAppNotificationSend:
-        this.showAppNotification(aMessage);
-        break;
-
       case kMessageAlertNotificationSend:
         this.showAlertNotification(aMessage);
         break;
 
       case kMessageAlertNotificationClose:
         this.closeAlert(aMessage.data.name);
         break;
     }
--- a/b2g/components/AlertsService.js
+++ b/b2g/components/AlertsService.js
@@ -31,41 +31,36 @@ function debug(str) {
 }
 
 // -----------------------------------------------------------------------
 // Alerts Service
 // -----------------------------------------------------------------------
 
 const kNotificationSystemMessageName = "notification";
 
-const kMessageAppNotificationSend    = "app-notification-send";
-const kMessageAppNotificationReturn  = "app-notification-return";
 const kMessageAlertNotificationSend  = "alert-notification-send";
 const kMessageAlertNotificationClose = "alert-notification-close";
 
 const kTopicAlertShow          = "alertshow";
 const kTopicAlertFinished      = "alertfinished";
 const kTopicAlertClickCallback = "alertclickcallback";
 
 function AlertsService() {
   Services.obs.addObserver(this, "xpcom-shutdown", false);
-  cpmm.addMessageListener(kMessageAppNotificationReturn, this);
 }
 
 AlertsService.prototype = {
   classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService,
-                                         Ci.nsIAppNotificationService,
                                          Ci.nsIObserver]),
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "xpcom-shutdown":
         Services.obs.removeObserver(this, "xpcom-shutdown");
-        cpmm.removeMessageListener(kMessageAppNotificationReturn, this);
         break;
     }
   },
 
   // nsIAlertsService
   showAlert: function(aAlert, aAlertListener) {
     if (!aAlert) {
       return;
@@ -99,87 +94,31 @@ AlertsService.prototype = {
   },
 
   closeAlert: function(aName) {
     cpmm.sendAsyncMessage(kMessageAlertNotificationClose, {
       name: aName
     });
   },
 
-  // nsIAppNotificationService
-  showAppNotification: function(aImageURL, aTitle, aText, aAlertListener,
-                                aDetails) {
-    let uid = (aDetails.id == "") ?
-          "app-notif-" + uuidGenerator.generateUUID() : aDetails.id;
-
-    let dataObj = this.deserializeStructuredClone(aDetails.data);
-    this._listeners[uid] = {
-      observer: aAlertListener,
-      title: aTitle,
-      text: aText,
-      manifestURL: aDetails.manifestURL,
-      imageURL: aImageURL,
-      lang: aDetails.lang || undefined,
-      id: aDetails.id || undefined,
-      dbId: aDetails.dbId || undefined,
-      dir: aDetails.dir || undefined,
-      tag: aDetails.tag || undefined,
-      timestamp: aDetails.timestamp || undefined,
-      dataObj: dataObj || undefined
-    };
-
-    cpmm.sendAsyncMessage(kMessageAppNotificationSend, {
-      imageURL: aImageURL,
-      title: aTitle,
-      text: aText,
-      uid: uid,
-      details: aDetails
-    });
-  },
-
   // AlertsService.js custom implementation
   _listeners: [],
 
   receiveMessage: function(aMessage) {
     let data = aMessage.data;
     let listener = this._listeners[data.uid];
-    if (aMessage.name !== kMessageAppNotificationReturn || !listener) {
+    if (!listener) {
       return;
     }
 
     let topic = data.topic;
 
     try {
       listener.observer.observe(null, topic, null);
     } catch (e) {
-      // It seems like there is no callbacks anymore, forward the click on
-      // notification via a system message containing the title/text/icon of
-      // the notification so the app get a change to react.
-      if (data.target) {
-        if (topic !== kTopicAlertShow) {
-          // excluding the 'show' event: there is no reason a unlaunched app
-          // would want to be notified that a notification is shown. This
-          // happens when a notification is still displayed at reboot time.
-          gSystemMessenger.sendMessage(kNotificationSystemMessageName, {
-              clicked: (topic === kTopicAlertClickCallback),
-              title: listener.title,
-              body: listener.text,
-              imageURL: listener.imageURL,
-              lang: listener.lang,
-              dir: listener.dir,
-              id: listener.id,
-              tag: listener.tag,
-              timestamp: listener.timestamp,
-              data: listener.dataObj || undefined,
-            },
-            Services.io.newURI(data.target, null, null),
-            Services.io.newURI(listener.manifestURL, null, null)
-          );
-        }
-      }
       if (topic === kTopicAlertFinished && listener.dbId) {
         notificationStorage.delete(listener.manifestURL, listener.dbId);
       }
     }
 
     // we're done with this notification
     if (topic === kTopicAlertFinished) {
       delete this._listeners[data.uid];
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -335,18 +335,16 @@
 @RESPATH@/components/xpcom_xpti.xpt
 @RESPATH@/components/xpconnect.xpt
 @RESPATH@/components/xulapp.xpt
 @RESPATH@/components/xul.xpt
 @RESPATH@/components/xultmpl.xpt
 @RESPATH@/components/zipwriter.xpt
 
 ; JavaScript components
-@RESPATH@/components/ChromeNotifications.js
-@RESPATH@/components/ChromeNotifications.manifest
 @RESPATH@/components/ConsoleAPI.manifest
 @RESPATH@/components/ConsoleAPIStorage.js
 @RESPATH@/components/BrowserElementParent.manifest
 @RESPATH@/components/BrowserElementParent.js
 @RESPATH@/components/BrowserElementProxy.manifest
 @RESPATH@/components/BrowserElementProxy.js
 @RESPATH@/components/ContactManager.js
 @RESPATH@/components/ContactManager.manifest
rename from browser/.eslintrc
rename to browser/.eslintrc.js
--- a/browser/.eslintrc
+++ b/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../toolkit/.eslintrc"
+    "../toolkit/.eslintrc.js"
   ],
-}
+};
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -443,17 +443,18 @@ toolbar:not(#TabsToolbar) > #personal-bo
 }
 
 /* ::::: location bar ::::: */
 #urlbar {
   -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
 }
 
 /* Always show URLs LTR. */
-.ac-url-text:-moz-locale-dir(rtl) {
+.ac-url-text:-moz-locale-dir(rtl),
+.ac-title-text[lookslikeurl]:-moz-locale-dir(rtl) {
   direction: ltr !important;
 }
 
 /* For non-action items, hide the action text; for action items, hide the URL
    text. */
 .ac-url[actiontype],
 .ac-action:not([actiontype]) {
   display: none;
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -19,17 +19,17 @@ Cu.import("resource://gre/modules/Task.j
 XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
   "resource:///modules/E10SUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
   "resource://gre/modules/BrowserUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
   "resource:///modules/ContentLinkHandler.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
   "resource://gre/modules/LoginManagerContent.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FormLikeFactory",
+XPCOMUtils.defineLazyModuleGetter(this, "LoginFormFactory",
   "resource://gre/modules/LoginManagerContent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
   "resource://gre/modules/InsecurePasswordUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PluginContent",
   "resource:///modules/PluginContent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FormSubmitObserver",
@@ -60,22 +60,22 @@ addMessageListener("ContextMenu:DoCustom
     () => PageMenuChild.executeMenu(message.data.generatedItemId));
 });
 
 addMessageListener("RemoteLogins:fillForm", function(message) {
   LoginManagerContent.receiveMessage(message, content);
 });
 addEventListener("DOMFormHasPassword", function(event) {
   LoginManagerContent.onDOMFormHasPassword(event, content);
-  let formLike = FormLikeFactory.createFromForm(event.target);
+  let formLike = LoginFormFactory.createFromForm(event.target);
   InsecurePasswordUtils.checkForInsecurePasswords(formLike);
 });
 addEventListener("DOMInputPasswordAdded", function(event) {
   LoginManagerContent.onDOMInputPasswordAdded(event, content);
-  let formLike = FormLikeFactory.createFromField(event.target);
+  let formLike = LoginFormFactory.createFromField(event.target);
   InsecurePasswordUtils.checkForInsecurePasswords(formLike);
 });
 addEventListener("pageshow", function(event) {
   LoginManagerContent.onPageShow(event, content);
 });
 addEventListener("DOMAutoComplete", function(event) {
   LoginManagerContent.onUsernameInput(event);
 });
rename from browser/base/content/test/alerts/.eslintrc
rename to browser/base/content/test/alerts/.eslintrc.js
--- a/browser/base/content/test/alerts/.eslintrc
+++ b/browser/base/content/test/alerts/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/base/content/test/chrome/.eslintrc
rename to browser/base/content/test/chrome/.eslintrc.js
--- a/browser/base/content/test/chrome/.eslintrc
+++ b/browser/base/content/test/chrome/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/chrome.eslintrc"
+    "../../../../../testing/mochitest/chrome.eslintrc.js"
   ]
-}
+};
rename from browser/base/content/test/general/.eslintrc
rename to browser/base/content/test/general/.eslintrc.js
--- a/browser/base/content/test/general/.eslintrc
+++ b/browser/base/content/test/general/.eslintrc.js
@@ -1,6 +1,8 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc",
-    "../../../../../testing/mochitest/mochitest.eslintrc",
+    "../../../../../testing/mochitest/browser.eslintrc.js",
+    "../../../../../testing/mochitest/mochitest.eslintrc.js",
   ]
-}
+};
rename from browser/base/content/test/newtab/.eslintrc
rename to browser/base/content/test/newtab/.eslintrc.js
--- a/browser/base/content/test/newtab/.eslintrc
+++ b/browser/base/content/test/newtab/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/base/content/test/plugins/.eslintrc
rename to browser/base/content/test/plugins/.eslintrc.js
--- a/browser/base/content/test/plugins/.eslintrc
+++ b/browser/base/content/test/plugins/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -60,17 +60,16 @@ skip-if = !crashreporter
 [browser_CTP_notificationBar.js]
 [browser_CTP_outsideScrollArea.js]
 [browser_CTP_remove_navigate.js]
 [browser_CTP_resize.js]
 [browser_CTP_zoom.js]
 [browser_blocking.js]
 [browser_plugins_added_dynamically.js]
 [browser_pluginnotification.js]
-[browser_plugin_infolink.js]
 [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]
--- a/browser/base/content/test/plugins/browser_bug797677.js
+++ b/browser/base/content/test/plugins/browser_bug797677.js
@@ -14,32 +14,28 @@ add_task(function* () {
     gBrowser.removeCurrentTab();
     window.focus();
     gTestBrowser = null;
   });
 
   gBrowser.selectedTab = gBrowser.addTab();
   gTestBrowser = gBrowser.selectedBrowser;
 
-  let bindingPromise = waitForEvent(gTestBrowser, "PluginBindingAttached", null, true, true);
-
   let consoleService = Cc["@mozilla.org/consoleservice;1"]
                          .getService(Ci.nsIConsoleService);
   let errorListener = {
     observe: function(aMessage) {
       if (aMessage.message.includes("NS_ERROR_FAILURE"))
         gConsoleErrors++;
     }
   };
   consoleService.registerListener(errorListener);
 
   yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_bug797677.html");
 
-  yield bindingPromise;
-
   let pluginInfo = yield promiseForPluginInfo("plugin");
   is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED, "plugin should not have been found.");
 
   // simple cpows
   let plugin = gTestBrowser.contentDocument.getElementById("plugin");
   ok(plugin, "plugin should be in the page");
   is(gConsoleErrors, 0, "should have no console errors");
 });
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_plugin_infolink.js
+++ /dev/null
@@ -1,48 +0,0 @@
-var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
-var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
-var oldBrowserOpenAddonsMgr = window.BrowserOpenAddonsMgr;
-
-registerCleanupFunction(function* cleanup() {
-  clearAllPluginPermissions();
-  Services.prefs.clearUserPref("plugins.click_to_play");
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
-  window.BrowserOpenAddonsMgr = oldBrowserOpenAddonsMgr;
-  window.focus();
-});
-
-add_task(function* test_clicking_manage_link_in_plugin_overlay_should_open_about_addons() {
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_DISABLED, "Test Plug-in");
-
-  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gTestRoot + "plugin_test.html");
-  let browser = tab.linkedBrowser;
-  yield promiseUpdatePluginBindings(browser);
-
-  let pluginInfo = yield promiseForPluginInfo("test", browser);
-  is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED,
-     "plugin fallback type should be PLUGIN_DISABLED");
-
-  let awaitBrowserOpenAddonsMgr = new Promise(resolve => {
-    window.BrowserOpenAddonsMgr = function(view) {
-      resolve(view);
-    }
-  });
-
-  yield ContentTask.spawn(browser, null, function* () {
-    let pluginNode = content.document.getElementById("test");
-    let manageLink = content.document.getAnonymousElementByAttribute(pluginNode, "anonid", "managePluginsLink");
-    let bounds = manageLink.getBoundingClientRect();
-    let left = (bounds.left + bounds.right) / 2;
-    let top = (bounds.top + bounds.bottom) / 2;
-    let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                       .getInterface(Components.interfaces.nsIDOMWindowUtils);
-    utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
-    utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
-    Assert.ok(true, "click on manage link");
-  });
-
-  let requestedView = yield awaitBrowserOpenAddonsMgr;
-  is(requestedView, "addons://list/plugin", "The Add-ons Manager should open the plugin view");
-
-  yield BrowserTestUtils.removeTab(tab);
-});
rename from browser/base/content/test/popupNotifications/.eslintrc
rename to browser/base/content/test/popupNotifications/.eslintrc.js
--- a/browser/base/content/test/popupNotifications/.eslintrc
+++ b/browser/base/content/test/popupNotifications/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/base/content/test/referrer/.eslintrc
rename to browser/base/content/test/referrer/.eslintrc.js
--- a/browser/base/content/test/referrer/.eslintrc
+++ b/browser/base/content/test/referrer/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/base/content/test/social/.eslintrc
rename to browser/base/content/test/social/.eslintrc.js
--- a/browser/base/content/test/social/.eslintrc
+++ b/browser/base/content/test/social/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1254,27 +1254,28 @@ file, You can obtain one at http://mozil
             var search = controller.getValueAt(this.selectedIndex);
 
             // close the autocomplete popup and revert the entered search term
             this.closePopup();
             controller.handleEscape();
 
             // open the search results according to the clicking subtlety
             var where = whereToOpenLink(aEvent, false, true);
+            let params = {};
 
             // But open ctrl/cmd clicks on autocomplete items in a new background tab.
             let modifier = this.AppConstants.platform == "macosx" ?
                            aEvent.metaKey :
                            aEvent.ctrlKey;
             if (where == "tab" && (aEvent instanceof MouseEvent) &&
                 (aEvent.button == 1 || modifier))
-              where = "tab-background";
+              params.inBackground = true;
 
-            searchBar.doSearch(search, where);
-            if (where == "tab-background")
+            searchBar.doSearch(search, where, null, params);
+            if (where == "tab" && params.inBackground)
               searchBar.focus();
             else
               searchBar.value = search;
           }
         ]]></body>
       </method>
     </implementation>
   </binding>
rename from browser/components/contextualidentity/test/browser/.eslintrc
rename to browser/components/contextualidentity/test/browser/.eslintrc.js
--- a/browser/components/contextualidentity/test/browser/.eslintrc
+++ b/browser/components/contextualidentity/test/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/customizableui/test/.eslintrc
rename to browser/components/customizableui/test/.eslintrc.js
--- a/browser/components/customizableui/test/.eslintrc
+++ b/browser/components/customizableui/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/dirprovider/tests/unit/.eslintrc
rename to browser/components/dirprovider/tests/unit/.eslintrc.js
--- a/browser/components/dirprovider/tests/unit/.eslintrc
+++ b/browser/components/dirprovider/tests/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/downloads/test/browser/.eslintrc
rename to browser/components/downloads/test/browser/.eslintrc.js
--- a/browser/components/downloads/test/browser/.eslintrc
+++ b/browser/components/downloads/test/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/downloads/test/unit/.eslintrc
rename to browser/components/downloads/test/unit/.eslintrc.js
--- a/browser/components/downloads/test/unit/.eslintrc
+++ b/browser/components/downloads/test/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/extensions/.eslintrc
rename to browser/components/extensions/.eslintrc.js
--- a/browser/components/extensions/.eslintrc
+++ b/browser/components/extensions/.eslintrc.js
@@ -1,10 +1,12 @@
-{
-  "extends": "../../../toolkit/components/extensions/.eslintrc",
+"use strict";
+
+module.exports = {  // eslint-disable-line no-undef
+  "extends": "../../../toolkit/components/extensions/.eslintrc.js",
 
   "globals": {
     "AllWindowEvents": true,
     "browserActionFor": true,
     "currentWindow": true,
     "EventEmitter": true,
     "getCookieStoreIdForTab": true,
     "IconDetails": true,
@@ -12,11 +14,9 @@
     "pageActionFor": true,
     "PanelPopup": true,
     "TabContext": true,
     "ViewPopup": true,
     "WindowEventManager": true,
     "WindowListManager": true,
     "WindowManager": true,
   },
-}
-
-
+};
rename from browser/components/extensions/test/browser/.eslintrc
rename to browser/components/extensions/test/browser/.eslintrc.js
--- a/browser/components/extensions/test/browser/.eslintrc
+++ b/browser/components/extensions/test/browser/.eslintrc.js
@@ -1,10 +1,12 @@
-{
-  "extends": "../../../../../testing/mochitest/browser.eslintrc",
+"use strict";
+
+module.exports = {  // eslint-disable-line no-undef
+  "extends": "../../../../../testing/mochitest/browser.eslintrc.js",
 
   "env": {
     "webextensions": true,
   },
 
   "globals": {
     "NetUtil": true,
     "XPCOMUtils": true,
@@ -21,10 +23,10 @@
     "clickPageAction": true,
     "closeContextMenu": true,
     "closeExtensionContextMenu": true,
     "focusWindow": true,
     "makeWidgetId": true,
     "openContextMenu": true,
     "openExtensionContextMenu": true,
     "CustomizableUI": true,
-  }
-}
+  },
+};
rename from browser/components/extensions/test/xpcshell/.eslintrc
rename to browser/components/extensions/test/xpcshell/.eslintrc.js
--- a/browser/components/extensions/test/xpcshell/.eslintrc
+++ b/browser/components/extensions/test/xpcshell/.eslintrc.js
@@ -1,7 +1,9 @@
-{
-  "extends": "../../../../../testing/xpcshell/xpcshell.eslintrc",
+"use strict";
+
+module.exports = {  // eslint-disable-line no-undef
+  "extends": "../../../../../testing/xpcshell/xpcshell.eslintrc.js",
 
   "globals": {
     "browser": false,
   },
-}
+};
rename from browser/components/feeds/test/.eslintrc
rename to browser/components/feeds/test/.eslintrc.js
--- a/browser/components/feeds/test/.eslintrc
+++ b/browser/components/feeds/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/mochitest.eslintrc"
+    "../../../../testing/mochitest/mochitest.eslintrc.js"
   ]
-}
+};
rename from browser/components/feeds/test/chrome/.eslintrc
rename to browser/components/feeds/test/chrome/.eslintrc.js
--- a/browser/components/feeds/test/chrome/.eslintrc
+++ b/browser/components/feeds/test/chrome/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/chrome.eslintrc"
+    "../../../../../testing/mochitest/chrome.eslintrc.js"
   ]
-}
+};
rename from browser/components/feeds/test/unit/.eslintrc
rename to browser/components/feeds/test/unit/.eslintrc.js
--- a/browser/components/feeds/test/unit/.eslintrc
+++ b/browser/components/feeds/test/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
--- a/browser/components/migration/360seProfileMigrator.js
+++ b/browser/components/migration/360seProfileMigrator.js
@@ -6,16 +6,17 @@
 
 const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource:///modules/MigrationUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
                                   "resource://gre/modules/Sqlite.jsm");
 
 const kBookmarksFileName = "360sefav.db";
--- a/browser/components/migration/ChromeProfileMigrator.js
+++ b/browser/components/migration/ChromeProfileMigrator.js
@@ -20,17 +20,16 @@ const AUTH_TYPE = {
 };
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Console.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource:///modules/MigrationUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OSCrypto",
                                   "resource://gre/modules/OSCrypto.jsm");
 /**
--- a/browser/components/migration/MigrationUtils.jsm
+++ b/browser/components/migration/MigrationUtils.jsm
@@ -4,16 +4,17 @@
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["MigrationUtils", "MigratorPrototype"];
 
 const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
 const TOPIC_WILL_IMPORT_BOOKMARKS = "initial-migration-will-import-default-bookmarks";
 const TOPIC_DID_IMPORT_BOOKMARKS = "initial-migration-did-import-default-bookmarks";
+const TOPIC_PLACES_DEFAULTS_FINISHED = "places-browser-init-complete";
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AutoMigrate",
                                   "resource:///modules/AutoMigrate.jsm");
@@ -318,38 +319,45 @@ this.MigratorPrototype = {
 
           yield unblockMainThread();
         }
       }
     });
 
     if (MigrationUtils.isStartupMigration && !this.startupOnlyMigrator) {
       MigrationUtils.profileStartup.doStartup();
-
-      // If we're about to migrate bookmarks, first import the default bookmarks.
-      // Note We do not need to do so for the Firefox migrator
+      // First import the default bookmarks.
+      // Note: We do not need to do so for the Firefox migrator
       // (=startupOnlyMigrator), as it just copies over the places database
       // from another profile.
-      const BOOKMARKS = MigrationUtils.resourceTypes.BOOKMARKS;
-      let migratingBookmarks = resources.some(r => r.type == BOOKMARKS);
-      if (migratingBookmarks) {
+      Task.spawn(function* () {
+        // Tell nsBrowserGlue we're importing default bookmarks.
         let browserGlue = Cc["@mozilla.org/browser/browserglue;1"].
                           getService(Ci.nsIObserver);
         browserGlue.observe(null, TOPIC_WILL_IMPORT_BOOKMARKS, "");
 
-        // Note doMigrate doesn't care about the success of the import.
-        let onImportComplete = function() {
-          browserGlue.observe(null, TOPIC_DID_IMPORT_BOOKMARKS, "");
-          doMigrate();
-        };
-        BookmarkHTMLUtils.importFromURL(
-          "chrome://browser/locale/bookmarks.html", true).then(
-          onImportComplete, onImportComplete);
-        return;
-      }
+        // Import the default bookmarks. We ignore whether or not we succeed.
+        yield BookmarkHTMLUtils.importFromURL(
+          "chrome://browser/locale/bookmarks.html", true).catch(r => r);
+
+        // We'll tell nsBrowserGlue we've imported bookmarks, but before that
+        // we need to make sure we're going to know when it's finished
+        // initializing places:
+        let placesInitedPromise = new Promise(resolve => {
+          let onPlacesInited = function() {
+            Services.obs.removeObserver(onPlacesInited, TOPIC_PLACES_DEFAULTS_FINISHED);
+            resolve();
+          };
+          Services.obs.addObserver(onPlacesInited, TOPIC_PLACES_DEFAULTS_FINISHED, false);
+        });
+        browserGlue.observe(null, TOPIC_DID_IMPORT_BOOKMARKS, "");
+        yield placesInitedPromise;
+        doMigrate();
+      });
+      return;
     }
     doMigrate();
   },
 
   /**
    * DO NOT OVERRIDE - After deCOMing migration, this code
    * won't be part of the migrator itself.
    *
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -420,17 +420,22 @@ var MigrationWizard = {
       break;
     case "Migration:ItemAfterMigrate":
       label = document.getElementById(aData + "_migrated");
       if (label)
         label.removeAttribute("style");
       break;
     case "Migration:Ended":
       if (this.isInitialMigration) {
-        this.reportDataRecencyTelemetry();
+        // Ensure errors in reporting data recency do not affect the rest of the migration.
+        try {
+          this.reportDataRecencyTelemetry();
+        } catch (ex) {
+          Cu.reportError(ex);
+        }
       }
       if (this._autoMigrate) {
         let hasImportedHomepage = !!(this._newHomePage && this._newHomePage != "DEFAULT");
         Services.telemetry.getKeyedHistogramById("FX_MIGRATION_IMPORTED_HOMEPAGE")
                           .add(this._source, hasImportedHomepage);
         if (this._newHomePage) {
           try {
             // set homepage properly
rename from browser/components/migration/tests/unit/.eslintrc
rename to browser/components/migration/tests/unit/.eslintrc.js
--- a/browser/components/migration/tests/unit/.eslintrc
+++ b/browser/components/migration/tests/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/newtab/tests/browser/.eslintrc
rename to browser/components/newtab/tests/browser/.eslintrc.js
--- a/browser/components/newtab/tests/browser/.eslintrc
+++ b/browser/components/newtab/tests/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/newtab/tests/xpcshell/.eslintrc
rename to browser/components/newtab/tests/xpcshell/.eslintrc.js
--- a/browser/components/newtab/tests/xpcshell/.eslintrc
+++ b/browser/components/newtab/tests/xpcshell/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1594,18 +1594,22 @@ BrowserGlue.prototype = {
       // If bookmarks are not imported, then initialize smart bookmarks.  This
       // happens during a common startup.
       // Otherwise, if any kind of import runs, smart bookmarks creation should be
       // delayed till the import operations has finished.  Not doing so would
       // cause them to be overwritten by the newly imported bookmarks.
       if (!importBookmarks) {
         // Now apply distribution customized bookmarks.
         // This should always run after Places initialization.
-        yield this._distributionCustomizer.applyBookmarks();
-        yield this.ensurePlacesDefaultQueriesInitialized();
+        try {
+          yield this._distributionCustomizer.applyBookmarks();
+          yield this.ensurePlacesDefaultQueriesInitialized();
+        } catch (e) {
+          Cu.reportError(e);
+        }
       }
       else {
         // An import operation is about to run.
         // Don't try to recreate smart bookmarks if autoExportHTML is true or
         // smart bookmarks are disabled.
         let smartBookmarksVersion = 0;
         try {
           smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
@@ -1637,17 +1641,17 @@ BrowserGlue.prototype = {
             // complete.
             yield this.ensurePlacesDefaultQueriesInitialized();
           } catch (e) {
             Cu.reportError(e);
           }
 
         }
         else {
-          Cu.reportError("Unable to find bookmarks.html file.");
+          Cu.reportError(new Error("Unable to find bookmarks.html file."));
         }
 
         // Reset preferences, so we won't try to import again at next run
         if (importBookmarksHTML)
           Services.prefs.setBoolPref("browser.places.importBookmarksHTML", false);
         if (restoreDefaultBookmarks)
           Services.prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
                                      false);
@@ -1674,28 +1678,33 @@ BrowserGlue.prototype = {
           if (profileLastUse > lastBackupTime) {
             let backupAge = Math.round((profileLastUse - lastBackupTime) / 86400000);
             // Report the age of the last available backup.
             try {
               Services.telemetry
                       .getHistogramById("PLACES_BACKUPS_DAYSFROMLAST")
                       .add(backupAge);
             } catch (ex) {
-              Cu.reportError("Unable to report telemetry.");
+              Cu.reportError(new Error("Unable to report telemetry."));
             }
 
             if (backupAge > BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS)
               this._bookmarksBackupIdleTime /= 2;
           }
         }
         this._idleService.addIdleObserver(this, this._bookmarksBackupIdleTime);
       }
 
+    }.bind(this)).catch(ex => {
+      Cu.reportError(ex);
+    }).then(() => {
+      // NB: deliberately after the catch so that we always do this, even if
+      // we threw halfway through initializing in the Task above.
       Services.obs.notifyObservers(null, "places-browser-init-complete", "");
-    }.bind(this));
+    });
   },
 
   /**
    * Places shut-down tasks
    * - finalize components depending on Places.
    * - export bookmarks as HTML, if so configured.
    */
   _onPlacesShutdown: function BG__onPlacesShutdown() {
rename from browser/components/originattributes/test/browser/.eslintrc
rename to browser/components/originattributes/test/browser/.eslintrc.js
--- a/browser/components/originattributes/test/browser/.eslintrc
+++ b/browser/components/originattributes/test/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/places/tests/browser/.eslintrc
rename to browser/components/places/tests/browser/.eslintrc.js
--- a/browser/components/places/tests/browser/.eslintrc
+++ b/browser/components/places/tests/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/places/tests/chrome/.eslintrc
rename to browser/components/places/tests/chrome/.eslintrc.js
--- a/browser/components/places/tests/chrome/.eslintrc
+++ b/browser/components/places/tests/chrome/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/chrome.eslintrc"
+    "../../../../../testing/mochitest/chrome.eslintrc.js"
   ]
-}
+};
rename from browser/components/places/tests/unit/.eslintrc
rename to browser/components/places/tests/unit/.eslintrc.js
--- a/browser/components/places/tests/unit/.eslintrc
+++ b/browser/components/places/tests/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/preferences/in-content/tests/.eslintrc
rename to browser/components/preferences/in-content/tests/.eslintrc.js
--- a/browser/components/preferences/in-content/tests/.eslintrc
+++ b/browser/components/preferences/in-content/tests/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/privatebrowsing/test/browser/.eslintrc
rename to browser/components/privatebrowsing/test/browser/.eslintrc.js
--- a/browser/components/privatebrowsing/test/browser/.eslintrc
+++ b/browser/components/privatebrowsing/test/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/safebrowsing/content/test/.eslintrc
rename to browser/components/safebrowsing/content/test/.eslintrc.js
--- a/browser/components/safebrowsing/content/test/.eslintrc
+++ b/browser/components/safebrowsing/content/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
+    "../../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/search/test/.eslintrc
rename to browser/components/search/test/.eslintrc.js
--- a/browser/components/search/test/.eslintrc
+++ b/browser/components/search/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/selfsupport/test/.eslintrc
rename to browser/components/selfsupport/test/.eslintrc.js
--- a/browser/components/selfsupport/test/.eslintrc
+++ b/browser/components/selfsupport/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/sessionstore/test/.eslintrc
rename to browser/components/sessionstore/test/.eslintrc.js
--- a/browser/components/sessionstore/test/.eslintrc
+++ b/browser/components/sessionstore/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/sessionstore/test/unit/.eslintrc
rename to browser/components/sessionstore/test/unit/.eslintrc.js
--- a/browser/components/sessionstore/test/unit/.eslintrc
+++ b/browser/components/sessionstore/test/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/shell/test/.eslintrc
rename to browser/components/shell/test/.eslintrc.js
--- a/browser/components/shell/test/.eslintrc
+++ b/browser/components/shell/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/shell/test/unit/.eslintrc
rename to browser/components/shell/test/unit/.eslintrc.js
--- a/browser/components/shell/test/unit/.eslintrc
+++ b/browser/components/shell/test/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/tests/browser/.eslintrc
rename to browser/components/tests/browser/.eslintrc.js
--- a/browser/components/tests/browser/.eslintrc
+++ b/browser/components/tests/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/translation/test/.eslintrc
rename to browser/components/translation/test/.eslintrc.js
--- a/browser/components/translation/test/.eslintrc
+++ b/browser/components/translation/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/components/translation/test/unit/.eslintrc
rename to browser/components/translation/test/unit/.eslintrc.js
--- a/browser/components/translation/test/unit/.eslintrc
+++ b/browser/components/translation/test/unit/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/components/uitour/test/.eslintrc
rename to browser/components/uitour/test/.eslintrc.js
--- a/browser/components/uitour/test/.eslintrc
+++ b/browser/components/uitour/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/experiments/test/xpcshell/.eslintrc
rename to browser/experiments/test/xpcshell/.eslintrc.js
--- a/browser/experiments/test/xpcshell/.eslintrc
+++ b/browser/experiments/test/xpcshell/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/extensions/formautofill/.eslintrc
rename to browser/extensions/formautofill/.eslintrc.js
--- a/browser/extensions/formautofill/.eslintrc
+++ b/browser/extensions/formautofill/.eslintrc.js
@@ -1,10 +1,12 @@
-{
-  "extends": "../../.eslintrc",
+"use strict";
+
+module.exports = { // eslint-disable-line no-undef
+  "extends": "../../.eslintrc.js",
 
   "globals": {
     "Components": true,
     "dump": true,
     "TextDecoder": false,
     "TextEncoder": false,
   },
 
@@ -328,17 +330,17 @@
 
     // Allow the use of leading or trailing decimal points in numeric literals.
     "no-floating-decimal": 0,
 
     // Allow comments inline after code.
     "no-inline-comments": 0,
 
     // Disallow use of labels for anything other then loops and switches.
-    "no-labels": [2, { "allowLoop": true }],
+    "no-labels": [2, {"allowLoop": true}],
 
     // Disallow use of multiline strings (use template strings instead).
     "no-multi-str": 1,
 
     // Disallow multiple empty lines.
     "no-multiple-empty-lines": [1, {"max": 2}],
 
     // Allow reassignment of function parameters.
@@ -464,10 +466,10 @@
     // Disallow usage of __iterator__ property
     "no-iterator": 2,
 
     // Disallow labels that share a name with a variable
     "no-label-var": 2,
 
     // Disallow creating new instances of String, Number, and Boolean
     "no-new-wrappers": 2,
-  }
-}
+  },
+};
rename from browser/extensions/formautofill/test/browser/.eslintrc
rename to browser/extensions/formautofill/test/browser/.eslintrc.js
--- a/browser/extensions/formautofill/test/browser/.eslintrc
+++ b/browser/extensions/formautofill/test/browser/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = { // eslint-disable-line no-undef
   "extends": [
-    "../../../../../testing/mochitest/browser.eslintrc"
-  ]
-}
+    "../../../../../testing/mochitest/browser.eslintrc.js",
+  ],
+};
rename from browser/extensions/pdfjs/test/.eslintrc
rename to browser/extensions/pdfjs/test/.eslintrc.js
--- a/browser/extensions/pdfjs/test/.eslintrc
+++ b/browser/extensions/pdfjs/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/mochitest/browser.eslintrc"
+    "../../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -340,18 +340,16 @@
 @RESPATH@/components/xpconnect.xpt
 @RESPATH@/components/xulapp.xpt
 @RESPATH@/components/xul.xpt
 @RESPATH@/components/xultmpl.xpt
 @RESPATH@/components/zipwriter.xpt
 @RESPATH@/components/telemetry.xpt
 
 ; JavaScript components
-@RESPATH@/components/ChromeNotifications.js
-@RESPATH@/components/ChromeNotifications.manifest
 @RESPATH@/components/ConsoleAPI.manifest
 @RESPATH@/components/ConsoleAPIStorage.js
 @RESPATH@/components/BrowserElementParent.manifest
 @RESPATH@/components/BrowserElementParent.js
 @RESPATH@/components/BrowserElementProxy.manifest
 @RESPATH@/components/BrowserElementProxy.js
 @RESPATH@/components/FeedProcessor.manifest
 @RESPATH@/components/FeedProcessor.js
rename from browser/modules/test/.eslintrc
rename to browser/modules/test/.eslintrc.js
--- a/browser/modules/test/.eslintrc
+++ b/browser/modules/test/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../testing/mochitest/browser.eslintrc"
+    "../../../testing/mochitest/browser.eslintrc.js"
   ]
-}
+};
rename from browser/modules/test/unit/social/.eslintrc
rename to browser/modules/test/unit/social/.eslintrc.js
--- a/browser/modules/test/unit/social/.eslintrc
+++ b/browser/modules/test/unit/social/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
rename from browser/modules/test/xpcshell/.eslintrc
rename to browser/modules/test/xpcshell/.eslintrc.js
--- a/browser/modules/test/xpcshell/.eslintrc
+++ b/browser/modules/test/xpcshell/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "extends": [
-    "../../../../testing/xpcshell/xpcshell.eslintrc"
+    "../../../../testing/xpcshell/xpcshell.eslintrc.js"
   ]
-}
+};
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -194,16 +194,21 @@ private:
  *  This is a companion checker for OverrideBaseCallChecker that rejects
  *  the usage of MOZ_REQUIRED_BASE_METHOD on non-virtual base methods.
  */
   class OverrideBaseCallUsageChecker : public MatchFinder::MatchCallback {
   public:
     virtual void run(const MatchFinder::MatchResult &Result);
   };
 
+  class NonParamInsideFunctionDeclChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
   ScopeChecker Scope;
   ArithmeticArgChecker ArithmeticArg;
   TrivialCtorDtorChecker TrivialCtorDtor;
   NaNExprChecker NaNExpr;
   NoAddRefReleaseOnReturnChecker NoAddRefReleaseOnReturn;
   RefCountedInsideLambdaChecker RefCountedInsideLambda;
   ExplicitOperatorBoolChecker ExplicitOperatorBool;
   NoDuplicateRefCntMemberChecker NoDuplicateRefCntMember;
@@ -214,16 +219,17 @@ private:
   NoAutoTypeChecker NoAutoType;
   NoExplicitMoveConstructorChecker NoExplicitMoveConstructor;
   RefCountedCopyConstructorChecker RefCountedCopyConstructor;
   AssertAssignmentChecker AssertAttribution;
   KungFuDeathGripChecker KungFuDeathGrip;
   SprintfLiteralChecker SprintfLiteral;
   OverrideBaseCallChecker OverrideBaseCall;
   OverrideBaseCallUsageChecker OverrideBaseCallUsage;
+  NonParamInsideFunctionDeclChecker NonParamInsideFunctionDecl;
   MatchFinder AstMatcher;
 };
 
 namespace {
 
 std::string getDeclarationNamespace(const Decl *Declaration) {
   const DeclContext *DC =
       Declaration->getDeclContext()->getEnclosingNamespaceContext();
@@ -491,16 +497,18 @@ static CustomTypeAnnotation GlobalClass 
 static CustomTypeAnnotation NonHeapClass =
     CustomTypeAnnotation("moz_nonheap_class", "non-heap");
 static CustomTypeAnnotation HeapClass =
     CustomTypeAnnotation("moz_heap_class", "heap");
 static CustomTypeAnnotation NonTemporaryClass =
     CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
 static CustomTypeAnnotation MustUse =
     CustomTypeAnnotation("moz_must_use_type", "must-use");
+static CustomTypeAnnotation NonParam =
+    CustomTypeAnnotation("moz_non_param", "non-param");
 
 class MemMoveAnnotation final : public CustomTypeAnnotation {
 public:
   MemMoveAnnotation()
       : CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able") {}
 
   virtual ~MemMoveAnnotation() {}
 
@@ -1324,16 +1332,27 @@ DiagnosticsMatcher::DiagnosticsMatcher()
   );
 
   AstMatcher.addMatcher(cxxRecordDecl(hasBaseClasses()).bind("class"),
       &OverrideBaseCall);
 
   AstMatcher.addMatcher(
       cxxMethodDecl(isNonVirtual(), isRequiredBaseMethod()).bind("method"),
       &OverrideBaseCallUsage);
+
+  AstMatcher.addMatcher(
+      functionDecl(anyOf(allOf(isDefinition(),
+                               hasAncestor(classTemplateSpecializationDecl()
+                                               .bind("spec"))),
+                         isDefinition()))
+          .bind("func"),
+      &NonParamInsideFunctionDecl);
+  AstMatcher.addMatcher(
+      lambdaExpr().bind("lambda"),
+      &NonParamInsideFunctionDecl);
 }
 
 // These enum variants determine whether an allocation has occured in the code.
 enum AllocationVariety {
   AV_None,
   AV_Global,
   AV_Automatic,
   AV_Temporary,
@@ -2128,16 +2147,67 @@ void DiagnosticsMatcher::OverrideBaseCal
   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
       DiagnosticIDs::Error,
       "MOZ_REQUIRED_BASE_METHOD can be used only on virtual methods");
   const CXXMethodDecl *Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
 
   Diag.Report(Method->getLocation(), ErrorID);
 }
 
+void DiagnosticsMatcher::NonParamInsideFunctionDeclChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  static DenseSet<const FunctionDecl*> CheckedFunctionDecls;
+
+  const FunctionDecl *func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  if (!func) {
+    const LambdaExpr *lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
+    if (lambda) {
+      func = lambda->getCallOperator();
+    }
+  }
+
+  if (!func) {
+    return;
+  }
+
+  if (func->isDeleted()) {
+    return;
+  }
+
+  // Don't report errors on the same declarations more than once.
+  if (CheckedFunctionDecls.count(func)) {
+    return;
+  }
+  CheckedFunctionDecls.insert(func);
+
+  const ClassTemplateSpecializationDecl *Spec =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("spec");
+
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "Type %0 must not be used as parameter");
+  unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "Please consider passing a const reference instead");
+  unsigned SpecNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "The bad argument was passed to %0 here");
+
+  for (ParmVarDecl *p : func->parameters()) {
+    QualType T = p->getType().withoutLocalFastQualifiers();
+    if (NonParam.hasEffectiveAnnotation(T)) {
+      Diag.Report(p->getLocation(), ErrorID) << T;
+      Diag.Report(p->getLocation(), NoteID);
+
+      if (Spec) {
+        Diag.Report(Spec->getPointOfInstantiation(), SpecNoteID)
+          << Spec->getSpecializedTemplate();
+      }
+    }
+  }
+}
+
 class MozCheckAction : public PluginASTAction {
 public:
   ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI,
                                    StringRef FileName) override {
 #if CLANG_VERSION_FULL >= 306
     std::unique_ptr<MozChecker> Checker(llvm::make_unique<MozChecker>(CI));
     ASTConsumerPtr Other(Checker->getOtherConsumer());
 
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/tests/NonParameterTestCases.h
@@ -0,0 +1,61 @@
+MAYBE_STATIC void raw(Param x) {}
+
+MAYBE_STATIC void raw(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(NonParamUnion x) {} //expected-error {{Type 'NonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(NonParamClass x) {} //expected-error {{Type 'NonParamClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(NonParamEnum x) {} //expected-error {{Type 'NonParamEnum' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(NonParamEnumClass x) {} //expected-error {{Type 'NonParamEnumClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void raw(HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+
+MAYBE_STATIC void const_(const NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const NonParamUnion x) {} //expected-error {{Type 'NonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const NonParamClass x) {} //expected-error {{Type 'NonParamClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const NonParamEnum x) {} //expected-error {{Type 'NonParamEnum' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const NonParamEnumClass x) {} //expected-error {{Type 'NonParamEnumClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC void const_(const HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+
+MAYBE_STATIC void array(NonParam x[]) {}
+MAYBE_STATIC void array(NonParamUnion x[]) {}
+MAYBE_STATIC void array(NonParamClass x[]) {}
+MAYBE_STATIC void array(NonParamEnum x[]) {}
+MAYBE_STATIC void array(NonParamEnumClass x[]) {}
+MAYBE_STATIC void array(HasNonParamStruct x[]) {}
+MAYBE_STATIC void array(HasNonParamUnion x[]) {}
+MAYBE_STATIC void array(HasNonParamStructUnion x[]) {}
+
+MAYBE_STATIC void ptr(NonParam* x) {}
+MAYBE_STATIC void ptr(NonParamUnion* x) {}
+MAYBE_STATIC void ptr(NonParamClass* x) {}
+MAYBE_STATIC void ptr(NonParamEnum* x) {}
+MAYBE_STATIC void ptr(NonParamEnumClass* x) {}
+MAYBE_STATIC void ptr(HasNonParamStruct* x) {}
+MAYBE_STATIC void ptr(HasNonParamUnion* x) {}
+MAYBE_STATIC void ptr(HasNonParamStructUnion* x) {}
+
+MAYBE_STATIC void ref(NonParam& x) {}
+MAYBE_STATIC void ref(NonParamUnion& x) {}
+MAYBE_STATIC void ref(NonParamClass& x) {}
+MAYBE_STATIC void ref(NonParamEnum& x) {}
+MAYBE_STATIC void ref(NonParamEnumClass& x) {}
+MAYBE_STATIC void ref(HasNonParamStruct& x) {}
+MAYBE_STATIC void ref(HasNonParamUnion& x) {}
+MAYBE_STATIC void ref(HasNonParamStructUnion& x) {}
+
+MAYBE_STATIC void constRef(const NonParam& x) {}
+MAYBE_STATIC void constRef(const NonParamUnion& x) {}
+MAYBE_STATIC void constRef(const NonParamClass& x) {}
+MAYBE_STATIC void constRef(const NonParamEnum& x) {}
+MAYBE_STATIC void constRef(const NonParamEnumClass& x) {}
+MAYBE_STATIC void constRef(const HasNonParamStruct& x) {}
+MAYBE_STATIC void constRef(const HasNonParamUnion& x) {}
+MAYBE_STATIC void constRef(const HasNonParamStructUnion& x) {}
+
+MAYBE_STATIC inline void inlineRaw(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC inline void inlineRaw(NonParamUnion x) {} //expected-error {{Type 'NonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC inline void inlineRaw(NonParamClass x) {} //expected-error {{Type 'NonParamClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC inline void inlineRaw(NonParamEnum x) {} //expected-error {{Type 'NonParamEnum' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+MAYBE_STATIC inline void inlineRaw(NonParamEnumClass x) {} //expected-error {{Type 'NonParamEnumClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/tests/TestNonParameterChecker.cpp
@@ -0,0 +1,179 @@
+#define MOZ_NON_PARAM __attribute__((annotate("moz_non_param")))
+
+struct Param {};
+struct MOZ_NON_PARAM NonParam {};
+union MOZ_NON_PARAM NonParamUnion {};
+class MOZ_NON_PARAM NonParamClass {};
+enum MOZ_NON_PARAM NonParamEnum { X, Y, Z };
+enum class MOZ_NON_PARAM NonParamEnumClass { X, Y, Z };
+
+struct HasNonParamStruct { NonParam x; int y; };
+union HasNonParamUnion { NonParam x; int y; };
+struct HasNonParamStructUnion { HasNonParamUnion z; };
+
+#define MAYBE_STATIC
+#include "NonParameterTestCases.h"
+#undef MAYBE_STATIC
+
+// Do not check typedef and using.
+typedef void (*funcTypeParam)(Param x);
+typedef void (*funcTypeNonParam)(NonParam x);
+
+using usingFuncTypeParam = void (*)(Param x);
+using usingFuncTypeNonParam = void (*)(NonParam x);
+
+class class_
+{
+    explicit class_(Param x) {}
+    explicit class_(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    explicit class_(HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    explicit class_(HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    explicit class_(HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+
+#define MAYBE_STATIC
+#include "NonParameterTestCases.h"
+#undef MAYBE_STATIC
+};
+
+class classWithStatic
+{
+#define MAYBE_STATIC static
+#include "NonParameterTestCases.h"
+#undef MAYBE_STATIC
+};
+
+template <typename T>
+class tmplClassForParam
+{
+public:
+    void raw(T x) {}
+    void rawDefault(T x = T()) {}
+    void const_(const T x) {}
+    void ptr(T* x) {}
+    void ref(T& x) {}
+    void constRef(const T& x) {}
+
+    void notCalled(T x) {}
+};
+
+template <typename T>
+class tmplClassForNonParam
+{
+public:
+    void raw(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    void rawDefault(T x = T()) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    void const_(const T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    void ptr(T* x) {}
+    void ref(T& x) {}
+    void constRef(const T& x) {}
+
+    void notCalled(T x) {}
+};
+
+template <typename T>
+class tmplClassForHasNonParamStruct
+{
+public:
+    void raw(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    void rawDefault(T x = T()) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    void const_(const T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    void ptr(T* x) {}
+    void ref(T& x) {}
+    void constRef(const T& x) {}
+
+    void notCalled(T x) {}
+};
+
+void testTemplateClass()
+{
+    tmplClassForParam<Param> paramClass;
+    Param param;
+    paramClass.raw(param);
+    paramClass.rawDefault();
+    paramClass.const_(param);
+    paramClass.ptr(&param);
+    paramClass.ref(param);
+    paramClass.constRef(param);
+
+    tmplClassForNonParam<NonParam> nonParamClass; //expected-note 3 {{The bad argument was passed to 'tmplClassForNonParam' here}}
+    NonParam nonParam;
+    nonParamClass.raw(nonParam);
+    nonParamClass.rawDefault();
+    nonParamClass.const_(nonParam);
+    nonParamClass.ptr(&nonParam);
+    nonParamClass.ref(nonParam);
+    nonParamClass.constRef(nonParam);
+
+    tmplClassForHasNonParamStruct<HasNonParamStruct> hasNonParamStructClass;//expected-note 3 {{The bad argument was passed to 'tmplClassForHasNonParamStruct' here}}
+    HasNonParamStruct hasNonParamStruct;
+    hasNonParamStructClass.raw(hasNonParamStruct);
+    hasNonParamStructClass.rawDefault();
+    hasNonParamStructClass.const_(hasNonParamStruct);
+    hasNonParamStructClass.ptr(&hasNonParamStruct);
+    hasNonParamStructClass.ref(hasNonParamStruct);
+    hasNonParamStructClass.constRef(hasNonParamStruct);
+}
+
+template <typename T>
+class NestedTemplateInner
+{
+public:
+    void raw(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+};
+
+template <typename T>
+class nestedTemplateOuter
+{
+public:
+    void constRef(const T& x) {
+        NestedTemplateInner<T> inner; //expected-note {{The bad argument was passed to 'NestedTemplateInner' here}}
+        inner.raw(x);
+    }
+};
+
+void testNestedTemplateClass()
+{
+    nestedTemplateOuter<NonParam> outer;
+    NonParam nonParam;
+    outer.constRef(nonParam); // FIXME: this line needs note "The bad argument was passed to 'constRef' here"
+}
+
+template <typename T>
+void tmplFuncForParam(T x) {}
+template <typename T>
+void tmplFuncForNonParam(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+template <typename T>
+void tmplFuncForNonParamImplicit(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+template <typename T>
+void tmplFuncForHasNonParamStruct(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+template <typename T>
+void tmplFuncForHasNonParamStructImplicit(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+
+void testTemplateFunc()
+{
+    Param param;
+    tmplFuncForParam<Param>(param);
+
+    NonParam nonParam;
+    tmplFuncForNonParam<NonParam>(nonParam); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForNonParam' here"
+    tmplFuncForNonParamImplicit(nonParam); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForNonParamImplicit' here"
+
+    HasNonParamStruct hasNonParamStruct;
+    tmplFuncForHasNonParamStruct<HasNonParamStruct>(hasNonParamStruct); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForHasNonParamStruct' here"
+    tmplFuncForHasNonParamStructImplicit(hasNonParamStruct); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForHasNonParamStructImplicit' here"
+}
+
+void testLambda()
+{
+    auto paramLambda = [](Param x) -> void {};
+    auto nonParamLambda = [](NonParam x) -> void {}; //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    auto nonParamStructLambda = [](HasNonParamStruct x) -> void {}; //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    auto nonParamUnionLambda = [](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    auto nonParamStructUnionLambda = [](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+
+    (void)[](Param x) -> void {};
+    (void)[](NonParam x) -> void {}; //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    (void)[](HasNonParamStruct x) -> void {}; //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    (void)[](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+    (void)[](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
+}
--- a/build/clang-plugin/tests/moz.build
+++ b/build/clang-plugin/tests/moz.build
@@ -25,16 +25,17 @@ SOURCES += [
     'TestNoAddRefReleaseOnReturn.cpp',
     'TestNoArithmeticExprInArgument.cpp',
     'TestNoAutoType.cpp',
     'TestNoDuplicateRefCntMember.cpp',
     'TestNoExplicitMoveConstructor.cpp',
     'TestNonHeapClass.cpp',
     'TestNonMemMovable.cpp',
     'TestNonMemMovableStd.cpp',
+    'TestNonParameterChecker.cpp',
     'TestNonTemporaryClass.cpp',
     'TestNoRefcountedInsideLambdas.cpp',
     'TestOverrideBaseCall.cpp',
     'TestOverrideBaseCallAnnotation.cpp',
     'TestRefCountedCopyConstructor.cpp',
     'TestSprintfLiteral.cpp',
     'TestStackClass.cpp',
     'TestTrivialCtorDtor.cpp',
--- a/config/external/moz.build
+++ b/config/external/moz.build
@@ -56,9 +56,12 @@ external_dirs += [
     'media/libopus',
     'media/libtheora',
     'media/libspeex_resampler',
     'media/libstagefright',
     'media/libsoundtouch',
     'media/psshparser'
 ]
 
+if CONFIG['MOZ_LINKER']:
+    external_dirs += ['modules/xz-embedded']
+
 DIRS += ['../../' + i for i in external_dirs]
rename from devtools/.eslintrc
rename to devtools/.eslintrc.js
--- a/devtools/.eslintrc
+++ b/devtools/.eslintrc.js
@@ -1,9 +1,11 @@
-{
+"use strict";
+
+module.exports = {
   "plugins": [
     "react"
   ],
   "globals": {
     "atob": true,
     "btoa": true,
     "Components": true,
     "CSSRule": true,
@@ -145,17 +147,20 @@
     // Enforces spacing between keys and values in object literal properties.
     "key-spacing": [2, {"beforeColon": false, "afterColon": true}],
     // Allow mixed 'LF' and 'CRLF' as linebreaks.
     "linebreak-style": 0,
     // Don't enforce the maximum depth that blocks can be nested. The complexity
     // rule is a better rule to check this.
     "max-depth": 0,
     // Maximum length of a line.
-    "max-len": [2, 90, 2, {"ignoreUrls": true, "ignorePattern": "data:image\/|\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-"}],
+    "max-len": [2, 90, 2, {
+      "ignoreUrls": true,
+      "ignorePattern": "data:image\/|\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-"
+    }],
     // Maximum depth callbacks can be nested.
     "max-nested-callbacks": [2, 3],
     // Don't limit the number of parameters that can be used in a function.
     "max-params": 0,
     // Don't limit the maximum number of statement allowed in a function. We
     // already have the complexity rule that's a better measurement.
     "max-statements": 0,
     // Require a capital letter for constructors, only check if all new
@@ -316,17 +321,18 @@
     "no-underscore-dangle": 0,
     // Allow use of undefined variable.
     "no-undefined": 0,
     // Disallow the use of Boolean literals in conditional expressions.
     "no-unneeded-ternary": 2,
     // Disallow unreachable statements after a return, throw, continue, or break
     // statement.
     "no-unreachable": 2,
-    // Disallow global and local variables that aren't used, but allow unused function arguments.
+    // Disallow global and local variables that aren't used, but allow unused
+    // function arguments.
     "no-unused-vars": [2, {"vars": "all", "args": "none"}],
     // Allow using variables before they are defined.
     "no-use-before-define": 0,
     // We use var-only-at-top-level instead of no-var as we allow top level
     // vars.
     "no-var": 0,
     // Allow using TODO/FIXME comments.
     "no-warning-comments": 0,
@@ -459,9 +465,9 @@
     // disallow wrapping of non-IIFE statements in parens
     "no-wrap-func": 0,
     // require assignment operator shorthand where possible or prohibit it
     // entirely
     "operator-assignment": 0,
     // enforce operators to be placed before or after line breaks
     "operator-linebreak": 0,
   }
-}
+};
rename from devtools/.eslintrc.mochitests
rename to devtools/.eslintrc.mochitests.js
--- a/devtools/.eslintrc.mochitests
+++ b/devtools/.eslintrc.mochitests.js
@@ -1,20 +1,20 @@
 // Parent config file for all devtools browser mochitest files.
-{
+module.exports = {
   "extends": [
-    "../testing/mochitest/browser.eslintrc"
+    "../testing/mochitest/browser.eslintrc.js"
   ],
   // All globals made available in the test environment.
   "globals": {
     "DevToolsUtils": true,
     "gDevTools": true,
     "once": true,
     "synthesizeKeyFromKeyTag": true,
     "TargetFactory": true,
     "waitForTick": true,
   },
 
   "rules": {
     // Tests can always import anything.
     "mozilla/reject-some-requires": 0,
   },
-}
+};
rename from devtools/.eslintrc.xpcshell
rename to devtools/.eslintrc.xpcshell.js
--- a/devtools/.eslintrc.xpcshell
+++ b/devtools/.eslintrc.xpcshell.js
@@ -1,21 +1,21 @@
 // Parent config file for all devtools xpcshell files.
-{
+module.exports = {
   "extends": [
-    "../testing/xpcshell/xpcshell.eslintrc"
+    "../testing/xpcshell/xpcshell.eslintrc.js"
   ],
   "rules": {
     // Allow non-camelcase so that run_test doesn't produce a warning.
     "camelcase": 0,
     // Allow using undefined variables so that tests can refer to functions
     // and variables defined in head.js files, without having to maintain a
     // list of globals in each .eslintrc file.
     // Note that bug 1168340 will eventually help auto-registering globals
     // from head.js files.
     "no-undef": 0,
     "block-scoped-var": 0,
     // Allow run_test to be unused in xpcshell
     "no-unused-vars": [2, { "varsIgnorePattern": "run_test" }],
     // Tests can always import anything.
     "mozilla/reject-some-requires": 0,
   }
-}
+};
rename from devtools/client/aboutdebugging/test/.eslintrc
rename to devtools/client/aboutdebugging/test/.eslintrc.js
--- a/devtools/client/aboutdebugging/test/.eslintrc
+++ b/devtools/client/aboutdebugging/test/.eslintrc.js
@@ -1,11 +1,13 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests",
+  "extends": "../../../.eslintrc.mochitests.js",
   // All globals made available in aboutdebugging head.js file.
   "globals": {
     "AddonManager": true,
     "addTab": true,
     "assertHasTarget": true,
     "CHROME_ROOT": true,
     "changeAboutDebuggingHash": true,
     "closeAboutDebugging": true,
@@ -16,9 +18,9 @@
     "openPanel": true,
     "removeTab": true,
     "uninstallAddon": true,
     "unregisterServiceWorker": true,
     "waitForInitialAddonList": true,
     "waitForMutation": true,
     "waitForServiceWorkerRegistered": true
   }
-}
+};
rename from devtools/client/animationinspector/test/.eslintrc
rename to devtools/client/animationinspector/test/.eslintrc.js
--- a/devtools/client/animationinspector/test/.eslintrc
+++ b/devtools/client/animationinspector/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/animationinspector/test/unit/.eslintrc
rename to devtools/client/animationinspector/test/unit/.eslintrc.js
--- a/devtools/client/animationinspector/test/unit/.eslintrc
+++ b/devtools/client/animationinspector/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/client/canvasdebugger/test/.eslintrc
rename to devtools/client/canvasdebugger/test/.eslintrc.js
--- a/devtools/client/canvasdebugger/test/.eslintrc
+++ b/devtools/client/canvasdebugger/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/commandline/test/.eslintrc
rename to devtools/client/commandline/test/.eslintrc.js
--- a/devtools/client/commandline/test/.eslintrc
+++ b/devtools/client/commandline/test/.eslintrc.js
@@ -1,8 +1,10 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests",
+  "extends": "../../../.eslintrc.mochitests.js",
   "globals": {
     "helpers": true,
     "assert": true
   }
-}
+};
rename from devtools/client/debugger/new/test/mochitest/.eslintrc
rename to devtools/client/debugger/new/test/mochitest/.eslintrc.js
--- a/devtools/client/debugger/new/test/mochitest/.eslintrc
+++ b/devtools/client/debugger/new/test/mochitest/.eslintrc.js
@@ -1,9 +1,11 @@
-{
+"use strict";
+
+module.exports = {
   "globals": {
     "add_task": false,
     "Assert": false,
     "BrowserTestUtils": false,
     "content": false,
     "ContentTask": false,
     "ContentTaskUtils": false,
     "EventUtils": false,
@@ -65,9 +67,9 @@
     "addBreakpoint": false,
     "toggleCallStack": false,
     "isVisibleWithin": false,
     "clickElement": false,
     "togglePauseOnExceptions": false,
     "pressKey": false,
     "EXAMPLE_URL": false
   }
-}
+};
rename from devtools/client/debugger/test/.eslintrc
rename to devtools/client/debugger/test/.eslintrc.js
--- a/devtools/client/debugger/test/.eslintrc
+++ b/devtools/client/debugger/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/dom/.eslintrc
rename to devtools/client/dom/.eslintrc.js
--- a/devtools/client/dom/.eslintrc
+++ b/devtools/client/dom/.eslintrc.js
@@ -1,15 +1,17 @@
-{
+"use strict";
+
+module.exports = {
   "globals": {
     "XMLHttpRequest": true,
     "window": true,
     "define": true,
     "addEventListener": true,
     "document": true,
     "dispatchEvent": true,
     "MessageEvent": true
   },
   "rules": {
     "indent": 0,
     "padded-blocks": 0,
   }
-}
+};
rename from devtools/client/dom/test/.eslintrc
rename to devtools/client/dom/test/.eslintrc.js
--- a/devtools/client/dom/test/.eslintrc
+++ b/devtools/client/dom/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests",
-}
+  "extends": "../../../.eslintrc.mochitests.js",
+};
rename from devtools/client/framework/test/.eslintrc
rename to devtools/client/framework/test/.eslintrc.js
--- a/devtools/client/framework/test/.eslintrc
+++ b/devtools/client/framework/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/inspector/.eslintrc
rename to devtools/client/inspector/.eslintrc.js
--- a/devtools/client/inspector/.eslintrc
+++ b/devtools/client/inspector/.eslintrc.js
@@ -1,12 +1,15 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the devtools eslintrc.
-  "extends": "../../.eslintrc",
+  "extends": "../../.eslintrc.js",
 
   "rules": {
     // The inspector is being migrated to HTML and cleaned of
     // chrome-privileged code, so this rule disallows requiring chrome
     // code. Some files in the inspector disable this rule still. The
     // goal is to enable the rule globally on all files.
+    /* eslint-disable max-len */
     "mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
   },
-}
+};
rename from devtools/client/inspector/components/test/.eslintrc
rename to devtools/client/inspector/components/test/.eslintrc.js
--- a/devtools/client/inspector/components/test/.eslintrc
+++ b/devtools/client/inspector/components/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/inspector/computed/test/.eslintrc
rename to devtools/client/inspector/computed/test/.eslintrc.js
--- a/devtools/client/inspector/computed/test/.eslintrc
+++ b/devtools/client/inspector/computed/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/inspector/fonts/test/.eslintrc
rename to devtools/client/inspector/fonts/test/.eslintrc.js
--- a/devtools/client/inspector/fonts/test/.eslintrc
+++ b/devtools/client/inspector/fonts/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/inspector/markup/test/.eslintrc
rename to devtools/client/inspector/markup/test/.eslintrc.js
--- a/devtools/client/inspector/markup/test/.eslintrc
+++ b/devtools/client/inspector/markup/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/inspector/rules/test/.eslintrc
rename to devtools/client/inspector/rules/test/.eslintrc.js
--- a/devtools/client/inspector/rules/test/.eslintrc
+++ b/devtools/client/inspector/rules/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/inspector/rules/test/browser_rules_invalid-source-map.js
+++ b/devtools/client/inspector/rules/test/browser_rules_invalid-source-map.js
@@ -30,14 +30,15 @@ add_task(function* () {
 
   yield verifyLinkText(view, CSS_LOC);
 
   Services.prefs.clearUserPref(PREF);
 });
 
 function verifyLinkText(view, text) {
   info("Verifying that the rule-view stylesheet link is " + text);
-  let label = getRuleViewLinkByIndex(view, 1).querySelector("label");
+  let label = getRuleViewLinkByIndex(view, 1)
+    .querySelector(".ruleview-rule-source-label");
   return waitForSuccess(
-    () => label.getAttribute("value") == text,
+    () => label.textContent == text,
     "Link text changed to display correct location: " + text
   );
 }
--- a/devtools/client/inspector/rules/test/browser_rules_original-source-link.js
+++ b/devtools/client/inspector/rules/test/browser_rules_original-source-link.js
@@ -72,13 +72,14 @@ function editorSelected(editor) {
     "selected stylesheet is correct one");
 
   let {line} = editor.sourceEditor.getCursor();
   is(line, 3, "cursor is at correct line number in original source");
 }
 
 function verifyLinkText(text, view) {
   info("Verifying that the rule-view stylesheet link is " + text);
-  let label = getRuleViewLinkByIndex(view, 1).querySelector("label");
+  let label = getRuleViewLinkByIndex(view, 1)
+    .querySelector(".ruleview-rule-source-label");
   return waitForSuccess(function* () {
-    return label.getAttribute("value") == text;
+    return label.textContent == text;
   }, "Link text changed to display correct location: " + text);
 }
--- a/devtools/client/inspector/rules/test/browser_rules_style-editor-link.js
+++ b/devtools/client/inspector/rules/test/browser_rules_style-editor-link.js
@@ -175,18 +175,18 @@ function* testDisabledStyleEditor(view, 
   is(toolbox.currentToolId, "styleeditor", "Style Editor should be selected");
 
   Services.prefs.clearUserPref("devtools.styleeditor.enabled");
 }
 
 function testRuleViewLinkLabel(view) {
   let link = getRuleViewLinkByIndex(view, 2);
   let labelElem = link.querySelector(".ruleview-rule-source-label");
-  let value = labelElem.getAttribute("value");
-  let tooltipText = labelElem.getAttribute("tooltiptext");
+  let value = labelElem.textContent;
+  let tooltipText = labelElem.getAttribute("title");
 
   is(value, EXTERNAL_STYLESHEET_FILE_NAME + ":1",
     "rule view stylesheet display value matches filename and line number");
   is(tooltipText, EXTERNAL_STYLESHEET_URL + ":1",
     "rule view stylesheet tooltip text matches the full URI path");
 }
 
 function testUnselectableRuleViewLink(view, index) {
--- a/devtools/client/inspector/rules/test/head.js
+++ b/devtools/client/inspector/rules/test/head.js
@@ -471,17 +471,17 @@ function getRuleViewLinkByIndex(view, in
  * @param {CssRuleView} view
  *        The instance of the rule-view panel
  * @param {Number} index
  *        The index of the link to get
  * @return {String} The string at this index
  */
 function getRuleViewLinkTextByIndex(view, index) {
   let link = getRuleViewLinkByIndex(view, index);
-  return link.querySelector(".ruleview-rule-source-label").value;
+  return link.querySelector(".ruleview-rule-source-label").textContent;
 }
 
 /**
  * Simulate adding a new property in an existing rule in the rule-view.
  *
  * @param {CssRuleView} view
  *        The instance of the rule-view panel
  * @param {Number} ruleIndex
--- a/devtools/client/inspector/rules/views/rule-editor.js
+++ b/devtools/client/inspector/rules/views/rule-editor.js
@@ -28,19 +28,16 @@ const promise = require("promise");
 const Services = require("Services");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {Task} = require("devtools/shared/task");
 
 const STYLE_INSPECTOR_PROPERTIES = "devtools-shared/locale/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
 /**
  * RuleEditor is responsible for the following:
  *   Owns a Rule object and creates a list of TextPropertyEditors
  *     for its TextProperties.
  *   Manages creation of new text properties.
  *
  * One step of a RuleEditor's instantiation is figuring out what's the original
  * source link to the parent stylesheet (in case of source maps). This step is
@@ -93,17 +90,17 @@ RuleEditor.prototype = {
       this.rule.domRule.type !== CSSRule.KEYFRAME_RULE;
 
     // Do not allow editing anonymousselectors until we can
     // detect mutations on  pseudo elements in Bug 1034110.
     return trait && !this.rule.elementStyle.element.isAnonymous;
   },
 
   _create: function () {
-    this.element = this.doc.createElementNS(HTML_NS, "div");
+    this.element = this.doc.createElement("div");
     this.element.className = "ruleview-rule theme-separator";
     this.element.setAttribute("uneditable", !this.isEditable);
     this.element.setAttribute("unmatched", this.rule.isUnmatched);
     this.element._ruleEditor = this;
 
     // Give a relative position for the inplace editor's measurement
     // span to be placed absolutely against.
     this.element.style.position = "relative";
@@ -114,18 +111,17 @@ RuleEditor.prototype = {
     });
     this.source.addEventListener("click", function () {
       if (this.source.hasAttribute("unselectable")) {
         return;
       }
       let rule = this.rule.domRule;
       this.ruleView.emit("ruleview-linked-clicked", rule);
     }.bind(this));
-    let sourceLabel = this.doc.createElementNS(XUL_NS, "label");
-    sourceLabel.setAttribute("crop", "center");
+    let sourceLabel = this.doc.createElement("span");
     sourceLabel.classList.add("ruleview-rule-source-label");
     this.source.appendChild(sourceLabel);
 
     this.updateSourceLink();
 
     let code = createChild(this.element, "div", {
       class: "ruleview-code"
     });
@@ -224,51 +220,51 @@ RuleEditor.prototype = {
 
   updateSourceLink: function () {
     let sourceLabel = this.element.querySelector(".ruleview-rule-source-label");
     let title = this.rule.title;
     let sourceHref = (this.rule.sheet && this.rule.sheet.href) ?
       this.rule.sheet.href : title;
     let sourceLine = this.rule.ruleLine > 0 ? ":" + this.rule.ruleLine : "";
 
-    sourceLabel.setAttribute("tooltiptext", sourceHref + sourceLine);
+    sourceLabel.setAttribute("title", sourceHref + sourceLine);
 
     if (this.toolbox.isToolRegistered("styleeditor")) {
       this.source.removeAttribute("unselectable");
     } else {
       this.source.setAttribute("unselectable", true);
     }
 
     if (this.rule.isSystem) {
       let uaLabel = STYLE_INSPECTOR_L10N.getStr("rule.userAgentStyles");
-      sourceLabel.setAttribute("value", uaLabel + " " + title);
+      sourceLabel.textContent = uaLabel + " " + title;
 
       // Special case about:PreferenceStyleSheet, as it is generated on the
       // fly and the URI is not registered with the about: handler.
       // https://bugzilla.mozilla.org/show_bug.cgi?id=935803#c37
       if (sourceHref === "about:PreferenceStyleSheet") {
         this.source.setAttribute("unselectable", "true");
-        sourceLabel.setAttribute("value", uaLabel);
-        sourceLabel.removeAttribute("tooltiptext");
+        sourceLabel.textContent = uaLabel;
+        sourceLabel.removeAttribute("title");
       }
     } else {
-      sourceLabel.setAttribute("value", title);
+      sourceLabel.textContent = title;
       if (this.rule.ruleLine === -1 && this.rule.domRule.parentStyleSheet) {
         this.source.setAttribute("unselectable", "true");
       }
     }
 
     let showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES);
     if (showOrig && !this.rule.isSystem &&
         this.rule.domRule.type !== ELEMENT_STYLE) {
       // Only get the original source link if the right pref is set, if the rule
       // isn't a system rule and if it isn't an inline rule.
       this.rule.getOriginalSourceStrings().then((strings) => {
-        sourceLabel.setAttribute("value", strings.short);
-        sourceLabel.setAttribute("tooltiptext", strings.full);
+        sourceLabel.textContent = strings.short;
+        sourceLabel.setAttribute("title", strings.full);
       }, e => console.error(e)).then(() => {
         this.emit("source-link-updated");
       });
     } else {
       // If we're not getting the original source link, then we can emit the
       // event immediately (but still asynchronously to give consumers a chance
       // to register it after having instantiated the RuleEditor).
       promise.resolve().then(() => {
rename from devtools/client/inspector/shared/test/.eslintrc
rename to devtools/client/inspector/shared/test/.eslintrc.js
--- a/devtools/client/inspector/shared/test/.eslintrc
+++ b/devtools/client/inspector/shared/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/inspector/shared/test/head.js
+++ b/devtools/client/inspector/shared/test/head.js
@@ -415,17 +415,17 @@ function getRuleViewLinkByIndex(view, in
  * @param {CssRuleView} view
  *        The instance of the rule-view panel
  * @param {Number} index
  *        The index of the link to get
  * @return {String} The string at this index
  */
 function getRuleViewLinkTextByIndex(view, index) {
   let link = getRuleViewLinkByIndex(view, index);
-  return link.querySelector(".ruleview-rule-source-label").value;
+  return link.querySelector(".ruleview-rule-source-label").textContent;
 }
 
 /**
  * Click on a rule-view's close brace to focus a new property name editor
  *
  * @param {RuleEditor} ruleEditor
  *        An instance of RuleEditor that will receive the new property
  * @return a promise that resolves to the newly created editor when ready and
rename from devtools/client/inspector/test/.eslintrc
rename to devtools/client/inspector/test/.eslintrc.js
--- a/devtools/client/inspector/test/.eslintrc
+++ b/devtools/client/inspector/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-xul.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-xul.js
@@ -25,14 +25,18 @@ add_task(function* () {
 
   info("Open the color picker");
   let cPicker = ruleView.tooltips.colorPicker;
   let onColorPickerReady = cPicker.once("ready");
   swatchEl.click();
   yield onColorPickerReady;
 
   button = cPicker.tooltip.doc.querySelector("#eyedropper-button");
-  ok(!isVisible(button), "The button is hidden in the color picker");
+  ok(isDisabled(button), "The button is disabled in the color picker");
 });
 
 function isVisible(button) {
   return button.getBoxQuads().length !== 0;
 }
+
+function isDisabled(button) {
+  return button.disabled;
+}
rename from devtools/client/jsonview/.eslintrc
rename to devtools/client/jsonview/.eslintrc.js
--- a/devtools/client/jsonview/.eslintrc
+++ b/devtools/client/jsonview/.eslintrc.js
@@ -1,9 +1,11 @@
-{
+"use strict";
+
+module.exports = {
   "globals": {
     "define": true,
     "document": true,
     "window": true,
     "CustomEvent": true,
     "Locale": true
   }
-}
+};
rename from devtools/client/jsonview/test/.eslintrc
rename to devtools/client/jsonview/test/.eslintrc.js
--- a/devtools/client/jsonview/test/.eslintrc
+++ b/devtools/client/jsonview/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/locales/en-US/inspector.properties
+++ b/devtools/client/locales/en-US/inspector.properties
@@ -36,16 +36,20 @@ markupView.more.showAll2=Show one more n
 # LOCALIZATION NOTE (markupView.whitespaceOnly)
 # Used in a tooltip that appears when the user hovers over whitespace-only text nodes in
 # the inspector.
 markupView.whitespaceOnly=Whitespace-only text node: %S
 
 #LOCALIZATION NOTE: Used in the image preview tooltip when the image could not be loaded
 previewTooltip.image.brokenImage=Could not load the image
 
+# LOCALIZATION NOTE: Used in color picker tooltip when the eyedropper is disabled for
+# non-HTML documents
+eyedropper.disabled.title=Unavailable in non-HTML documents
+
 #LOCALIZATION NOTE: Used in the image preview tooltip when the image could not be loaded
 eventsTooltip.openInDebugger=Open in Debugger
 
 # LOCALIZATION NOTE (docsTooltip.visitMDN): Shown in the tooltip that displays
 # help from MDN. This is a link to the complete MDN documentation page.
 docsTooltip.visitMDN=Visit MDN page
 
 # LOCALIZATION NOTE (docsTooltip.visitMDN): Shown in the docs tooltip when the MDN page
rename from devtools/client/memory/test/browser/.eslintrc
rename to devtools/client/memory/test/browser/.eslintrc.js
--- a/devtools/client/memory/test/browser/.eslintrc
+++ b/devtools/client/memory/test/browser/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/memory/test/unit/.eslintrc
rename to devtools/client/memory/test/unit/.eslintrc.js
--- a/devtools/client/memory/test/unit/.eslintrc
+++ b/devtools/client/memory/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/client/netmonitor/.eslintrc
rename to devtools/client/netmonitor/.eslintrc.js
--- a/devtools/client/netmonitor/.eslintrc
+++ b/devtools/client/netmonitor/.eslintrc.js
@@ -1,12 +1,15 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the devtools eslintrc.
-  "extends": "../../.eslintrc",
+  "extends": "../../.eslintrc.js",
 
   "rules": {
     // The netmonitor is being migrated to HTML and cleaned of
     // chrome-privileged code, so this rule disallows requiring chrome
     // code. Some files in the netmonitor disable this rule still. The
     // goal is to enable the rule globally on all files.
+    /* eslint-disable max-len */
     "mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
   },
-}
+};
rename from devtools/client/netmonitor/har/test/.eslintrc
rename to devtools/client/netmonitor/har/test/.eslintrc.js
--- a/devtools/client/netmonitor/har/test/.eslintrc
+++ b/devtools/client/netmonitor/har/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/netmonitor/test/.eslintrc
rename to devtools/client/netmonitor/test/.eslintrc.js
--- a/devtools/client/netmonitor/test/.eslintrc
+++ b/devtools/client/netmonitor/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/performance/test/.eslintrc
rename to devtools/client/performance/test/.eslintrc.js
--- a/devtools/client/performance/test/.eslintrc
+++ b/devtools/client/performance/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/performance/test/unit/.eslintrc
rename to devtools/client/performance/test/unit/.eslintrc.js
--- a/devtools/client/performance/test/unit/.eslintrc
+++ b/devtools/client/performance/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/client/projecteditor/test/.eslintrc
rename to devtools/client/projecteditor/test/.eslintrc.js
--- a/devtools/client/projecteditor/test/.eslintrc
+++ b/devtools/client/projecteditor/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/promisedebugger/test/.eslintrc
rename to devtools/client/promisedebugger/test/.eslintrc.js
--- a/devtools/client/promisedebugger/test/.eslintrc
+++ b/devtools/client/promisedebugger/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/responsive.html/browser/tunnel.js
+++ b/devtools/client/responsive.html/browser/tunnel.js
@@ -357,21 +357,29 @@ MessageManagerTunnel.prototype = {
     "SessionStore:update",
     // Messages sent to BrowserTestUtils.jsm
     "browser-test-utils:loadEvent",
   ],
 
   OUTER_TO_INNER_MESSAGE_PREFIXES: [
     // Messages sent from DevTools
     "debug:",
+    // Messages sent from findbar.xml
+    "Findbar:",
+    // Messages sent from RemoteFinder.jsm
+    "Finder:",
   ],
 
   INNER_TO_OUTER_MESSAGE_PREFIXES: [
     // Messages sent to DevTools
     "debug:",
+    // Messages sent to findbar.xml
+    "Findbar:",
+    // Messages sent to RemoteFinder.jsm
+    "Finder:",
   ],
 
   OUTER_TO_INNER_FRAME_SCRIPTS: [
     // DevTools server for OOP frames
     "resource://devtools/server/child.js"
   ],
 
   get outerParentMM() {
rename from devtools/client/responsive.html/test/browser/.eslintrc
rename to devtools/client/responsive.html/test/browser/.eslintrc.js
--- a/devtools/client/responsive.html/test/browser/.eslintrc
+++ b/devtools/client/responsive.html/test/browser/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/responsive.html/test/unit/.eslintrc
rename to devtools/client/responsive.html/test/unit/.eslintrc.js
--- a/devtools/client/responsive.html/test/unit/.eslintrc
+++ b/devtools/client/responsive.html/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for xpcshell.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/client/responsivedesign/test/.eslintrc
rename to devtools/client/responsivedesign/test/.eslintrc.js
--- a/devtools/client/responsivedesign/test/.eslintrc
+++ b/devtools/client/responsivedesign/test/.eslintrc.js
@@ -1,8 +1,10 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests",
+  "extends": "../../../.eslintrc.mochitests.js",
   "globals": {
     "ResponsiveUI": true,
     "helpers": true
   }
-}
+};
rename from devtools/client/scratchpad/test/.eslintrc
rename to devtools/client/scratchpad/test/.eslintrc.js
--- a/devtools/client/scratchpad/test/.eslintrc
+++ b/devtools/client/scratchpad/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/shadereditor/test/.eslintrc
rename to devtools/client/shadereditor/test/.eslintrc.js
--- a/devtools/client/shadereditor/test/.eslintrc
+++ b/devtools/client/shadereditor/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/shared/components/.eslintrc
rename to devtools/client/shared/components/.eslintrc.js
--- a/devtools/client/shared/components/.eslintrc
+++ b/devtools/client/shared/components/.eslintrc.js
@@ -1,5 +1,7 @@
-{
+"use strict";
+
+module.exports = {
   "globals": {
     "define": true,
   }
-}
+};
--- a/devtools/client/shared/components/reps/string.js
+++ b/devtools/client/shared/components/reps/string.js
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // Make this available to both AMD and CJS environments
 define(function (require, exports, module) {
   // Dependencies
   const React = require("devtools/client/shared/vendor/react");
-  const { cropMultipleLines } = require("./rep-utils");
+  const { cropString } = require("./rep-utils");
 
   // Shortcuts
   const { span } = React.DOM;
 
   /**
    * Renders a string. String value is enclosed within quotes.
    */
   const StringRep = React.createClass({
@@ -38,23 +38,24 @@ define(function (require, exports, modul
         return (
           span({className: "objectBox objectBox-string"},
             "\"" + text + "\""
           )
         );
       }
 
       let croppedString = this.props.cropLimit ?
-        cropMultipleLines(text, this.props.cropLimit) : cropMultipleLines(text);
+        cropString(text, this.props.cropLimit) : cropString(text);
 
       let formattedString = this.props.useQuotes ?
         "\"" + croppedString + "\"" : croppedString;
 
       return (
-        span({className: "objectBox objectBox-string"}, formattedString
+        span({className: "objectBox objectBox-string"},
+          formattedString
         )
       );
     },
   });
 
   function supportsObject(object, type) {
     return (type == "string");
   }
rename from devtools/client/shared/components/test/browser/.eslintrc
rename to devtools/client/shared/components/test/browser/.eslintrc.js
--- a/devtools/client/shared/components/test/browser/.eslintrc
+++ b/devtools/client/shared/components/test/browser/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../../.eslintrc.mochitests",
-}
+  "extends": "../../../../../.eslintrc.mochitests.js",
+};
rename from devtools/client/shared/components/test/mochitest/.eslintrc
rename to devtools/client/shared/components/test/mochitest/.eslintrc.js
--- a/devtools/client/shared/components/test/mochitest/.eslintrc
+++ b/devtools/client/shared/components/test/mochitest/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/shared/components/test/mochitest/test_reps_string.html
+++ b/devtools/client/shared/components/test/mochitest/test_reps_string.html
@@ -31,22 +31,22 @@ window.onload = Task.async(function* () 
   } catch(e) {
     ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
   } finally {
     SimpleTest.finish();
   }
 
   function testMultiline() {
     const renderedComponent = renderComponent(StringRep.rep, { object: getGripStub("testMultiline") });
-    is(renderedComponent.textContent, "\"aaaaaaaaaaaaaaaaaaaaa\\nbbbbbbbbbbbbbbbbbbb\\ncccccccccccccccc\\n\"", "String rep has expected text content for multiline string");
+    is(renderedComponent.textContent, "\"aaaaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbb\ncccccccccccccccc\n\"", "String rep has expected text content for multiline string");
   }
 
   function testMultilineLimit() {
     const renderedComponent = renderComponent(StringRep.rep, { object: getGripStub("testMultiline"), cropLimit: 20 });
-    is(renderedComponent.textContent, "\"aaaaaaaaaa…cccccccc\\n\"", "String rep has expected text content for multiline string with specified number of characters");
+    is(renderedComponent.textContent, "\"aaaaaaaaaa…cccccccc\n\"", "String rep has expected text content for multiline string with specified number of characters");
   }
 
   function testMultilineOpen() {
     const renderedComponent = renderComponent(StringRep.rep, { object: getGripStub("testMultiline"), member: {open: true} });
     is(renderedComponent.textContent, "\"aaaaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbb\ncccccccccccccccc\n\"", "String rep has expected text content for multiline string when open");
   }
 
   function testUseQuotes(){
rename from devtools/client/shared/shim/test/.eslintrc
rename to devtools/client/shared/shim/test/.eslintrc.js
--- a/devtools/client/shared/shim/test/.eslintrc
+++ b/devtools/client/shared/shim/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/shared/test/.eslintrc
rename to devtools/client/shared/test/.eslintrc.js
--- a/devtools/client/shared/test/.eslintrc
+++ b/devtools/client/shared/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/shared/test/unit/.eslintrc
rename to devtools/client/shared/test/unit/.eslintrc.js
--- a/devtools/client/shared/test/unit/.eslintrc
+++ b/devtools/client/shared/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
--- a/devtools/client/shared/widgets/tooltip/HTMLTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/HTMLTooltip.js
@@ -569,16 +569,17 @@ HTMLTooltip.prototype = {
 
     // XUL panel is only a way to display DOM elements outside of the document viewport,
     // so disable all features that impact the behavior.
     panel.setAttribute("animate", false);
     panel.setAttribute("consumeoutsideclicks", false);
     panel.setAttribute("noautofocus", true);
     panel.setAttribute("noautohide", true);
     panel.setAttribute("ignorekeys", true);
+    panel.setAttribute("tooltip", "aHTMLTooltip");
 
     // Use type="arrow" to prevent side effects (see Bug 1285206)
     panel.setAttribute("type", "arrow");
 
     panel.setAttribute("level", "top");
     panel.setAttribute("class", "tooltip-xul-wrapper");
 
     return panel;
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
@@ -3,16 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {Task} = require("devtools/shared/task");
 const {colorUtils} = require("devtools/shared/css/color");
 const {Spectrum} = require("devtools/client/shared/widgets/Spectrum");
 const SwatchBasedEditorTooltip = require("devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip");
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools/locale/inspector.properties");
 
 const Heritage = require("sdk/core/heritage");
 
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 
 /**
  * The swatch color picker tooltip class is a specific class meant to be used
  * along with output-parser's generated color swatches.
@@ -51,16 +53,20 @@ SwatchColorPickerTooltip.prototype = Her
     let container = doc.createElementNS(XHTML_NS, "div");
     container.id = "spectrum-tooltip";
     let spectrumNode = doc.createElementNS(XHTML_NS, "div");
     spectrumNode.id = "spectrum";
     container.appendChild(spectrumNode);
     let eyedropper = doc.createElementNS(XHTML_NS, "button");
     eyedropper.id = "eyedropper-button";
     eyedropper.className = "devtools-button";
+    /* pointerEvents for eyedropper has to be set auto to display tooltip when
+     * eyedropper is disabled in non-HTML documents.
+     */
+    eyedropper.style.pointerEvents = "auto";
     container.appendChild(eyedropper);
 
     this.tooltip.setContent(container, { width: 218, height: 224 });
 
     let spectrum = new Spectrum(spectrumNode, color);
 
     // Wait for the tooltip to be shown before calling spectrum.show
     // as it expect to be visible in order to compute DOM element sizes.
@@ -91,17 +97,18 @@ SwatchColorPickerTooltip.prototype = Her
 
     let {target} = this.inspector;
     target.actorHasMethod("inspector", "pickColorFromPage").then(value => {
       let tooltipDoc = this.tooltip.doc;
       let eyeButton = tooltipDoc.querySelector("#eyedropper-button");
       if (value && this.inspector.selection.nodeFront.isInHTMLDocument) {
         eyeButton.addEventListener("click", this._openEyeDropper);
       } else {
-        eyeButton.style.display = "none";
+        eyeButton.disabled = true;
+        eyeButton.title = L10N.getStr("eyedropper.disabled.title");
       }
       this.emit("ready");
     }, e => console.error(e));
   }),
 
   _onSpectrumColorChange: function (event, rgba, cssColor) {
     this._selectColor(cssColor);
   },
rename from devtools/client/sourceeditor/.eslintrc
rename to devtools/client/sourceeditor/.eslintrc.js
--- a/devtools/client/sourceeditor/.eslintrc
+++ b/devtools/client/sourceeditor/.eslintrc.js
@@ -1,12 +1,15 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the devtools eslintrc.
-  "extends": "../../.eslintrc",
+  "extends": "../../.eslintrc.js",
 
   "rules": {
     // The inspector is being migrated to HTML and cleaned of
     // chrome-privileged code, so this rule disallows requiring chrome
     // code. Some files here disable this rule still. The
     // goal is to enable the rule globally on all files.
+    /* eslint-disable max-len */
     "mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm)$"],
   },
-}
+};
rename from devtools/client/sourceeditor/test/.eslintrc
rename to devtools/client/sourceeditor/test/.eslintrc.js
--- a/devtools/client/sourceeditor/test/.eslintrc
+++ b/devtools/client/sourceeditor/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/storage/test/.eslintrc
rename to devtools/client/storage/test/.eslintrc.js
--- a/devtools/client/storage/test/.eslintrc
+++ b/devtools/client/storage/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/styleeditor/test/.eslintrc
rename to devtools/client/styleeditor/test/.eslintrc.js
--- a/devtools/client/styleeditor/test/.eslintrc
+++ b/devtools/client/styleeditor/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -136,31 +136,44 @@
 .ruleview-computedlist[user-open],
 .ruleview-computedlist[filter-open] {
   display: block;
 }
 
 .ruleview-rule-source {
   text-align: end;
   float: right;
+  max-width: 100%;
+
+  /* Force RTL direction to crop the source link at the beginning. */
+  direction: rtl;
+  overflow: hidden;
+  text-overflow: ellipsis;
+
   -moz-user-select: none;
   margin-bottom: 2px;
 }
 
-.ruleview-rule-source > label {
+.ruleview-rule-source-label {
+  white-space: nowrap;
+  margin: 0;
   cursor: pointer;
-  margin: 0;
+
+  /* Create an LTR embed to avoid special characters being shifted to the start due to the
+     parent node direction: rtl; */
+  direction: ltr;
+  unicode-bidi: embed
 }
 
 .ruleview-rule-source[unselectable],
-.ruleview-rule-source[unselectable] > label {
+.ruleview-rule-source[unselectable] > .ruleview-rule-source-label {
   cursor: default;
 }
 
-.theme-firebug .ruleview-rule-source label {
+.theme-firebug .ruleview-rule-source-label {
   font-family: var(--proportional-font-family);
   font-weight: bold;
   color: #0000FF;
 }
 
 .ruleview-rule-source:not([unselectable]):hover {
   text-decoration: underline;
 }
rename from devtools/client/webaudioeditor/test/.eslintrc
rename to devtools/client/webaudioeditor/test/.eslintrc.js
--- a/devtools/client/webaudioeditor/test/.eslintrc
+++ b/devtools/client/webaudioeditor/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/webconsole/net/.eslintrc
rename to devtools/client/webconsole/net/.eslintrc.js
--- a/devtools/client/webconsole/net/.eslintrc
+++ b/devtools/client/webconsole/net/.eslintrc.js
@@ -1,18 +1,20 @@
-{
+"use strict";
+
+module.exports = {
   "globals": {
     "Locale": true,
     "Document": true,
     "document": true,
     "Node": true,
     "Element": true,
     "MessageEvent": true,
     "BrowserLoader": true,
     "addEventListener": true,
     "DOMParser": true,
     "dispatchEvent": true,
     "setTimeout": true
   },
   "rules": {
     "no-unused-vars": [2, {"args": "none"}],
   }
-}
+};
--- a/devtools/client/webconsole/net/components/net-info-params.js
+++ b/devtools/client/webconsole/net/components/net-info-params.js
@@ -9,36 +9,36 @@ const React = require("devtools/client/s
 const DOM = React.DOM;
 const PropTypes = React.PropTypes;
 
 /**
  * This template renders list of parameters within a group.
  * It's essentially a list of name + value pairs.
  */
 var NetInfoParams = React.createClass({
+  displayName: "NetInfoParams",
+
   propTypes: {
     params: PropTypes.arrayOf(PropTypes.shape({
       name: PropTypes.string.isRequired,
       value: PropTypes.string.isRequired
     })).isRequired,
   },
 
-  displayName: "NetInfoParams",
-
   render() {
     let params = this.props.params || [];
 
     params.sort(function (a, b) {
       return a.name > b.name ? 1 : -1;
     });
 
     let rows = [];
-    params.forEach(param => {
+    params.forEach((param, index) => {
       rows.push(
-        DOM.tr({key: param.name},
+        DOM.tr({key: index},
           DOM.td({className: "netInfoParamName"},
             DOM.span({title: param.name}, param.name)
           ),
           DOM.td({className: "netInfoParamValue"},
             DOM.code({}, param.value)
           )
         )
       );
rename from devtools/client/webconsole/net/test/mochitest/.eslintrc
rename to devtools/client/webconsole/net/test/mochitest/.eslintrc.js
--- a/devtools/client/webconsole/net/test/mochitest/.eslintrc
+++ b/devtools/client/webconsole/net/test/mochitest/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../../.eslintrc.mochitests",
-}
+  "extends": "../../../../../.eslintrc.mochitests.js",
+};
--- a/devtools/client/webconsole/net/test/mochitest/browser_net_params.js
+++ b/devtools/client/webconsole/net/test/mochitest/browser_net_params.js
@@ -35,8 +35,35 @@ add_task(function* () {
   is(paramName.textContent, "foo",
     "The param name must have proper value");
 
   let paramValue = paramName.parentNode.nextSibling;
   ok(paramValue, "param value must exist");
   is(paramValue.textContent, "bar",
     "The param value must have proper value");
 });
+
+/**
+ * Test URL parameters with the same name.
+ */
+add_task(function* () {
+  info("Test XHR Spy params started");
+
+  let {hud} = yield addTestTab(TEST_PAGE_URL);
+
+  let netInfoBody = yield executeAndInspectXhr(hud, {
+    method: "GET",
+    url: JSON_XHR_URL,
+    queryString: "?box[]=123&box[]=456"
+  });
+
+  // Check headers
+  let tabBody = yield selectNetInfoTab(hud, netInfoBody, "params");
+
+  let params = tabBody.querySelectorAll(
+    ".netInfoParamName > span[title='box[]']");
+  is(params.length, 2, "Two URI parameters must exist");
+
+  let values = tabBody.querySelectorAll(
+    ".netInfoParamValue > code");
+  is(values[0].textContent, 123, "First value must match");
+  is(values[1].textContent, 456, "Second value must match");
+});
rename from devtools/client/webconsole/net/test/unit/.eslintrc
rename to devtools/client/webconsole/net/test/unit/.eslintrc.js
--- a/devtools/client/webconsole/net/test/unit/.eslintrc
+++ b/devtools/client/webconsole/net/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../../.eslintrc.xpcshell.js"
+};
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -103,16 +103,20 @@ NewConsoleOutputWrapper.prototype = {
   dispatchMessagesAdd: function (messages) {
     const batchedActions = messages.map(message => actions.messageAdd(message));
     store.dispatch(actions.batchActions(batchedActions));
   },
 
   dispatchMessagesClear: function () {
     store.dispatch(actions.messagesClear());
   },
+  // Should be used for test purpose only.
+  getStore: function () {
+    return store;
+  }
 };
 
 function batchedMessageAdd(action) {
   queuedActions.push(action);
   if (!throttledDispatchTimeout) {
     throttledDispatchTimeout = setTimeout(() => {
       store.dispatch(actions.batchActions(queuedActions));
       queuedActions = [];
rename from devtools/client/webconsole/new-console-output/test/.eslintrc
rename to devtools/client/webconsole/new-console-output/test/.eslintrc.js
--- a/devtools/client/webconsole/new-console-output/test/.eslintrc
+++ b/devtools/client/webconsole/new-console-output/test/.eslintrc.js
@@ -1,3 +1,5 @@
-{
-  "extends": ["../../../../.eslintrc.xpcshell"]
-}
+"use strict";
+
+module.exports = {
+  "extends": ["../../../../.eslintrc.xpcshell.js"]
+};
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
@@ -1,19 +1,21 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
   head.js
+  test-batching.html
   test-console.html
   test-console-filters.html
   test-console-group.html
   test-console-table.html
   !/devtools/client/framework/test/shared-head.js
 
+[browser_webconsole_batching.js]
 [browser_webconsole_console_group.js]
 [browser_webconsole_console_table.js]
 [browser_webconsole_filters.js]
 [browser_webconsole_init.js]
 [browser_webconsole_input_focus.js]
 [browser_webconsole_keyboard_accessibility.js]
 [browser_webconsole_observer_notifications.js]
 [browser_webconsole_vview_close_on_esc_key.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_batching.js
@@ -0,0 +1,69 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Check adding console calls as batch keep the order of the message.
+
+const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-batching.html";
+const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
+
+add_task(function* () {
+  let hud = yield openNewTabAndConsole(TEST_URI);
+
+  const store = hud.ui.newConsoleOutput.getStore();
+  // Adding loggin each time the store is modified in order to check
+  // the store state in case of failure.
+  store.subscribe(() => {
+    const messages = store.getState().messages.messagesById.toJS()
+      .map(message => {
+        return {
+          id: message.id,
+          type: message.type,
+          parameters: message.parameters,
+          messageText: message.messageText
+        };
+      }
+    );
+    info("messages : " + JSON.stringify(messages));
+  });
+
+  const messageNumber = 100;
+  yield testSimpleBatchLogging(hud, messageNumber);
+  yield testBatchLoggingAndClear(hud, messageNumber);
+});
+
+function* testSimpleBatchLogging(hud, messageNumber) {
+  yield ContentTask.spawn(gBrowser.selectedBrowser, messageNumber,
+    function (numMessages) {
+      content.wrappedJSObject.batchLog(numMessages);
+    }
+  );
+
+  for (let i = 0; i < messageNumber; i++) {
+    let node = yield waitFor(() => findMessageAtIndex(hud, i, i));
+    is(node.textContent, i.toString(), `message at index "${i}" is the expected one`);
+  }
+}
+
+function* testBatchLoggingAndClear(hud, messageNumber) {
+  yield ContentTask.spawn(gBrowser.selectedBrowser, messageNumber,
+    function (numMessages) {
+      content.wrappedJSObject.batchLogAndClear(numMessages);
+    }
+  );
+  yield waitFor(() => findMessage(hud, l10n.getStr("consoleCleared")));
+  ok(true, "console cleared message is displayed");
+
+  // Passing the text argument as an empty string will returns all the message,
+  // whatever their content is.
+  const messages = findMessages(hud, "");
+  is(messages.length, 1, "console was cleared as expected");
+}
+
+function findMessageAtIndex(hud, text, index) {
+  const selector = `.message:nth-of-type(${index + 1}) .message-body`;
+  return findMessage(hud, text, selector);
+}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_group.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_group.js
@@ -10,16 +10,37 @@
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-console-group.html";
 const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent");
 
 add_task(function* () {
   let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
   let hud = toolbox.getCurrentPanel().hud;
 
+  const store = hud.ui.newConsoleOutput.getStore();
+  // Adding loggin each time the store is modified in order to check
+  // the store state in case of failure.
+  store.subscribe(() => {
+    const messages = store.getState().messages.messagesById.toJS()
+      .map(message => {
+        return {
+          id: message.id,
+          type: message.type,
+          parameters: message.parameters,
+          messageText: message.messageText
+        };
+      }
+    );
+    info("messages : " + JSON.stringify(messages));
+  });
+
+  yield ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
+    content.wrappedJSObject.doLog();
+  });
+
   info("Test a group at root level");
   let node = yield waitFor(() => findMessage(hud, "group-1"));
   testClass(node, "startGroup");
   testIndent(node, 0);
 
   info("Test a message in a 1 level deep group");
   node = yield waitFor(() => findMessage(hud, "log-1"));
   testClass(node, "log");
@@ -55,16 +76,16 @@ add_task(function* () {
   testClass(node, "log");
   testIndent(node, 0);
 
   let nodes = hud.ui.experimentalOutputNode.querySelectorAll(".message");
   is(nodes.length, 8, "expected number of messages are displayed");
 });
 
 function testClass(node, className) {
-  ok(node.classList.contains(className, "message has the expected class"));
+  ok(node.classList.contains(className), `message has the expected "${className}" class`);
 }
 
 function testIndent(node, indent) {
   indent = `${indent * INDENT_WIDTH}px`;
   is(node.querySelector(".indent").style.width, indent,
     "message has the expected level of indentation");
 }
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-batching.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>Webconsole batch console calls test page</title>
+  </head>
+  <body>
+    <p>batch console calls test page</p>
+    <script>
+    "use strict";
+
+    function batchLog(numMessages = 0) {
+      for (let i = 0; i < numMessages; i++) {
+        console.log(i);
+      }
+    }
+
+    function batchLogAndClear(numMessages = 0) {
+      for (let i = 0; i < numMessages; i++) {
+        console.log(i);
+        if (i === numMessages - 1) {
+          console.clear();
+        }
+      }
+    }
+    </script>
+  </body>
+</html>
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-console-group.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-console-group.html
@@ -4,23 +4,25 @@
     <meta charset="utf-8">
     <title>Webconsole console.group test page</title>
   </head>
   <body>
     <p>console.group() & console.groupCollapsed() test page</p>
     <script>
     "use strict";
 
-    console.group("group-1");
-    console.log("log-1");
-    console.group("group-2");
-    console.log("log-2");
-    console.groupEnd("group-2");
-    console.log("log-3");
-    console.groupEnd("group-1");
-    console.log("log-4");
-    console.groupCollapsed("group-3");
-    console.log("log-5");
-    console.groupEnd("group-3");
-    console.log("log-6");
+    function doLog() {
+        console.group("group-1");
+        console.log("log-1");
+        console.group("group-2");
+        console.log("log-2");
+        console.groupEnd("group-2");
+        console.log("log-3");
+        console.groupEnd("group-1");
+        console.log("log-4");
+        console.groupCollapsed("group-3");
+        console.log("log-5");
+        console.groupEnd("group-3");
+        console.log("log-6");
+    }
     </script>
   </body>
 </html>
rename from devtools/client/webconsole/test/.eslintrc
rename to devtools/client/webconsole/test/.eslintrc.js
--- a/devtools/client/webconsole/test/.eslintrc
+++ b/devtools/client/webconsole/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/webide/test/.eslintrc
rename to devtools/client/webide/test/.eslintrc.js
--- a/devtools/client/webide/test/.eslintrc
+++ b/devtools/client/webide/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/server/tests/browser/.eslintrc
rename to devtools/server/tests/browser/.eslintrc.js
--- a/devtools/server/tests/browser/.eslintrc
+++ b/devtools/server/tests/browser/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools mochitest eslintrc config.
-  "extends": "../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../.eslintrc.xpcshell.js"
+};
rename from devtools/server/tests/mochitest/.eslintrc
rename to devtools/server/tests/mochitest/.eslintrc.js
--- a/devtools/server/tests/mochitest/.eslintrc
+++ b/devtools/server/tests/mochitest/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools mochitest eslintrc config.
-  "extends": "../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../.eslintrc.xpcshell.js"
+};
rename from devtools/server/tests/unit/.eslintrc
rename to devtools/server/tests/unit/.eslintrc.js
--- a/devtools/server/tests/unit/.eslintrc
+++ b/devtools/server/tests/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/heapsnapshot/tests/unit/.eslintrc
rename to devtools/shared/heapsnapshot/tests/unit/.eslintrc.js
--- a/devtools/shared/heapsnapshot/tests/unit/.eslintrc
+++ b/devtools/shared/heapsnapshot/tests/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/platform/content/.eslintrc
rename to devtools/shared/platform/content/.eslintrc.js
--- a/devtools/shared/platform/content/.eslintrc
+++ b/devtools/shared/platform/content/.eslintrc.js
@@ -1,9 +1,12 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the devtools eslintrc.
-  "extends": "../../../.eslintrc",
+  "extends": "../../../.eslintrc.js",
 
   "rules": {
+    /* eslint-disable max-len */
     // All code in this directory must be content-clean.
     "mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
   },
-}
+};
rename from devtools/shared/platform/content/test/.eslintrc
rename to devtools/shared/platform/content/test/.eslintrc.js
--- a/devtools/shared/platform/content/test/.eslintrc
+++ b/devtools/shared/platform/content/test/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/security/tests/unit/.eslintrc
rename to devtools/shared/security/tests/unit/.eslintrc.js
--- a/devtools/shared/security/tests/unit/.eslintrc
+++ b/devtools/shared/security/tests/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/tests/browser/.eslintrc
rename to devtools/shared/tests/browser/.eslintrc.js
--- a/devtools/shared/tests/browser/.eslintrc
+++ b/devtools/shared/tests/browser/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests"
-}
+  "extends": "../../../.eslintrc.mochitests.js"
+};
rename from devtools/shared/tests/unit/.eslintrc
rename to devtools/shared/tests/unit/.eslintrc.js
--- a/devtools/shared/tests/unit/.eslintrc
+++ b/devtools/shared/tests/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../.eslintrc.xpcshell"
-}
+  "extends": "../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/transport/tests/unit/.eslintrc
rename to devtools/shared/transport/tests/unit/.eslintrc.js
--- a/devtools/shared/transport/tests/unit/.eslintrc
+++ b/devtools/shared/transport/tests/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/webconsole/test/unit/.eslintrc
rename to devtools/shared/webconsole/test/unit/.eslintrc.js
--- a/devtools/shared/webconsole/test/unit/.eslintrc
+++ b/devtools/shared/webconsole/test/unit/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell"
-}
\ No newline at end of file
+  "extends": "../../../../.eslintrc.xpcshell.js"
+};
rename from devtools/shared/worker/tests/browser/.eslintrc
rename to devtools/shared/worker/tests/browser/.eslintrc.js
--- a/devtools/shared/worker/tests/browser/.eslintrc
+++ b/devtools/shared/worker/tests/browser/.eslintrc.js
@@ -1,4 +1,6 @@
-{
+"use strict";
+
+module.exports = {
   // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../../.eslintrc.mochitests"
-}
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -15,17 +15,17 @@
 #include "nsWrapperCache.h"
 #include "mozilla/AnimationPerformanceWarning.h"
 #include "mozilla/AnimationTarget.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ComputedTimingFunction.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/KeyframeEffectParams.h"
 #include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
-#include "mozilla/ServoBindingHelpers.h" // ServoDeclarationBlock and
+#include "mozilla/ServoBindingHelpers.h" // RawServoDeclarationBlock and
                                          // associated RefPtrTraits
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/dom/AnimationEffectReadOnly.h"
 #include "mozilla/dom/Element.h"
 
 struct JSContext;
 class JSObject;
 class nsCSSPropertyIDSet;
@@ -62,17 +62,17 @@ struct PropertyValuePair
   // The specified value for the property. For shorthand properties or invalid
   // property values, we store the specified property value as a token stream
   // (string).
   nsCSSValue mValue;
 
   // The specified value when using the Servo backend. However, even when
   // using the Servo backend, we still fill in |mValue| in the case where we
   // fail to parse the value since we use it to store the original string.
-  RefPtr<ServoDeclarationBlock> mServoDeclarationBlock;
+  RefPtr<RawServoDeclarationBlock> mServoDeclarationBlock;
 
   bool operator==(const PropertyValuePair& aOther) const {
     return mProperty == aOther.mProperty &&
            mValue == aOther.mValue &&
            !mServoDeclarationBlock == !aOther.mServoDeclarationBlock &&
            (!mServoDeclarationBlock ||
             Servo_DeclarationBlock_Equals(mServoDeclarationBlock,
                                           aOther.mServoDeclarationBlock));
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -1001,17 +1001,17 @@ MakePropertyValuePair(nsCSSPropertyID aP
     RefPtr<ThreadSafeURIHolder> referrer =
       new ThreadSafeURIHolder(aDocument->GetDocumentURI());
     RefPtr<ThreadSafePrincipalHolder> principal =
       new ThreadSafePrincipalHolder(aDocument->NodePrincipal());
 
     nsCString baseString;
     aDocument->GetDocumentURI()->GetSpec(baseString);
 
-    RefPtr<ServoDeclarationBlock> servoDeclarationBlock =
+    RefPtr<RawServoDeclarationBlock> servoDeclarationBlock =
       Servo_ParseProperty(
         reinterpret_cast<const uint8_t*>(name.get()), name.Length(),
         reinterpret_cast<const uint8_t*>(value.get()), value.Length(),
         reinterpret_cast<const uint8_t*>(baseString.get()), baseString.Length(),
         base, referrer, principal).Consume();
 
     if (servoDeclarationBlock) {
       result.mServoDeclarationBlock = servoDeclarationBlock.forget();
--- a/dom/animation/test/chrome.ini
+++ b/dom/animation/test/chrome.ini
@@ -7,12 +7,12 @@ support-files =
 
 [chrome/test_animate_xrays.html]
 # file_animate_xrays.html needs to go in mochitest.ini since it is served
 # over HTTP
 [chrome/test_animation_observers.html]
 [chrome/test_animation_performance_warning.html]
 [chrome/test_animation_properties.html]
 [chrome/test_generated_content_getAnimations.html]
-[chrome/test_observers_for_script_animation.html]
+[chrome/test_observers_for_sync_api.html]
 [chrome/test_restyles.html]
 [chrome/test_running_on_compositor.html]
 skip-if = buildapp == 'b2g'
--- a/dom/animation/test/chrome/test_animation_observers.html
+++ b/dom/animation/test/chrome/test_animation_observers.html
@@ -13,37 +13,24 @@
   to { transform: translate(0px); }
 }
 #target {
   width: 100px;
   height: 100px;
   background-color: yellow;
   line-height: 16px;
 }
-.init::before {
-  content: "";
-  animation: anim 100s;
-}
 </style>
 <div id=container><div id=target></div></div>
 <script>
 var div = document.getElementById("target");
 var gRecords = [];
-var gRecordPromiseResolvers = [];
 var gObserver = new MutationObserver(function(newRecords) {
   gRecords.push(...newRecords);
-
-  var resolvers = gRecordPromiseResolvers;
-  gRecordPromiseResolvers = [];
-  resolvers.forEach(fn => fn());
 });
-// Get the pseudo element target.
-div.classList.add("init");
-var pseudoTarget = document.getAnimations()[0].effect.target;
-div.classList.remove("init");
 
 // Asynchronous testing framework based on layout/style/test/animation_utils.js.
 
 var gTests = [];
 var gCurrentTestName;
 
 function addAsyncAnimTest(aName, aOptions, aTestGenerator) {
   aTestGenerator.testName = aName;
@@ -610,54 +597,16 @@ function assert_records(expected, desc) 
     // be delivered.
     yield waitForFrame();
     assert_records([{ added: [], changed: [], removed: animations }],
                    "records after animation end");
 
     e.style = "";
   });
 
-  // Test that starting a single animation that is cancelled by calling
-  // cancel() dispatches an added notification and then a removed
-  // notification.
-  addAsyncAnimTest("single_animation_cancelled_api", aOptions, function*() {
-    // Start a short, filled animation.
-    e.style = "animation: anim 100s forwards;";
-
-    // The animation should cause the creation of a single Animation.
-    var animations = e.getAnimations();
-    is(animations.length, 1, "getAnimations().length after animation start");
-
-    // Wait for the single MutationRecord for the Animation addition to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                   "records after animation start");
-
-    // Cancel the animation
-    animations[0].cancel();
-
-    // Wait for the single MutationRecord for the Animation removal to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [], removed: animations }],
-                   "records after animation end");
-
-    // Re-trigger the animation
-    animations[0].play();
-    yield waitForFrame();
-
-    // Wait for the single MutationRecord for the Animation (re-)addition to
-    // be delivered.
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                   "records after animation start");
-
-    e.style = "";
-  });
-
   // Test that updating an animation property dispatches a changed notification.
   [
     { name: "duration",  prop: "animationDuration",       val: "200s"    },
     { name: "timing",    prop: "animationTimingFunction", val: "linear"  },
     { name: "iteration", prop: "animationIterationCount", val: "2"       },
     { name: "direction", prop: "animationDirection",      val: "reverse" },
     { name: "state",     prop: "animationPlayState",      val: "paused"  },
     { name: "delay",     prop: "animationDelay",          val: "-1s"     },
@@ -693,283 +642,16 @@ function assert_records(expected, desc) 
       yield waitForFrame();
       assert_records([{ added: [], changed: [], removed: animations }],
                       "records after animation end");
 
       e.style = "";
     });
   });
 
-  // Test that updating a property on the Animation object dispatches a changed
-  // notification.
-  [
-    { prop: "playbackRate", val: 0.5 },
-    { prop: "startTime",    val: 50 * MS_PER_SEC },
-    { prop: "currentTime",  val: 50 * MS_PER_SEC },
-  ].forEach(function(aChangeTest) {
-    addAsyncAnimTest(`single_animation_api_change_${aChangeTest.prop}`,
-                     aOptions, function*() {
-      // Start a long animation
-      //
-      // We use a forwards fill mode so that even if the change we make causes
-      // the animation to become finished, it will still be "relevant" so we
-      // won't mark it as removed.
-      e.style = "animation: anim 100s forwards";
-
-      // The animation should cause the creation of a single Animation.
-      var animations = e.getAnimations();
-      is(animations.length, 1, "getAnimations().length after animation start");
-
-      // Wait for the single MutationRecord for the Animation addition to
-      // be delivered.
-      yield waitForFrame();
-      assert_records([{ added: animations, changed: [], removed: [] }],
-                     "records after animation start");
-
-      // Wait until the animation is playing
-      yield animations[0].ready;
-
-      // Update the property
-      animations[0][aChangeTest.prop] = aChangeTest.val;
-
-      // Make a redundant change
-      animations[0][aChangeTest.prop] = animations[0][aChangeTest.prop];
-
-      // Wait for the single MutationRecord for the Animation change to
-      // be delivered.
-      yield waitForFrame();
-      assert_records([{ added: [], changed: animations, removed: [] }],
-                     "records after animation property change");
-
-      // Cancel the animation.
-      e.style = "";
-
-      // Wait for the single removal notification.
-      yield waitForFrame();
-      assert_records([{ added: [], changed: [], removed: animations }],
-                     "records after animation end");
-    });
-  });
-
-  addAsyncAnimTest("change_id", aOptions, function*() {
-    e.style.animation = "anim 100s";
-
-    var animation = div.getAnimations()[0];
-    yield waitForFrame();
-    assert_records([{ added: [animation], changed: [], removed: []}],
-                   "records after creation");
-    animation.id = "new id";
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [animation], removed: []}],
-                   "records after id is changed");
-
-    animation.id = "new id";
-    yield waitForFrame();
-    assert_records([],
-                   "records after assigning same value with id");
-
-    e.style.animation = "";
-    yield waitForFrame();
-  });
-
-  // Test that making a redundant change to currentTime while an Animation
-  // is pause-pending still generates a change MutationRecord since setting
-  // the currentTime to any value in this state aborts the pending pause.
-  addAsyncAnimTest("change_currentTime_while_pause_pending", aOptions,
-    function*() {
-    // Start a long animation
-    e.style = "animation: anim 100s";
-
-    // The animation should cause the creation of a single Animation.
-    var animations = e.getAnimations();
-    is(animations.length, 1, "getAnimations().length after animation start");
-
-    // Wait for the single MutationRecord for the Animation addition to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                    "records after animation start");
-
-    // Wait until the animation is playing
-    yield animations[0].ready;
-
-    // Pause the animation
-    animations[0].pause();
-
-    // We are now pause-pending. Even if we make a redundant change to the
-    // currentTime, we should still get a change record because setting the
-    // currentTime while pause-pending has the effect of cancelling a pause.
-    animations[0].currentTime = animations[0].currentTime;
-
-    // Wait for the two MutationRecords for the Animation changes to
-    // be delivered: one for pausing, one for aborting the pause.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: animations, removed: [] },
-                    { added: [], changed: animations, removed: [] }],
-                    "records after pausing then seeking");
-
-    // Cancel the animation.
-    e.style = "";
-
-    // Wait for the single removal notification.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [], removed: animations }],
-                    "records after animation end");
-  });
-
-  // Test that calling reverse() dispatches a changed notification.
-  addAsyncAnimTest("reverse", aOptions, function*() {
-    // Start a long animation
-    e.style = "animation: anim 100s both";
-
-    // The animation should cause the creation of a single Animation.
-    var animations = e.getAnimations();
-    is(animations.length, 1, "getAnimations().length after animation start");
-
-    // Wait for the single MutationRecord for the Animation addition to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                    "records after animation start");
-
-    // Reverse
-    animations[0].reverse();
-
-    // Wait for the single MutationRecord for the Animation change to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: animations, removed: [] }],
-                    "records after calling reverse()");
-
-    // Cancel the animation.
-    e.style = "";
-
-    // Wait for the single removal notification.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [], removed: animations }],
-                    "records after animation end");
-  });
-
-  // Test that calling reverse() does *not* dispatch a changed notification
-  // when playbackRate == 0.
-  addAsyncAnimTest("reverse_with_zero_playbackRate", aOptions, function*() {
-    // Start a long animation
-    e.style = "animation: anim 100s both";
-
-    // The animation should cause the creation of a single Animation.
-    var animations = e.getAnimations();
-    is(animations.length, 1, "getAnimations().length after animation start");
-
-    // Wait for the single MutationRecord for the Animation addition to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                    "records after animation start");
-
-    // Seek to the middle and set playbackRate to zero.
-    animations[0].currentTime = 50 * MS_PER_SEC;
-    animations[0].playbackRate = 0;
-
-    // Wait for the MutationRecords, one for each change, to be delivered.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: animations, removed: [] },
-                    { added: [], changed: animations, removed: [] }],
-                    "records after seeking and setting playbackRate");
-
-    // Reverse
-    animations[0].reverse();
-
-    // We should get no notifications.
-    assert_records([], "records after calling reverse()");
-
-    // Cancel the animation.
-    e.style = "";
-
-    // Wait for the single removal notification.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [], removed: animations }],
-                    "records after animation end");
-  });
-
-  // Test that calling finish() on a forwards-filling Animation dispatches
-  // a changed notification.
-  addAsyncAnimTest("finish_with_forwards_fill", aOptions, function*() {
-    // Start a long animation
-    e.style = "animation: anim 100s forwards";
-
-    // The animation should cause the creation of a single Animation.
-    var animations = e.getAnimations();
-    is(animations.length, 1, "getAnimations().length after animation start");
-
-    // Wait for the single MutationRecord for the Animation addition to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                    "records after animation start");
-
-    // Wait until the animation is playing
-    yield animations[0].ready;
-
-    // Finish
-    animations[0].finish();
-
-    // Wait for the single MutationRecord for the Animation change to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: animations, removed: [] }],
-                    "records after finish()");
-
-    // Redundant finish
-    animations[0].finish();
-
-    // Wait to ensure no change is dispatched
-    yield waitForFrame();
-    assert_records([], "records after redundant finish()");
-
-    // Cancel the animation.
-    e.style = "";
-
-    // Wait for the single removal notification.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [], removed: animations }],
-                    "records after animation end");
-  });
-
-  // Test that calling finish() on an Animation that does not fill forwards,
-  // dispatches a removal notification.
-  addAsyncAnimTest("finish_without_fill", aOptions, function*() {
-    // Start a long animation
-    e.style = "animation: anim 100s";
-
-    // The animation should cause the creation of a single Animation.
-    var animations = e.getAnimations();
-    is(animations.length, 1, "getAnimations().length after animation start");
-
-    // Wait for the single MutationRecord for the Animation addition to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: [] }],
-                    "records after animation start");
-
-    // Wait until the animation is playing
-    yield animations[0].ready;
-
-    // Finish
-    animations[0].finish();
-
-    // Wait for the single MutationRecord for the Animation removal to
-    // be delivered.
-    yield waitForFrame();
-    assert_records([{ added: [], changed: [], removed: animations }],
-                    "records after finishing");
-
-    // Cancel the animation.
-    e.style = "";
-  });
-
   // Test that calling finish() on a paused (but otherwise finished) animation
   // dispatches a changed notification.
   addAsyncAnimTest("finish_from_pause", aOptions, function*() {
     // Start a long animation
     e.style = "animation: anim 100s forwards";
 
     // The animation should cause the creation of a single Animation.
     var animations = e.getAnimations();
@@ -1353,55 +1035,16 @@ function assert_records(expected, desc) 
     // We should get a single removal notification.
     yield waitForFrame();
     assert_records([{ added: [], changed: [], removed: animations }],
                    "records after animation end");
 
     e.style = "";
   });
 
-  // Test that attempting to start an animation that should already be finished
-  // does not send any notifications.
-  addAsyncAnimTest("already_finished", aOptions, function*() {
-    // Start an animation that should already be finished.
-    e.style = "animation: anim 1s -2s;";
-
-    // The animation should cause no Animations to be created.
-    var animations = e.getAnimations();
-    is(animations.length, 0, "getAnimations().length after animation start");
-
-    // And we should get no notifications.
-    yield waitForFrame();
-    assert_records([], "records after attempted animation start");
-
-    e.style = "";
-  });
-
-  addAsyncAnimTest("animtion_order_change", aOptions, function*() {
-    e.style.animation = "anim 100s, anotherAnim 100s";
-
-    var animations = e.getAnimations();
-    yield waitForFrame();
-    assert_records([{ added: animations, changed: [], removed: []}],
-                   "records after creation");
-    e.style.animation = "anotherAnim 100s, anim 100s";
-    animations = e.getAnimations();
-    yield waitForFrame();
-    assert_records([{ added: [], changed: animations, removed: []}],
-                   "records after the order is changed");
-
-    e.style.animation = "anotherAnim 100s, anim 100s";
-    yield waitForFrame();
-    assert_records([],
-                   "no records after applying the same order");
-
-    e.style.animation = "";
-    yield waitForFrame();
-  });
-
 });
 
 addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
   // Add style for pseudo elements
   var extraStyle = document.createElement('style');
   document.head.appendChild(extraStyle);
   var sheet = extraStyle.sheet;
   var rules = { ".before::before": "animation: anim 100s;",
@@ -1517,75 +1160,16 @@ addAsyncAnimTest("tree_ordering", { obse
   div.classList.remove("before");
   div.classList.remove("after");
   div.style = "";
   childA.remove();
   childB.remove();
   extraStyle.remove();
 });
 
-addAsyncAnimTest("change_duration_and_currenttime",
-                 { observe: div, subtree: true }, function*() {
-  var anim = pseudoTarget.animate({ opacity: [ 0, 1 ] }, 200 * MS_PER_SEC);
-
-  yield waitForFrame();
-  assert_records([{ added: [anim], changed: [], removed: [] }],
-                 "records after animation is added");
-
-  anim.effect.timing.duration = 100 * MS_PER_SEC;
-  yield waitForFrame();
-  assert_records([{ added: [], changed: [anim], removed: [] }],
-                 "records after duration is changed");
-
-  anim.effect.timing.duration = 100 * MS_PER_SEC;
-  yield waitForFrame();
-  assert_records([], "records after assigning same value");
-
-  anim.currentTime = anim.effect.timing.duration * 2;
-  anim.finish();
-  yield waitForFrame();
-  assert_records([{ added: [], changed: [], removed: [anim] }],
-                 "records after animation end");
-
-  anim.effect.timing.duration = anim.effect.timing.duration * 3;
-  yield waitForFrame();
-  assert_records([{ added: [anim], changed: [], removed: [] }],
-                 "records after animation restarted");
-
-  anim.effect.timing.duration = "auto";
-  yield waitForFrame();
-  assert_records([{ added: [], changed: [], removed: [anim] }],
-                 "records after duration set \"auto\"");
-
-  anim.effect.timing.duration = "auto";
-  yield waitForFrame();
-  assert_records([], "records after assigning same value \"auto\"");
-
-  anim.cancel();
-  yield waitForFrame();
-});
-
-addAsyncAnimTest("exclude_animations_targeting_pseudo_elements",
-                 { observe: div, subtree: false }, function*() {
-  var anim = div.animate({ opacity: [ 0, 1 ] },
-                         { duration: 100 * MS_PER_SEC });
-  var pAnim = pseudoTarget.animate({ opacity: [ 0, 1 ] },
-                                   { duration: 100 * MS_PER_SEC });
-
-  yield waitForFrame();
-  assert_records([{ added: [anim], changed: [], removed: [] }],
-                 "records after animation is added");
-
-  anim.finish();
-  pAnim.finish();
-  yield waitForFrame();
-  assert_records([{ added: [], changed: [], removed: [anim] }],
-                 "records after animation is finished");
-});
-
 // Run the tests.
 SimpleTest.requestLongerTimeout(2);
 SimpleTest.waitForExplicitFinish();
 
 runAllAsyncTests().then(function() {
   SimpleTest.finish();
 }, function(aError) {
   ok(false, "Something failed: " + aError);
rename from dom/animation/test/chrome/test_observers_for_script_animation.html
rename to dom/animation/test/chrome/test_observers_for_sync_api.html
--- a/dom/animation/test/chrome/test_observers_for_script_animation.html
+++ b/dom/animation/test/chrome/test_observers_for_sync_api.html
@@ -1,18 +1,25 @@
 <!DOCTYPE html>
 <meta charset=utf-8>
 <title>
-Test chrome-only MutationObserver animation notifications for script
-animations
+Test chrome-only MutationObserver animation notifications for sync APIs
 </title>
 <script type="application/javascript" src="../testharness.js"></script>
 <script type="application/javascript" src="../testharnessreport.js"></script>
 <script type="application/javascript" src="../testcommon.js"></script>
 <div id="log"></div>
+<style>
+@keyframes anim {
+  to { transform: translate(100px); }
+}
+@keyframes anotherAnim {
+  to { transform: translate(0px); }
+}
+</style>
 <script>
 
 function assert_record_list(actual, expected, desc, index, listName) {
   assert_equals(actual.length, expected.length,
                 `${desc} - record[${index}].${listName} length`);
   if (actual.length != expected.length) {
     return;
   }
@@ -32,16 +39,30 @@ function assert_equals_records(actual, e
                        expected[i].added, desc, i, "addedAnimations");
     assert_record_list(actual[i].changedAnimations,
                        expected[i].changed, desc, i, "changedAnimations");
     assert_record_list(actual[i].removedAnimations,
                        expected[i].removed, desc, i, "removedAnimations");
   }
 }
 
+// Create a pseudo element
+function createPseudo(test, element, type) {
+  addStyle(test, { '@keyframes anim': '',
+                   ['.pseudo::' + type]: 'animation: anim 10s;' });
+  element.classList.add('pseudo');
+  var anims = document.getAnimations();
+  assert_true(anims.length >= 1);
+  var anim = anims[anims.length - 1];
+  assert_equals(anim.effect.target.parentElement, element);
+  assert_equals(anim.effect.target.type, '::' + type);
+  anim.cancel();
+  return anim.effect.target;
+}
+
 [ { subtree: false },
   { subtree: true }
 ].forEach(aOptions => {
   test(t => {
     var div = addDiv(t);
     var observer =
       setupSynchronousObserver(t,
                                aOptions.subtree ? div.parentNode : div,
@@ -417,16 +438,301 @@ function assert_equals_records(actual, e
     assert_equals_records(observer.takeRecords(),
       [{ added: [anim], changed: [], removed: [] }],
       "records after animation is added");
 
     anim.effect.spacing = "paced(margin-left)";
     assert_equals_records(observer.takeRecords(),
       [], "no record after setting the same spacing");
   }, "set_the_same_spacing");
+
+  // Test that starting a single animation that is cancelled by calling
+  // cancel() dispatches an added notification and then a removed
+  // notification.
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s forwards" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1,
+      "getAnimations().length after animation start");
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+
+    animations[0].cancel();
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: [], removed: animations }],
+      "records after animation end");
+
+    // Re-trigger the animation.
+    animations[0].play();
+
+    // Single MutationRecord for the Animation (re-)addition.
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+  }, "single_animation_cancelled_api");
+
+  // Test that updating a property on the Animation object dispatches a changed
+  // notification.
+  [
+    { prop: "playbackRate", val: 0.5 },
+    { prop: "startTime",    val: 50 * MS_PER_SEC },
+    { prop: "currentTime",  val: 50 * MS_PER_SEC },
+  ].forEach(function(aChangeTest) {
+    test(t => {
+      // We use a forwards fill mode so that even if the change we make causes
+      // the animation to become finished, it will still be "relevant" so we
+      // won't mark it as removed.
+      var div = addDiv(t, { style: "animation: anim 100s forwards" });
+      var observer =
+        setupSynchronousObserver(t,
+                                 aOptions.subtree ? div.parentNode : div,
+                                 aOptions.subtree);
+
+      var animations = div.getAnimations();
+      assert_equals(animations.length, 1,
+        "getAnimations().length after animation start");
+
+      assert_equals_records(observer.takeRecords(),
+        [{ added: animations, changed: [], removed: [] }],
+        "records after animation start");
+
+      // Update the property.
+      animations[0][aChangeTest.prop] = aChangeTest.val;
+
+      // Make a redundant change.
+      animations[0][aChangeTest.prop] = animations[0][aChangeTest.prop];
+
+      assert_equals_records(observer.takeRecords(),
+        [{ added: [], changed: animations, removed: [] }],
+        "records after animation property change");
+    }, `single_animation_api_change_${aChangeTest.prop}`);
+  });
+
+  // Test that making a redundant change to currentTime while an Animation
+  // is pause-pending still generates a change MutationRecord since setting
+  // the currentTime to any value in this state aborts the pending pause.
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1,
+      "getAnimations().length after animation start");
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+
+    animations[0].pause();
+
+    // We are now pause-pending. Even if we make a redundant change to the
+    // currentTime, we should still get a change record because setting the
+    // currentTime while pause-pending has the effect of cancelling a pause.
+    animations[0].currentTime = animations[0].currentTime;
+
+    // Two MutationRecords for the Animation changes: one for pausing, one
+    // for aborting the pause.
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: animations, removed: [] },
+       { added: [], changed: animations, removed: [] }],
+      "records after pausing then seeking");
+  }, "change_currentTime_while_pause_pending");
+
+  // Test that calling finish() on a forwards-filling Animation dispatches
+  // a changed notification.
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s forwards" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1,
+      "getAnimations().length after animation start");
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+
+    animations[0].finish();
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: animations, removed: [] }],
+      "records after finish()");
+
+    // Redundant finish.
+    animations[0].finish();
+
+    // Ensure no change records.
+    assert_equals_records(observer.takeRecords(),
+      [], "records after redundant finish()");
+  }, "finish_with_forwards_fill");
+
+  // Test that calling finish() on an Animation that does not fill forwards,
+  // dispatches a removal notification.
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1,
+      "getAnimations().length after animation start");
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+
+    animations[0].finish();
+
+    // Single MutationRecord for the Animation removal.
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: [], removed: animations }],
+      "records after finishing");
+  }, "finish_without_fill");
+
+  // Test that calling finish() on a forwards-filling Animation dispatches
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animation = div.getAnimations()[0];
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [animation], changed: [], removed: []}],
+      "records after creation");
+    animation.id = "new id";
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: [animation], removed: []}],
+      "records after id is changed");
+
+    animation.id = "new id";
+    assert_equals_records(observer.takeRecords(),
+      [], "records after assigning same value with id");
+  }, "change_id");
+
+  // Test that calling reverse() dispatches a changed notification.
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s both" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1,
+      "getAnimations().length after animation start");
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+
+    animations[0].reverse();
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: animations, removed: [] }],
+      "records after calling reverse()");
+  }, "reverse");
+
+  // Test that calling reverse() does *not* dispatch a changed notification
+  // when playbackRate == 0.
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s both" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1,
+      "getAnimations().length after animation start");
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: [] }],
+      "records after animation start");
+
+    // Seek to the middle and set playbackRate to zero.
+    animations[0].currentTime = 50 * MS_PER_SEC;
+    animations[0].playbackRate = 0;
+
+    // Two MutationRecords, one for each change.
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: animations, removed: [] },
+       { added: [], changed: animations, removed: [] }],
+      "records after seeking and setting playbackRate");
+
+    animations[0].reverse();
+
+    // We should get no notifications.
+    assert_equals_records(observer.takeRecords(),
+      [], "records after calling reverse()");
+  }, "reverse_with_zero_playbackRate");
+
+  // Test that attempting to start an animation that should already be finished
+  // does not send any notifications.
+  test(t => {
+    // Start an animation that should already be finished.
+    var div = addDiv(t, { style: "animation: anim 1s -2s;" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    // The animation should cause no Animations to be created.
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 0,
+      "getAnimations().length after animation start");
+
+    // And we should get no notifications.
+    assert_equals_records(observer.takeRecords(),
+      [], "records after attempted animation start");
+  }, "already_finished");
+
+  test(t => {
+    var div = addDiv(t, { style: "animation: anim 100s, anotherAnim 100s" });
+    var observer =
+      setupSynchronousObserver(t,
+                               aOptions.subtree ? div.parentNode : div,
+                               aOptions.subtree);
+
+    var animations = div.getAnimations();
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: animations, changed: [], removed: []}],
+      "records after creation");
+
+    div.style.animation = "anotherAnim 100s, anim 100s";
+    animations = div.getAnimations();
+
+    assert_equals_records(observer.takeRecords(),
+      [{ added: [], changed: animations, removed: []}],
+      "records after the order is changed");
+
+    div.style.animation = "anotherAnim 100s, anim 100s";
+
+    assert_equals_records(observer.takeRecords(),
+      [], "no records after applying the same order");
+  }, "animtion_order_change");
+
 });
 
 test(t => {
   var div = addDiv(t);
   var observer = setupSynchronousObserver(t, div, true);
 
   var child = document.createElement("div");
   div.appendChild(child);
@@ -477,9 +783,72 @@ test(t => {
 
   anim.effect.target = addDiv(t);
   assert_equals_records(observer.takeRecords(),
     [{ added: [], changed: [], removed: [anim] },
      { added: [anim], changed: [], removed: [] }],
     "records after setting a different target");
 }, "set_animation_target");
 
+test(t => {
+  var div = addDiv(t);
+  var pseudoTarget = createPseudo(t, div, 'before');
+  var observer = setupSynchronousObserver(t, div, true);
+
+  var anim = pseudoTarget.animate({ opacity: [ 0, 1 ] }, 200 * MS_PER_SEC);
+
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [anim], changed: [], removed: [] }],
+    "records after animation is added");
+
+  anim.effect.timing.duration = 100 * MS_PER_SEC;
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [], changed: [anim], removed: [] }],
+    "records after duration is changed");
+
+  anim.effect.timing.duration = 100 * MS_PER_SEC;
+  assert_equals_records(observer.takeRecords(),
+    [], "records after assigning same value");
+
+  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.finish();
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [], changed: [], removed: [anim] }],
+    "records after animation end");
+
+  anim.effect.timing.duration = anim.effect.timing.duration * 3;
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [anim], changed: [], removed: [] }],
+    "records after animation restarted");
+
+  anim.effect.timing.duration = "auto";
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [], changed: [], removed: [anim] }],
+    "records after duration set \"auto\"");
+
+  anim.effect.timing.duration = "auto";
+  assert_equals_records(observer.takeRecords(),
+    [], "records after assigning same value \"auto\"");
+}, "change_duration_and_currenttime_on_pseudo_elements");
+
+test(t => {
+  var div = addDiv(t);
+  var pseudoTarget = createPseudo(t, div, 'before');
+  var observer = setupSynchronousObserver(t, div, false);
+
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { duration: 100 * MS_PER_SEC });
+  var pAnim = pseudoTarget.animate({ opacity: [ 0, 1 ] },
+                                   { duration: 100 * MS_PER_SEC });
+
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [anim], changed: [], removed: [] }],
+    "records after animation is added");
+
+  anim.finish();
+  pAnim.finish();
+
+  assert_equals_records(observer.takeRecords(),
+    [{ added: [], changed: [], removed: [anim] }],
+    "records after animation is finished");
+}, "exclude_animations_targeting_pseudo_elements");
+
 </script>
--- a/dom/apps/AppsService.js
+++ b/dom/apps/AppsService.js
@@ -32,32 +32,16 @@ function AppsService()
 
 AppsService.prototype = {
 
   isInvalidId: function(localId) {
     return (localId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
             localId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID);
   },
 
-  getManifestCSPByLocalId: function getCSPByLocalId(localId) {
-    debug("GetManifestCSPByLocalId( " + localId + " )");
-    if (this.isInvalidId(localId)) {
-      return null;
-    }
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-
-  getDefaultCSPByLocalId: function getCSPByLocalId(localId) {
-    debug("GetDefaultCSPByLocalId( " + localId + " )");
-    if (this.isInvalidId(localId)) {
-      return null;
-    }
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-
   getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
     debug("GetAppByManifestURL( " + aManifestURL + " )");
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
   getManifestFor: function getManifestFor(aManifestURL) {
     debug("getManifestFor(" + aManifestURL + ")");
     if (this.inParent) {
--- a/dom/apps/AppsServiceChild.jsm
+++ b/dom/apps/AppsServiceChild.jsm
@@ -366,26 +366,16 @@ this.DOMApplicationRegistry = {
     return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
   },
 
   getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
     debug("getAppLocalIdByManifestURL " + aManifestURL);
     return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
   },
 
-  getManifestCSPByLocalId: function(aLocalId) {
-    debug("getManifestCSPByLocalId:" + aLocalId);
-    return AppsUtils.getManifestCSPByLocalId(this.webapps, aLocalId);
-  },
-
-  getDefaultCSPByLocalId: function(aLocalId) {
-    debug("getDefaultCSPByLocalId:" + aLocalId);
-    return AppsUtils.getDefaultCSPByLocalId(this.webapps, aLocalId);
-  },
-
   getAppLocalIdByStoreId: function(aStoreId) {
     debug("getAppLocalIdByStoreId:" + aStoreId);
     return AppsUtils.getAppLocalIdByStoreId(this.webapps, aStoreId);
   },
 
   getAppByLocalId: function getAppByLocalId(aLocalId) {
     debug("getAppByLocalId " + aLocalId + " - ready: " + this.ready);
     let app = this.localIdIndex[aLocalId];
--- a/dom/apps/AppsUtils.jsm
+++ b/dom/apps/AppsUtils.jsm
@@ -257,53 +257,16 @@ this.AppsUtils = {
       if (aApps[id].storeId == aStoreId) {
         return aApps[id].localId;
       }
     }
 
     return Ci.nsIScriptSecurityManager.NO_APP_ID;
   },
 
-  getManifestCSPByLocalId: function getManifestCSPByLocalId(aApps, aLocalId) {
-    debug("getManifestCSPByLocalId " + aLocalId);
-    for (let id in aApps) {
-      let app = aApps[id];
-      if (app.localId == aLocalId) {
-        return ( app.csp || "" );
-      }
-    }
-
-    return "";
-  },
-
-  getDefaultCSPByLocalId: function(aApps, aLocalId) {
-    debug("getDefaultCSPByLocalId " + aLocalId);
-    for (let id in aApps) {
-      let app = aApps[id];
-      if (app.localId == aLocalId) {
-        // Use the app status to choose the right default CSP.
-        try {
-          switch (app.appStatus) {
-            case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
-              return Services.prefs.getCharPref("security.apps.certified.CSP.default");
-              break;
-            case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
-              return Services.prefs.getCharPref("security.apps.privileged.CSP.default");
-              break;
-            case Ci.nsIPrincipal.APP_STATUS_INSTALLED:
-              return "";
-              break;
-          }
-        } catch(e) {}
-      }
-    }
-
-    return "default-src 'self'; object-src 'none'";
-  },
-
   getAppByLocalId: function getAppByLocalId(aApps, aLocalId) {
     debug("getAppByLocalId " + aLocalId);
     for (let id in aApps) {
       let app = aApps[id];
       if (app.localId == aLocalId) {
         return new mozIApplication(app);
       }
     }
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -557,17 +557,17 @@ IsNativeAnonymousImplementationOfPseudoE
 
   // Finally check the actual pseudo type.
   bool isImpl = pseudoType != CSSPseudoElementType::NotPseudo;
   MOZ_ASSERT_IF(isImpl, aContent->IsRootOfNativeAnonymousSubtree());
   return isImpl;
 }
 
 /* static */ bool
-StyleChildrenIterator::IsNeeded(Element* aElement)
+StyleChildrenIterator::IsNeeded(const Element* aElement)
 {
   // If the node is in an anonymous subtree, we conservatively return true to
   // handle insertion points.
   if (aElement->IsInAnonymousSubtree()) {
     return true;
   }
 
   // If the node has an XBL binding with anonymous content return true.
--- a/dom/base/ChildIterator.h
+++ b/dom/base/ChildIterator.h
@@ -30,17 +30,18 @@ namespace dom {
 // <xbl:children> nodes replaced by the elements that have been filtered into that
 // insertion point. Any bindings on the given element are ignored for purposes
 // of determining which insertion point children are filtered into. The iterator
 // can be initialized to start at the end by providing false for aStartAtBeginning
 // in order to start iterating in reverse from the last child.
 class ExplicitChildIterator
 {
 public:
-  explicit ExplicitChildIterator(nsIContent* aParent, bool aStartAtBeginning = true)
+  explicit ExplicitChildIterator(const nsIContent* aParent,
+                                 bool aStartAtBeginning = true)
     : mParent(aParent),
       mChild(nullptr),
       mDefaultChild(nullptr),
       mIndexInInserted(0),
       mIsFirst(aStartAtBeginning)
   {
   }
 
@@ -94,17 +95,17 @@ public:
   // The inverse of GetNextChild. Properly steps in and out of insertion
   // points.
   nsIContent* GetPreviousChild();
 
 protected:
   // The parent of the children being iterated. For the FlattenedChildIterator,
   // if there is a binding attached to the original parent, mParent points to
   // the <xbl:content> element for the binding.
-  nsIContent* mParent;
+  const nsIContent* mParent;
 
   // The current child. When we encounter an insertion point,
   // mChild remains as the insertion point whose content we're iterating (and
   // our state is controled by mDefaultChild or mIndexInInserted depending on
   // whether the insertion point expands to its default content or not).
   nsIContent* mChild;
 
   // If non-null, this points to the current default content for the current
@@ -131,17 +132,18 @@ protected:
 // Iterates over the flattened children of a node, which accounts for anonymous
 // children and nodes moved by insertion points. If a node has anonymous
 // children, those are iterated over.  The iterator can be initialized to start
 // at the end by providing false for aStartAtBeginning in order to start
 // iterating in reverse from the last child.
 class FlattenedChildIterator : public ExplicitChildIterator
 {
 public:
-  explicit FlattenedChildIterator(nsIContent* aParent, bool aStartAtBeginning = true)
+  explicit FlattenedChildIterator(const nsIContent* aParent,
+                                  bool aStartAtBeginning = true)
     : ExplicitChildIterator(aParent, aStartAtBeginning), mXBLInvolved(false)
   {
     Init(false);
   }
 
   FlattenedChildIterator(FlattenedChildIterator&& aOther)
     : ExplicitChildIterator(Move(aOther)), mXBLInvolved(aOther.mXBLInvolved) {}
 
@@ -150,17 +152,18 @@ public:
 
   bool XBLInvolved() { return mXBLInvolved; }
 
 protected:
   /**
    * This constructor is a hack to help AllChildrenIterator which sometimes
    * doesn't want to consider XBL.
    */
-  FlattenedChildIterator(nsIContent* aParent, uint32_t aFlags, bool aStartAtBeginning = true)
+  FlattenedChildIterator(const nsIContent* aParent, uint32_t aFlags,
+                         bool aStartAtBeginning = true)
     : ExplicitChildIterator(aParent, aStartAtBeginning), mXBLInvolved(false)
   {
     bool ignoreXBL = aFlags & nsIContent::eAllButXBL;
     Init(ignoreXBL);
   }
 
   void Init(bool aIgnoreXBL);
 
@@ -176,17 +179,18 @@ protected:
  * start iterating in reverse from the last child.
  *
  * Note: it assumes that no mutation of the DOM or frame tree takes place during
  * iteration, and will break horribly if that is not true.
  */
 class AllChildrenIterator : private FlattenedChildIterator
 {
 public:
-  AllChildrenIterator(nsIContent* aNode, uint32_t aFlags, bool aStartAtBeginning = true) :
+  AllChildrenIterator(const nsIContent* aNode, uint32_t aFlags,
+                      bool aStartAtBeginning = true) :
     FlattenedChildIterator(aNode, aFlags, aStartAtBeginning),
     mOriginalContent(aNode), mAnonKidsIdx(aStartAtBeginning ? UINT32_MAX : 0),
     mFlags(aFlags), mPhase(aStartAtBeginning ? eAtBegin : eAtEnd) { }
 
   AllChildrenIterator(AllChildrenIterator&& aOther)
     : FlattenedChildIterator(Move(aOther)),
       mOriginalContent(aOther.mOriginalContent),
       mAnonKids(Move(aOther.mAnonKids)), mAnonKidsIdx(aOther.mAnonKidsIdx),
@@ -206,17 +210,17 @@ public:
 
   // Seeks the given node in children of a parent element, starting from
   // the current iterator's position, and sets the iterator at the given child
   // node if it was found.
   bool Seek(nsIContent* aChildToFind);
 
   nsIContent* GetNextChild();
   nsIContent* GetPreviousChild();
-  nsIContent* Parent() const { return mOriginalContent; }
+  const nsIContent* Parent() const { return mOriginalContent; }
 
   enum IteratorPhase
   {
     eAtBegin,
     eAtBeforeKid,
     eAtExplicitKids,
     eAtAnonKids,
     eAtAfterKid,
@@ -224,17 +228,17 @@ public:
   };
   IteratorPhase Phase() const { return mPhase; }
 
 private:
   // Helpers.
   void AppendNativeAnonymousChildren();
   void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame);
 
-  nsIContent* mOriginalContent;
+  const nsIContent* mOriginalContent;
 
   // mAnonKids is an array of native anonymous children, mAnonKidsIdx is index
   // in the array. If mAnonKidsIdx < mAnonKids.Length() and mPhase is
   // eAtAnonKids then the iterator points at a child at mAnonKidsIdx index. If
   // mAnonKidsIdx == mAnonKids.Length() then the iterator is somewhere after
   // the last native anon child. If mAnonKidsIdx == UINT32_MAX then the iterator
   // is somewhere before the first native anon child.
   nsTArray<nsIContent*> mAnonKids;
@@ -257,26 +261,26 @@ private:
  * to implement pseudo-elements (since the style system needs to cascade those
  * using different algorithms).
  *
  * Note: it assumes that no mutation of the DOM or frame tree takes place during
  * iteration, and will break horribly if that is not true.
  */
 class StyleChildrenIterator : private AllChildrenIterator {
 public:
-  explicit StyleChildrenIterator(nsIContent* aContent)
+  explicit StyleChildrenIterator(const nsIContent* aContent)
     : AllChildrenIterator(aContent, nsIContent::eAllChildren)
   {
     MOZ_COUNT_CTOR(StyleChildrenIterator);
   }
   ~StyleChildrenIterator() { MOZ_COUNT_DTOR(StyleChildrenIterator); }
 
   nsIContent* GetNextChild();
 
   // Returns true if we cannot find all the children we need to style by
   // traversing the siblings of the first child.
-  static bool IsNeeded(Element* aParent);
+  static bool IsNeeded(const Element* aParent);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2009,24 +2009,24 @@ Element::IsLabelable() const
 }
 
 bool
 Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return false;
 }
 
-css::Declaration*
+DeclarationBlock*
 Element::GetInlineStyleDeclaration()
 {
   return nullptr;
 }
 
 nsresult
-Element::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+Element::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                    const nsAString* aSerialized,
                                    bool aNotify)
 {
   NS_NOTYETIMPLEMENTED("Element::SetInlineStyleDeclaration");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP_(bool)
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -51,16 +51,17 @@ struct nsRect;
 class nsFocusManager;
 class nsGlobalWindow;
 class nsICSSDeclaration;
 class nsISMILAttr;
 class nsDocument;
 class nsDOMStringMap;
 
 namespace mozilla {
+class DeclarationBlock;
 namespace dom {
   struct AnimationFilter;
   struct ScrollIntoViewOptions;
   struct ScrollToOptions;
   class ElementOrCSSPseudoElement;
   class UnrestrictedDoubleOrKeyframeAnimationOptions;
 } // namespace dom
 } // namespace mozilla
@@ -249,23 +250,23 @@ public:
   /**
    * Clear all style state locks on this element.
    */
   void ClearStyleStateLocks();
 
   /**
    * Get the inline style declaration, if any, for this element.
    */
-  virtual css::Declaration* GetInlineStyleDeclaration();
+  virtual DeclarationBlock* GetInlineStyleDeclaration();
 
   /**
    * Set the inline style declaration for this element. This will send
    * an appropriate AttributeChanged notification if aNotify is true.
    */
-  virtual nsresult SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+  virtual nsresult SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                              const nsAString* aSerialized,
                                              bool aNotify);
 
   /**
    * Get the SMIL override style declaration for this element. If the
    * rule hasn't been created, this method simply returns null.
    */
   virtual css::Declaration* GetSMILOverrideStyleDeclaration();
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -28,16 +28,19 @@ class nsDOMAttributeMap;
 class nsDOMTokenList;
 class nsIControllers;
 class nsICSSDeclaration;
 class nsIDocument;
 class nsDOMStringMap;
 class nsIURI;
 
 namespace mozilla {
+namespace css {
+class Declaration;
+} // namespace css
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 /**
  * A class that implements nsIWeakReference
  */
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -13,17 +13,17 @@
 #include "mozilla/HashFunctions.h"
 
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsIAtom.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ServoBindingHelpers.h"
-#include "mozilla/css/Declaration.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "prprf.h"
 #include "nsHTMLCSSStyleSheet.h"
 #include "nsCSSParser.h"
 #include "nsStyledElement.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
@@ -68,89 +68,59 @@ MiscContainer::GetString(nsAString& aStr
   atom->ToString(aString);
   return true;
 }
 
 void
 MiscContainer::Cache()
 {
   // Not implemented for anything else yet.
-  MOZ_ASSERT(mType == nsAttrValue::eGeckoCSSDeclaration ||
-             mType == nsAttrValue::eServoCSSDeclaration);
+  if (mType != nsAttrValue::eCSSDeclaration) {
+    MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
+    return;
+  }
+
   MOZ_ASSERT(IsRefCounted());
   MOZ_ASSERT(mValue.mRefCount > 0);
   MOZ_ASSERT(!mValue.mCached);
 
-  nsHTMLCSSStyleSheet* sheet;
-  switch (mType) {
-    case nsAttrValue::eGeckoCSSDeclaration:
-      sheet = mValue.mGeckoCSSDeclaration->GetHTMLCSSStyleSheet();
-      break;
-    case nsAttrValue::eServoCSSDeclaration:
-      sheet = Servo_DeclarationBlock_GetCache(mValue.mServoCSSDeclaration);
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-      sheet = nullptr;
-      break;
-  }
-
+  nsHTMLCSSStyleSheet* sheet = mValue.mCSSDeclaration->GetHTMLCSSStyleSheet();
   if (!sheet) {
     return;
   }
 
   nsString str;
   bool gotString = GetString(str);
   if (!gotString) {
     return;
   }
 
   sheet->CacheStyleAttr(str, this);
   mValue.mCached = 1;
 
   // This has to be immutable once it goes into the cache.
-  switch (mType) {
-    case nsAttrValue::eGeckoCSSDeclaration:
-      mValue.mGeckoCSSDeclaration->SetImmutable();
-      break;
-    case nsAttrValue::eServoCSSDeclaration:
-      Servo_DeclarationBlock_SetImmutable(mValue.mServoCSSDeclaration);
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-      break;
-  }
+  mValue.mCSSDeclaration->SetImmutable();
 }
 
 void
 MiscContainer::Evict()
 {
   // Not implemented for anything else yet.
-  MOZ_ASSERT(mType == nsAttrValue::eGeckoCSSDeclaration ||
-             mType == nsAttrValue::eServoCSSDeclaration);
+  if (mType != nsAttrValue::eCSSDeclaration) {
+    MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
+    return;
+  }
   MOZ_ASSERT(IsRefCounted());
   MOZ_ASSERT(mValue.mRefCount == 0);
 
   if (!mValue.mCached) {
     return;
   }
 
-  nsHTMLCSSStyleSheet* sheet;
-  switch (mType) {
-    case nsAttrValue::eGeckoCSSDeclaration:
-      sheet = mValue.mGeckoCSSDeclaration->GetHTMLCSSStyleSheet();
-      break;
-    case nsAttrValue::eServoCSSDeclaration:
-      sheet = Servo_DeclarationBlock_GetCache(mValue.mServoCSSDeclaration);
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-      sheet = nullptr;
-      break;
-  }
+  nsHTMLCSSStyleSheet* sheet = mValue.mCSSDeclaration->GetHTMLCSSStyleSheet();
   MOZ_ASSERT(sheet);
 
   nsString str;
   DebugOnly<bool> gotString = GetString(str);
   MOZ_ASSERT(gotString);
 
   sheet->EvictStyleAttr(str, this);
   mValue.mCached = 0;
@@ -176,20 +146,21 @@ nsAttrValue::nsAttrValue(const nsAString
 }
 
 nsAttrValue::nsAttrValue(nsIAtom* aValue)
     : mBits(0)
 {
   SetTo(aValue);
 }
 
-nsAttrValue::nsAttrValue(css::Declaration* aValue, const nsAString* aSerialized)
+nsAttrValue::nsAttrValue(already_AddRefed<DeclarationBlock> aValue,
+                         const nsAString* aSerialized)
     : mBits(0)
 {
-  SetTo(aValue, aSerialized);
+  SetTo(Move(aValue), aSerialized);
 }
 
 nsAttrValue::nsAttrValue(const nsIntMargin& aValue)
     : mBits(0)
 {
   SetTo(aValue);
 }
 
@@ -338,18 +309,17 @@ nsAttrValue::SetTo(const nsAttrValue& aO
       cont->mValue.mPercent = otherCont->mValue.mPercent;
       break;
     }
     case eColor:
     {
       cont->mValue.mColor = otherCont->mValue.mColor;
       break;
     }
-    case eGeckoCSSDeclaration:
-    case eServoCSSDeclaration:
+    case eCSSDeclaration:
     {
       MOZ_CRASH("These should be refcounted!");
     }
     case eURL:
     {
       NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL);
       break;
     }
@@ -446,35 +416,23 @@ nsAttrValue::SetTo(double aValue, const 
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   cont->mDoubleValue = aValue;
   cont->mType = eDoubleValue;
   SetMiscAtomOrString(aSerialized);
 }
 
 void
-nsAttrValue::SetTo(css::Declaration* aValue, const nsAString* aSerialized)
-{
-  MiscContainer* cont = EnsureEmptyMiscContainer();
-  MOZ_ASSERT(cont->mValue.mRefCount == 0);
-  NS_ADDREF(cont->mValue.mGeckoCSSDeclaration = aValue);
-  cont->mType = eGeckoCSSDeclaration;
-  NS_ADDREF(cont);
-  SetMiscAtomOrString(aSerialized);
-  MOZ_ASSERT(cont->mValue.mRefCount == 1);
-}
-
-void
-nsAttrValue::SetTo(already_AddRefed<ServoDeclarationBlock> aValue,
+nsAttrValue::SetTo(already_AddRefed<DeclarationBlock> aValue,
                    const nsAString* aSerialized)
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   MOZ_ASSERT(cont->mValue.mRefCount == 0);
-  cont->mValue.mServoCSSDeclaration = aValue.take();
-  cont->mType = eServoCSSDeclaration;
+  cont->mValue.mCSSDeclaration = aValue.take();
+  cont->mType = eCSSDeclaration;
   NS_ADDREF(cont);
   SetMiscAtomOrString(aSerialized);
   MOZ_ASSERT(cont->mValue.mRefCount == 1);
 }
 
 void
 nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized)
 {
@@ -677,27 +635,25 @@ nsAttrValue::ToString(nsAString& aResult
     case ePercent:
     {
       nsAutoString intStr;
       intStr.AppendInt(cont ? cont->mValue.mPercent : GetIntInternal());
       aResult = intStr + NS_LITERAL_STRING("%");
 
       break;
     }
-    case eGeckoCSSDeclaration:
+    case eCSSDeclaration:
     {
-      // XXXheycam Once we support CSSOM access to them, we should
-      // probably serialize eServoCSSDeclarations like this too.
-      // For now, we will return the string from the MiscContainer
-      // at the top of this function.
       aResult.Truncate();
       MiscContainer *container = GetMiscContainer();
-      css::Declaration *decl = container->mValue.mGeckoCSSDeclaration;
-      if (decl) {
-        decl->ToString(aResult);
+      DeclarationBlock* decl = container->mValue.mCSSDeclaration;
+      // XXXheycam Once we support CSSOM access to them, we should
+      // probably serialize ServoDeclarationBlock like this too.
+      if (decl && decl->IsGecko()) {
+        decl->AsGecko()->ToString(aResult);
       }
       const_cast<nsAttrValue*>(this)->SetMiscAtomOrString(&aResult);
 
       break;
     }
     case eDoubleValue:
     {
       aResult.Truncate();
@@ -930,23 +886,19 @@ nsAttrValue::HashValue() const
     case ePercent:
     {
       return cont->mValue.mPercent;
     }
     case eColor:
     {
       return cont->mValue.mColor;
     }
-    case eGeckoCSSDeclaration:
+    case eCSSDeclaration:
     {
-      return NS_PTR_TO_INT32(cont->mValue.mGeckoCSSDeclaration);
-    }
-    case eServoCSSDeclaration:
-    {
-      return NS_PTR_TO_INT32(cont->mValue.mServoCSSDeclaration);
+      return NS_PTR_TO_INT32(cont->mValue.mCSSDeclaration);
     }
     // Intentionally identical, so that loading the image does not change the
     // hash code.
     case eURL:
     case eImage:
     {
       nsString str;
       ToString(str);
@@ -1043,20 +995,20 @@ nsAttrValue::Equals(const nsAttrValue& a
     }
     case eColor:
     {
       if (thisCont->mValue.mColor == otherCont->mValue.mColor) {
         needsStringComparison = true;
       }
       break;
     }
-    case eGeckoCSSDeclaration:
+    case eCSSDeclaration:
     {
-      return thisCont->mValue.mGeckoCSSDeclaration ==
-               otherCont->mValue.mGeckoCSSDeclaration;
+      return thisCont->mValue.mCSSDeclaration ==
+               otherCont->mValue.mCSSDeclaration;
     }
     case eURL:
     {
       return thisCont->mValue.mURL == otherCont->mValue.mURL;
     }
     case eImage:
     {
       return thisCont->mValue.mImage == otherCont->mValue.mImage;
@@ -1076,21 +1028,16 @@ nsAttrValue::Equals(const nsAttrValue& a
     case eDoubleValue:
     {
       return thisCont->mDoubleValue == otherCont->mDoubleValue;
     }
     case eIntMarginValue:
     {
       return thisCont->mValue.mIntMargin == otherCont->mValue.mIntMargin;
     }
-    case eServoCSSDeclaration:
-    {
-      return thisCont->mValue.mServoCSSDeclaration ==
-               otherCont->mValue.mServoCSSDeclaration;
-    }
     default:
     {
       if (IsSVGType(thisCont->mType)) {
         // Currently this method is never called for nsAttrValue objects that
         // point to SVG data types.
         // If that changes then we probably want to add methods to the
         // corresponding SVG types to compare their base values.
         // As a shortcut, however, we can begin by comparing the pointers.
@@ -1766,36 +1713,30 @@ nsAttrValue::ParseStyleAttribute(const n
     if (cont) {
       // Set our MiscContainer to the cached one.
       NS_ADDREF(cont);
       SetPtrValueAndType(cont, eOtherBase);
       return true;
     }
   }
 
+  RefPtr<DeclarationBlock> decl;
   if (ownerDoc->GetStyleBackendType() == StyleBackendType::Servo) {
-    NS_ConvertUTF16toUTF8 value(aString);
-    RefPtr<ServoDeclarationBlock> decl = Servo_ParseStyleAttribute(
-        reinterpret_cast<const uint8_t*>(value.get()),
-        value.Length(), sheet).Consume();
-    MOZ_ASSERT(decl);
-    SetTo(decl.forget(), &aString);
+    decl = ServoDeclarationBlock::FromStyleAttribute(aString);
   } else {
     css::Loader* cssLoader = ownerDoc->CSSLoader();
     nsCSSParser cssParser(cssLoader);
-
-    RefPtr<css::Declaration> declaration =
-      cssParser.ParseStyleAttribute(aString, docURI, baseURI,
-                                    aElement->NodePrincipal());
-    if (!declaration) {
-      return false;
-    }
-    declaration->SetHTMLCSSStyleSheet(sheet);
-    SetTo(declaration, &aString);
+    decl = cssParser.ParseStyleAttribute(aString, docURI, baseURI,
+                                         aElement->NodePrincipal());
   }
+  if (!decl) {
+    return false;
+  }
+  decl->SetHTMLCSSStyleSheet(sheet);
+  SetTo(decl.forget(), &aString);
 
   if (cachingAllowed) {
     MiscContainer* cont = GetMiscContainer();
     cont->Cache();
   }
 
   return true;
 }
@@ -1803,25 +1744,24 @@ nsAttrValue::ParseStyleAttribute(const n
 void
 nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
 {
   NS_ASSERTION(GetMiscContainer(), "Must have MiscContainer!");
   NS_ASSERTION(!GetMiscContainer()->mStringBits,
                "Trying to re-set atom or string!");
   if (aValue) {
     uint32_t len = aValue->Length();
-    // * We're allowing eGeckoCSSDeclaration and eServoCSSDeclaration
-    //   attributes to store empty strings as it can be beneficial to store
-    //   an empty style attribute as a parsed rule.
+    // * We're allowing eCSSDeclaration attributes to store empty
+    //   strings as it can be beneficial to store an empty style
+    //   attribute as a parsed rule.
     // * We're allowing enumerated values because sometimes the empty
     //   string corresponds to a particular enumerated value, especially
     //   for enumerated values that are not limited enumerated.
     // Add other types as needed.
-    NS_ASSERTION(len || Type() == eGeckoCSSDeclaration ||
-                 Type() == eServoCSSDeclaration || Type() == eEnum,
+    NS_ASSERTION(len || Type() == eCSSDeclaration || Type() == eEnum,
                  "Empty string?");
     MiscContainer* cont = GetMiscContainer();
     if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
       nsCOMPtr<nsIAtom> atom = NS_Atomize(*aValue);
       if (atom) {
         cont->mStringBits =
           reinterpret_cast<uintptr_t>(atom.forget().take()) | eAtomBase;
       }
@@ -1875,27 +1815,22 @@ nsAttrValue::ClearMiscContainer()
       // This MiscContainer is shared, we need a new one.
       NS_RELEASE(cont);
 
       cont = new MiscContainer;
       SetPtrValueAndType(cont, eOtherBase);
     }
     else {
       switch (cont->mType) {
-        case eGeckoCSSDeclaration:
-        case eServoCSSDeclaration:
+        case eCSSDeclaration:
         {
           MOZ_ASSERT(cont->mValue.mRefCount == 1);
           cont->Release();
           cont->Evict();
-          if (cont->mType == eGeckoCSSDeclaration) {
-            NS_RELEASE(cont->mValue.mGeckoCSSDeclaration);
-          } else {
-            Servo_DeclarationBlock_Release(cont->mValue.mServoCSSDeclaration);
-          }
+          NS_RELEASE(cont->mValue.mCSSDeclaration);
           break;
         }
         case eURL:
         {
           NS_RELEASE(cont->mValue.mURL);
           break;
         }
         case eImage:
@@ -2015,26 +1950,22 @@ nsAttrValue::SizeOfExcludingThis(MallocS
       // We only count the size of the object pointed by otherPtr if it's a
       // string. When it's an atom, it's counted separatly.
       if (otherPtr &&
           static_cast<ValueBaseType>(container->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == eStringBase) {
         nsStringBuffer* str = static_cast<nsStringBuffer*>(otherPtr);
         n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0;
       }
 
-      if (Type() == eGeckoCSSDeclaration &&
-          container->mValue.mGeckoCSSDeclaration) {
-        // TODO: mGeckoCSSDeclaration might be owned by another object which
+      if (Type() == eCSSDeclaration && container->mValue.mCSSDeclaration) {
+        // TODO: mCSSDeclaration might be owned by another object which
         //       would make us count them twice, bug 677493.
-        //n += container->mGeckoCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf);
-      } else if (Type() == eServoCSSDeclaration &&
-                 container->mValue.mServoCSSDeclaration) {
-        // Bug 1281964: As with eGeckoCSSDeclaration, but if we do measure we'll
-        // need a way to call the Servo heap_size_of function for the
-        // declaration block.
+        // Bug 1281964: For ServoDeclarationBlock if we do measure we'll
+        // need a way to call the Servo heap_size_of function.
+        //n += container->mCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf);
       } else if (Type() == eAtomArray && container->mValue.mAtomArray) {
         // Don't measure each nsIAtom, they are measured separatly.
         n += container->mValue.mAtomArray->ShallowSizeOfIncludingThis(aMallocSizeOf);
       }
       break;
     }
     case eAtomBase:    // Atoms are counted separately.
     case eIntegerBase: // The value is in mBits, nothing to do.
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -30,21 +30,20 @@
 
 // Undefine LoadImage to prevent naming conflict with Windows.
 #undef LoadImage
 
 class nsAString;
 class nsIDocument;
 class nsStyledElement;
 struct MiscContainer;
-struct ServoDeclarationBlock;
 
 namespace mozilla {
+class DeclarationBlock;
 namespace css {
-class Declaration;
 struct URLValue;
 struct ImageValue;
 } // namespace css
 } // namespace mozilla
 
 #define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
 
 #define NS_ATTRVALUE_BASETYPE_MASK (uintptr_t(3))
@@ -93,18 +92,17 @@ public:
                           //   01  this value indicates a 'misc' struct
     eAtom =         0x02, //   10
     eInteger =      0x03, // 0011
     eColor =        0x07, // 0111
     eEnum =         0x0B, // 1011  This should eventually die
     ePercent =      0x0F, // 1111
     // Values below here won't matter, they'll be always stored in the 'misc'
     // struct.
-    eGeckoCSSDeclaration = 0x10,
-    eServoCSSDeclaration,
+    eCSSDeclaration = 0x10,
     eURL,
     eImage,
     eAtomArray,
     eDoubleValue,
     eIntMarginValue,
     eSVGAngle,
     eSVGTypesBegin = eSVGAngle,
     eSVGIntegerPair,
@@ -120,17 +118,18 @@ public:
     eSVGViewBox,
     eSVGTypesEnd = eSVGViewBox,
   };
 
   nsAttrValue();
   nsAttrValue(const nsAttrValue& aOther);
   explicit nsAttrValue(const nsAString& aValue);
   explicit nsAttrValue(nsIAtom* aValue);
-  nsAttrValue(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
+  nsAttrValue(already_AddRefed<mozilla::DeclarationBlock> aValue,
+              const nsAString* aSerialized);
   explicit nsAttrValue(const nsIntMargin& aValue);
   ~nsAttrValue();
 
   inline const nsAttrValue& operator=(const nsAttrValue& aOther);
 
   static nsresult Init();
   static void Shutdown();
 
@@ -145,18 +144,17 @@ public:
   void Reset();
 
   void SetTo(const nsAttrValue& aOther);
   void SetTo(const nsAString& aValue);
   void SetTo(nsIAtom* aValue);
   void SetTo(int16_t aInt);
   void SetTo(int32_t aInt, const nsAString* aSerialized);
   void SetTo(double aValue, const nsAString* aSerialized);
-  void SetTo(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
-  void SetTo(already_AddRefed<ServoDeclarationBlock> aDeclarationBlock,
+  void SetTo(already_AddRefed<mozilla::DeclarationBlock> aValue,
              const nsAString* aSerialized);
   void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized);
   void SetTo(const nsIntMargin& aValue);
   void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
   void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized);
   void SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized);
   void SetTo(const mozilla::SVGLengthList& aValue,
              const nsAString* aSerialized);
@@ -198,18 +196,17 @@ public:
   inline bool IsEmptyString() const;
   const nsCheapString GetStringValue() const;
   inline nsIAtom* GetAtomValue() const;
   inline int32_t GetIntegerValue() const;
   bool GetColorValue(nscolor& aColor) const;
   inline int16_t GetEnumValue() const;
   inline float GetPercentValue() const;
   inline AtomArray* GetAtomArrayValue() const;
-  inline mozilla::css::Declaration* GetGeckoCSSDeclarationValue() const;
-  inline ServoDeclarationBlock* GetServoCSSDeclarationValue() const;
+  inline mozilla::DeclarationBlock* GetCSSDeclarationValue() const;
   inline mozilla::css::URLValue* GetURLValue() const;
   inline mozilla::css::ImageValue* GetImageValue() const;
   inline double GetDoubleValue() const;
   bool GetIntMarginValue(nsIntMargin& aMargin) const;
 
   /**
    * Returns the string corresponding to the stored enum value.
    *
--- a/dom/base/nsAttrValueInlines.h
+++ b/dom/base/nsAttrValueInlines.h
@@ -15,29 +15,28 @@
 struct MiscContainer;
 
 struct MiscContainer final
 {
   typedef nsAttrValue::ValueType ValueType;
 
   ValueType mType;
   // mStringBits points to either nsIAtom* or nsStringBuffer* and is used when
-  // mType isn't eGeckoCSSDeclaration.
+  // mType isn't eCSSDeclaration.
   // Note eStringBase and eAtomBase is used also to handle the type of
   // mStringBits.
   uintptr_t mStringBits;
   union {
     struct {
       union {
         int32_t mInteger;
         nscolor mColor;
         uint32_t mEnumValue;
         int32_t mPercent;
-        mozilla::css::Declaration* mGeckoCSSDeclaration;
-        ServoDeclarationBlock* mServoCSSDeclaration;
+        mozilla::DeclarationBlock* mCSSDeclaration;
         mozilla::css::URLValue* mURL;
         mozilla::css::ImageValue* mImage;
         nsAttrValue::AtomArray* mAtomArray;
         nsIntMargin* mIntMargin;
         const nsSVGAngle* mSVGAngle;
         const nsSVGIntegerPair* mSVGIntegerPair;
         const nsSVGLength2* mSVGLength;
         const mozilla::SVGLengthList* mSVGLengthList;
@@ -82,18 +81,17 @@ protected:
 public:
   bool GetString(nsAString& aString) const;
 
   inline bool IsRefCounted() const
   {
     // Nothing stops us from refcounting (and sharing) other types of
     // MiscContainer (except eDoubleValue types) but there's no compelling
     // reason to.
-    return mType == nsAttrValue::eGeckoCSSDeclaration ||
-           mType == nsAttrValue::eServoCSSDeclaration;
+    return mType == nsAttrValue::eCSSDeclaration;
   }
 
   inline int32_t AddRef() {
     MOZ_ASSERT(IsRefCounted());
     return ++mValue.mRefCount;
   }
 
   inline int32_t Release() {
@@ -143,28 +141,21 @@ nsAttrValue::GetPercentValue() const
 
 inline nsAttrValue::AtomArray*
 nsAttrValue::GetAtomArrayValue() const
 {
   NS_PRECONDITION(Type() == eAtomArray, "wrong type");
   return GetMiscContainer()->mValue.mAtomArray;
 }
 
-inline mozilla::css::Declaration*
-nsAttrValue::GetGeckoCSSDeclarationValue() const
+inline mozilla::DeclarationBlock*
+nsAttrValue::GetCSSDeclarationValue() const
 {
-  NS_PRECONDITION(Type() == eGeckoCSSDeclaration, "wrong type");
-  return GetMiscContainer()->mValue.mGeckoCSSDeclaration;
-}
-
-inline ServoDeclarationBlock*
-nsAttrValue::GetServoCSSDeclarationValue() const
-{
-  NS_PRECONDITION(Type() == eServoCSSDeclaration, "wrong type");
-  return GetMiscContainer()->mValue.mServoCSSDeclaration;
+  NS_PRECONDITION(Type() == eCSSDeclaration, "wrong type");
+  return GetMiscContainer()->mValue.mCSSDeclaration;
 }
 
 inline mozilla::css::URLValue*
 nsAttrValue::GetURLValue() const
 {
   NS_PRECONDITION(Type() == eURL, "wrong type");
   return GetMiscContainer()->mValue.mURL;
 }
@@ -202,19 +193,17 @@ nsAttrValue::IsSVGType(ValueType aType) 
 
 inline bool
 nsAttrValue::StoresOwnData() const
 {
   if (BaseType() != eOtherBase) {
     return true;
   }
   ValueType t = Type();
-  return t != eGeckoCSSDeclaration &&
-         t != eServoCSSDeclaration &&
-         !IsSVGType(t);
+  return t != eCSSDeclaration && !IsSVGType(t);
 }
 
 inline void
 nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType)
 {
   NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK),
                "pointer not properly aligned, this will crash");
   mBits = reinterpret_cast<intptr_t>(aValue) | aType;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -198,17 +198,16 @@
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsSandboxFlags.h"
 #include "nsIAddonPolicyService.h"
-#include "nsIAppsService.h"
 #include "mozilla/dom/AnimatableBinding.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentTimeline.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
@@ -2539,112 +2538,53 @@ nsDocument::InitCSP(nsIChannel* aChannel
 
     httpChannel->GetResponseHeader(
         NS_LITERAL_CSTRING("content-security-policy-report-only"),
         tCspROHeaderValue);
   }
   NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
   NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
 
-  // Figure out if we need to apply an app default CSP or a CSP from an app manifest
-  nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
-
-  uint16_t appStatus = principal->GetAppStatus();
-  bool applyAppDefaultCSP = false;
-  bool applyAppManifestCSP = false;
-
-  nsAutoString appManifestCSP;
-  nsAutoString appDefaultCSP;
-  if (appStatus != nsIPrincipal::APP_STATUS_NOT_INSTALLED) {
-    nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
-    if (appsService) {
-      uint32_t appId = principal->GetAppId();
-      appsService->GetManifestCSPByLocalId(appId, appManifestCSP);
-      if (!appManifestCSP.IsEmpty()) {
-        applyAppManifestCSP = true;
-      }
-      appsService->GetDefaultCSPByLocalId(appId, appDefaultCSP);
-      if (!appDefaultCSP.IsEmpty()) {
-        applyAppDefaultCSP = true;
-      }
-    }
-  }
-
   // Check if this is a document from a WebExtension.
   nsString addonId;
+  nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
   principal->GetAddonId(addonId);
   bool applyAddonCSP = !addonId.IsEmpty();
 
   // Check if this is a signed content to apply default CSP.
   bool applySignedContentCSP = false;
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   if (loadInfo && loadInfo->GetVerifySignedContent()) {
     applySignedContentCSP = true;
   }
 
   // If there's no CSP to apply, go ahead and return early
-  if (!applyAppDefaultCSP &&
-      !applyAppManifestCSP &&
-      !applyAddonCSP &&
+  if (!applyAddonCSP &&
       !applySignedContentCSP &&
       cspHeaderValue.IsEmpty() &&
       cspROHeaderValue.IsEmpty()) {
     if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
       nsCOMPtr<nsIURI> chanURI;
       aChannel->GetURI(getter_AddRefs(chanURI));
       nsAutoCString aspec;
       chanURI->GetAsciiSpec(aspec);
       MOZ_LOG(gCspPRLog, LogLevel::Debug,
-             ("no CSP for document, %s, %s",
-              aspec.get(),
-              applyAppDefaultCSP ? "is app" : "not an app"));
+             ("no CSP for document, %s",
+              aspec.get()));
     }
 
     return NS_OK;
   }
 
-  MOZ_LOG(gCspPRLog, LogLevel::Debug, ("Document is an app or CSP header specified %p", this));
-
-  // If Document is an app check to see if we already set CSP and return early
-  // if that is indeed the case.
-  //
-  // In general (see bug 947831), we should not be setting CSP on a principal
-  // that aliases another document. For non-app code this is not a problem
-  // since we only share the underlying principal with nested browsing
-  // contexts for which a header cannot be set (e.g., about:blank and
-  // about:srcodoc iframes) and thus won't try to set the CSP again. This
-  // check ensures that we do not try to set CSP for an app.
-  if (applyAppDefaultCSP || applyAppManifestCSP) {
-    nsCOMPtr<nsIContentSecurityPolicy> csp;
-    rv = principal->GetCsp(getter_AddRefs(csp));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (csp) {
-      MOZ_LOG(gCspPRLog, LogLevel::Debug, ("%s %s %s",
-           "This document is sharing principal with another document.",
-           "Since the document is an app, CSP was already set.",
-           "Skipping attempt to set CSP."));
-      return NS_OK;
-    }
-  }
+  MOZ_LOG(gCspPRLog, LogLevel::Debug, ("Document is an add-on or CSP header specified %p", this));
 
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = principal->EnsureCSP(this, getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // ----- if the doc is an app and we want a default CSP, apply it.
-  if (applyAppDefaultCSP) {
-    csp->AppendPolicy(appDefaultCSP, false, false);
-  }
-
-  // ----- if the doc is an app and specifies a CSP in its manifest, apply it.
-  if (applyAppManifestCSP) {
-    csp->AppendPolicy(appManifestCSP, false, false);
-  }
-
   // ----- if the doc is an addon, apply its CSP.
   if (applyAddonCSP) {
     nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
 
     nsAutoString addonCSP;
     rv = aps->GetBaseCSP(addonCSP);
     if (NS_SUCCEEDED(rv)) {
       csp->AppendPolicy(addonCSP, false, false);
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -10,16 +10,17 @@
  */
 
 #include "base/basictypes.h"
 
 #include "prenv.h"
 
 #include "mozIApplication.h"
 #include "nsDocShell.h"
+#include "nsIAppsService.h"
 #include "nsIDOMHTMLIFrameElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMMozBrowserFrame.h"
 #include "nsIDOMWindow.h"
 #include "nsIPresShell.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -242,17 +242,17 @@ public:
    * the term, i.e. not in an XHTML/XML document).
    */
   inline bool IsInHTMLDocument() const;
 
 
   /**
    * Returns true if in a chrome document
    */
-  virtual bool IsInChromeDocument();
+  virtual bool IsInChromeDocument() const;
 
   /**
    * Get the namespace that this element's tag is defined in
    * @return the namespace
    */
   inline int32_t GetNameSpaceID() const
   {
     return mNodeInfo->NamespaceID();
--- a/dom/base/nsIContentInlines.h
+++ b/dom/base/nsIContentInlines.h
@@ -14,17 +14,17 @@
 
 inline bool
 nsIContent::IsInHTMLDocument() const
 {
   return OwnerDoc()->IsHTMLDocument();
 }
 
 inline bool
-nsIContent::IsInChromeDocument()
+nsIContent::IsInChromeDocument() const
 {
   return nsContentUtils::IsChromeDoc(OwnerDoc());
 }
 
 inline mozilla::dom::ShadowRoot* nsIContent::GetShadowRoot() const
 {
   if (!IsElement()) {
     return nullptr;
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -1448,25 +1448,17 @@ nsObjectLoadingContent::ObjectState() co
         case eFallbackClickToPlay:
           return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
         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.
-          char* pluginsBlocked = PR_GetEnv("MOZ_PLUGINS_BLOCKED");
-          if (pluginsBlocked && pluginsBlocked[0] == '1') {
-            return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM;
-          } else {
-            return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_TYPE_UNSUPPORTED;
-          }
-        }
+        case eFallbackUnsupported:
         case eFallbackOutdated:
         case eFallbackAlternate:
           return NS_EVENT_STATE_BROKEN;
         case eFallbackVulnerableUpdatable:
           return NS_EVENT_STATE_VULNERABLE_UPDATABLE;
         case eFallbackVulnerableNoUpdate:
           return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
       }
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -9,17 +9,17 @@
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsDOMCSSAttrDeclaration.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDocument.h"
-#include "mozilla/css/Declaration.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsXULElement.h"
 #include "nsContentUtils.h"
 #include "nsStyleUtil.h"
 
 using namespace mozilla;
@@ -44,17 +44,17 @@ nsStyledElement::ParseAttribute(int32_t 
     return true;
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
 
 nsresult
-nsStyledElement::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                            const nsAString* aSerialized,
                                            bool aNotify)
 {
   SetMayHaveStyle();
   bool modification = false;
   nsAttrValue oldValue;
 
   bool hasListeners = aNotify &&
@@ -76,38 +76,38 @@ nsStyledElement::SetInlineStyleDeclarati
     if (modification) {
       oldValue.SetTo(oldValueStr);
     }
   }
   else if (aNotify && IsInUncomposedDoc()) {
     modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   }
 
-  nsAttrValue attrValue(aDeclaration, aSerialized);
+  nsAttrValue attrValue(do_AddRef(aDeclaration), aSerialized);
 
   // XXXbz do we ever end up with ADDITION here?  I doubt it.
   uint8_t modType = modification ?
     static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) :
     static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
 
   return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr,
                           oldValue, attrValue, modType, hasListeners,
                           aNotify, kDontCallAfterSetAttr);
 }
 
-css::Declaration*
+DeclarationBlock*
 nsStyledElement::GetInlineStyleDeclaration()
 {
   if (!MayHaveStyle()) {
     return nullptr;
   }
   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
 
-  if (attrVal && attrVal->Type() == nsAttrValue::eGeckoCSSDeclaration) {
-    return attrVal->GetGeckoCSSDeclarationValue();
+  if (attrVal && attrVal->Type() == nsAttrValue::eCSSDeclaration) {
+    return attrVal->GetCSSDeclarationValue();
   }
 
   return nullptr;
 }
 
 // ---------------------------------------------------------------
 // Others and helpers
 
@@ -129,23 +129,17 @@ nsStyledElement::Style()
 
 nsresult
 nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc)
 {
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
-  
-  nsAttrValue::ValueType desiredType =
-    OwnerDoc()->GetStyleBackendType() == StyleBackendType::Gecko ?
-      nsAttrValue::eGeckoCSSDeclaration :
-      nsAttrValue::eServoCSSDeclaration;
-
-  if (oldVal && oldVal->Type() != desiredType) {
+  if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) {
     nsAttrValue attrValue;
     nsAutoString stringValue;
     oldVal->ToString(stringValue);
     ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
     // Don't bother going through SetInlineStyleDeclaration; we don't
     // want to fire off mutation events or document notifications anyway
     nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/base/nsStyledElement.h
+++ b/dom/base/nsStyledElement.h
@@ -13,19 +13,17 @@
 #ifndef __NS_STYLEDELEMENT_H_
 #define __NS_STYLEDELEMENT_H_
 
 #include "mozilla/Attributes.h"
 #include "nsString.h"
 #include "mozilla/dom/Element.h"
 
 namespace mozilla {
-namespace css {
-class Declaration;
-} // namespace css
+class DeclarationBlock;
 } // namespace mozilla
 
 // IID for nsStyledElement interface
 #define NS_STYLED_ELEMENT_IID \
 { 0xacbd9ea6, 0x15aa, 0x4f37, \
  { 0x8c, 0xe0, 0x35, 0x1e, 0xd7, 0x21, 0xca, 0xe9 } }
 
 typedef mozilla::dom::Element nsStyledElementBase;
@@ -41,18 +39,18 @@ protected:
 
 public:
   // We don't want to implement AddRef/Release because that would add an extra
   // function call for those on pretty much all elements.  But we do need QI, so
   // we can QI to nsStyledElement.
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
   // Element interface methods
-  virtual mozilla::css::Declaration* GetInlineStyleDeclaration() override;
-  virtual nsresult SetInlineStyleDeclaration(mozilla::css::Declaration* aDeclaration,
+  virtual mozilla::DeclarationBlock* GetInlineStyleDeclaration() override;
+  virtual nsresult SetInlineStyleDeclaration(mozilla::DeclarationBlock* aDeclaration,
                                              const nsAString* aSerialized,
                                              bool aNotify) override;
 
   nsICSSDeclaration* Style();
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_STYLED_ELEMENT_IID)
 
 protected:
--- a/dom/base/test/chrome/chrome.ini
+++ b/dom/base/test/chrome/chrome.ini
@@ -1,18 +1,16 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g' || os == 'android'
 support-files =
   blockNoPlugins.xml
   blockPluginHard.xml
   bug418986-1.js
   cpows_child.js
   cpows_parent.xul
-  file_bug391728.html
-  file_bug391728_2.html
   file_bug549682.xul
   file_bug616841.xul
   file_bug816340.xul
   file_bug990812-1.xul
   file_bug990812-2.xul
   file_bug990812-3.xul
   file_bug990812-4.xul
   file_bug990812-5.xul
@@ -31,17 +29,16 @@ support-files =
 [test_bug206691.xul]
 [test_bug289714.xul]
 [test_bug339494.xul]
 [test_bug357450.xul]
 support-files = ../file_bug357450.js
 [test_bug380418.html]
 [test_bug380418.html^headers^]
 [test_bug383430.html]
-[test_bug391728.html]
 [test_bug418986-1.xul]
 [test_bug421622.xul]
 [test_bug429785.xul]
 [test_bug430050.xul]
 [test_bug467123.xul]
 [test_bug549682.xul]
 [test_bug571390.xul]
 [test_bug1098074_throw_from_ReceiveMessage.xul]
deleted file mode 100644
--- a/dom/base/test/chrome/file_bug391728.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<html>
-<head>
-<style type="text/css">
-embed,object {
-  border: 1px solid black;
-}
-
-embed:-moz-handler-disabled,
-object:-moz-handler-disabled {
-  border-style: dotted !important;
-}
-
-embed:-moz-handler-blocked,
-object:-moz-handler-blocked {
-  border-style: dashed !important;
-}
-
-embed:-moz-type-unsupported,
-object:-moz-type-unsupported {
-  border-style: none !important;
-}
-</style>
-<script type="text/javascript">
-function plugin_binding_attached(event) {
-  window.parent.plugin_binding_attached(event);
-}
-document.addEventListener("PluginBindingAttached", plugin_binding_attached, true, true);
-</script>
-</head>
-<body>
-<!-- Embeds always fire events and have the pseudo class attached -->
-<div><embed id="plugin1" style="width: 100px; height: 100px" type="application/x-test"></div>
-<div><embed id="plugin2" style="width: 100px; height: 100px" src="data:application/x-test,test"></div>
-
-<!-- So do objects with a type/uri and no content -->
-<div><object id="plugin3" style="width: 100px; height: 100px" type="application/x-test"></object></div>
-<div><object id="plugin4" style="width: 100px; height: 100px" data="data:application/x-test,test"></object></div>
-
-<!-- Params are not considered content -->
-<div><object id="plugin5" style="width: 100px; height: 100px" type="application/x-test">
-  <param name="foo" value="bar">
-</object></div>
-<div><object id="plugin6" style="width: 100px; height: 100px" data="data:application/x-test,test">
-  <param name="foo" value="bar">
-</object></div>
-
-<!-- Nor is whitespace -->
-<div><object id="plugin7" style="width: 100px; height: 100px" type="application/x-test">
-
-  
-</object></div>
-<div><object id="plugin8" style="width: 100px; height: 100px" data="data:application/x-test,test">
-
-  
-</object></div>
-
-<!-- No errors or psuedo classes for objects with fallback content -->
-<div><object id="fallback1" style="width: 100px; height: 100px" type="application/x-test">
-  <p>Fallback content</p>
-</object></div>
-<div><object id="fallback2" style="width: 100px; height: 100px" data="data:application/x-test,test">
-  <p>Fallback content</p>
-</object></div>
-
-<!-- Even other plugins are considered content so no errors dispatched from these
-     objects, but the inner embeds do get processed -->
-<div><object id="fallback3" style="width: 100px; height: 100px" type="application/x-test">
-  <embed id="plugin9" style="width: 100px; height: 100px" type="application/x-test">
-</object></div>
-<div><object id="fallback4" style="width: 100px; height: 100px" data="data:application/x-test,test">
-  <embed id="plugin10" style="width: 100px; height: 100px" type="application/x-test">
-</object></div>
-
-<!-- pluginurl was removed in bug 548133, and should not affect fallback -->
-<div><object id="plugin11" style="width: 100px; height: 100px" data="data:application/x-test,test">
-    <param name="pluginurl">
-</object></div>
-
-<div><object id="fallback5" style="width: 100px; height: 100px" data="data:application/x-test,test">
-    <param name="pluginurl">
-    Fallback content
-</object></div>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/base/test/chrome/file_bug391728_2.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<html>
-<head>
-<style type="text/css">
-embed,object {
-  border: 1px solid black;
-}
-
-embed:-moz-handler-disabled,
-object:-moz-handler-disabled {
-  border-style: dotted !important;
-}
-
-embed:-moz-handler-blocked,
-object:-moz-handler-blocked {
-  border-style: dashed !important;
-}
-
-embed:-moz-type-unsupported,
-object:-moz-type-unsupported {
-  border-style: none !important;
-}
-</style>
-<script type="text/javascript">
-function plugin_binding_attached(event) {
-  window.parent.plugin_binding_attached(event);
-}
-document.addEventListener("PluginBindingAttached", plugin_binding_attached, true, true);
-</script>
-</head>
-<body>
-<!-- Embeds always fire events and have the pseudo class attached -->
-<div><embed id="plugin1" style="width: 100px; height: 100px" type="application/x-unknown"></div>
-<div><embed id="plugin2" style="width: 100px; height: 100px" src="data:application/x-unknown,test"></div>
-
-<!-- So do objects with a type/uri and no content -->
-<div><object id="plugin3" style="width: 100px; height: 100px" type="application/x-unknown"></object></div>
-<div><object id="plugin4" style="width: 100px; height: 100px" data="data:application/x-unknown,test"></object></div>
-
-<!-- Params are not considered content -->
-<div><object id="plugin5" style="width: 100px; height: 100px" type="application/x-unknown">
-  <param name="foo" value="bar">
-</object></div>
-<div><object id="plugin6" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
-  <param name="foo" value="bar">
-</object></div>
-
-<!-- Nor is whitespace -->
-<div><object id="plugin7" style="width: 100px; height: 100px" type="application/x-unknown">
-
-  
-</object></div>
-<div><object id="plugin8" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
-
-  
-</object></div>
-
-<!-- No errors or psuedo classes for objects with fallback content -->
-<div><object id="fallback1" style="width: 100px; height: 100px" type="application/x-unknown">
-  <p>Fallback content</p>
-</object></div>
-<div><object id="fallback2" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
-  <p>Fallback content</p>
-</object></div>
-
-<!-- Even other plugins are considered content so no errors dispatched from these
-     objects, but the inner embeds do get processed -->
-<div><object id="fallback3" style="width: 100px; height: 100px" type="application/x-unknown">
-  <embed id="plugin9" style="width: 100px; height: 100px" type="application/x-unknown">
-</object></div>
-<div><object id="fallback4" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
-  <embed id="plugin10" style="width: 100px; height: 100px" type="application/x-unknown">
-</object></div>
-
-<!-- pluginurl was removed in bug 548133, and should not affect fallback -->
-<div><object id="plugin11" style="width: 100px; height: 100px" type="application/x-unknown">
-    <param name="pluginurl">
-</object></div>
-
-<div><object id="fallback5" style="width: 100px; height: 100px" type="applicatin/x-unknown">
-    <param name="pluginurl">
-    Fallback content
-</object></div>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/base/test/chrome/test_bug391728.html
+++ /dev/null
@@ -1,201 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=391728
--->
-<head>
-  <title>Test for Bug 391728</title>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=391728">Mozilla Bug 391728</a>
-<p id="display"></p>
-<div id="content">
-  <iframe id="testframe" width="150" height="250" src="about:blank"></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-const gHttpTestRoot = location.toString().replace("chrome://mochitests/content/", "http://127.0.0.1:8888/").split(/\//).slice(0, -1).join('/') + '/';
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-/** Test for Bug 391728 **/
-// Plugins that should dispatch error events and have the pseudo classes set
-const PLUGIN_COUNT = 11;
-// Plugins that should neither dispatch error events or have the pseudo classes set
-const FALLBACK_COUNT = 5;
-const OBJLC = Components.interfaces.nsIObjectLoadingContent;
-
-var gNextTest = null;
-var gUnknown = [];
-var gBlocked = [];
-var gDisabled = [];
-
-function plugin_binding_attached(event) {
-  var plugin = event.target;
-  plugin instanceof OBJLC;
-  switch (SpecialPowers.wrap(plugin).pluginFallbackType) {
-    case OBJLC.PLUGIN_DISABLED:
-      gDisabled.push(plugin.id);
-      break;
-    case OBJLC.PLUGIN_BLOCKLISTED:
-      gBlocked.push(plugin.id);
-      break;
-    case OBJLC.PLUGIN_UNSUPPORTED:
-      gUnknown.push(plugin.id);
-      break;
-  }
-}
-
-function init_test() {
-  if (!PluginUtils.withTestPlugin(start_test))
-    SimpleTest.finish();
-}
-
-function updateBlocklist(aCallback) {
-  var blocklistNotifier = Components.classes["@mozilla.org/extensions/blocklist;1"]
-                          .getService(Components.interfaces.nsITimerCallback);
-  var observer = function() {
-    Services.obs.removeObserver(observer, "blocklist-updated");
-    SimpleTest.executeSoon(aCallback);
-  };
-  Services.obs.addObserver(observer, "blocklist-updated", false);
-  blocklistNotifier.notify(null);
-}
-
-var _originalBlocklistURL = null;
-function setAndUpdateBlocklist(aURL, aCallback) {
-  info("Setting blocklist to " + aURL);
-  if (!_originalBlocklistURL) {
-    _originalBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
-  }
-  Services.prefs.setCharPref("extensions.blocklist.url", aURL);
-  updateBlocklist(aCallback);
-}
-
-function resetBlocklist() {
-  info("resetting blocklist URL to " + _originalBlocklistURL);
-  Services.prefs.setCharPref("extensions.blocklist.url", _originalBlocklistURL);
-}
-
-function start_test(plugin) {
-  Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
-
-  is(plugin.description, "Plug-in for testing purposes.\u2122 " +
-                             "(\u0939\u093f\u0928\u094d\u0926\u0940 " +
-                             "\u4e2d\u6587 " +
-                             "\u0627\u0644\u0639\u0631\u0628\u064a\u0629)",
-                         "Test plugin had an incorrect description");
-  is(plugin.version, "1.0.0.0", "Test plugin had an incorrect version");
-  ok(!plugin.disabled, "Test plugin should not be disabled");
-  ok(!plugin.blocklisted, "Test plugin should not be blocklisted");
-
-  var frame = document.getElementById("testframe");
-  frame.addEventListener("load", frame_loaded, true);
-  load_frame(test_normal, "file_bug391728");
-}
-
-function finish_test(plugin) {
-  Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
-  resetBlocklist();
-  plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED;
-  SimpleTest.finish();
-}
-
-function load_frame(nextTest, file) {
-  gNextTest = nextTest;
-  gDisabled = [];
-  gUnknown = [];
-  gBlocked = [];
-  var frame = document.getElementById("testframe");
-  frame.src = file + ".html?" + Math.random();
-}
-
-function next_text() {
-  PluginUtils.withTestPlugin(gNextTest);
-}
-
-function frame_loaded() {
-  SimpleTest.requestFlakyTimeout("We must delay to wait for the plugin sources to be loaded :(");
-  setTimeout(next_text, 500);
-}
-
-function test_style(expected) {
-  var frame = document.getElementById("testframe");
-  for (var i = 1; i <= PLUGIN_COUNT; i++) {
-    var tag = frame.contentDocument.getElementById("plugin" + i);
-    ok(tag, "Plugin " + i + " did not exist");
-    var style = frame.contentWindow.getComputedStyle(tag, null);
-    is(style.borderTopStyle, expected, "Plugin " + i + " had an incorrect border style");
-  }
-  for (i = 1; i <= FALLBACK_COUNT; i++) {
-    var tag = frame.contentDocument.getElementById("fallback" + i);
-    ok(tag, "Fallback plugin " + i + " did not exist");
-    var style = frame.contentWindow.getComputedStyle(tag, null);
-    is(style.borderTopStyle, "solid", "Fallback plugin " + i + " had an incorrect border style");
-  }
-}
-
-function test_list(list) {
-  for (var i = 1; i <= PLUGIN_COUNT; i++) {
-    ok(list.indexOf("plugin" + i) >= 0, "Plugin " + i + " did not send the event");
-  }
-  for (i = 1; i <= FALLBACK_COUNT; i++) {
-    ok(list.indexOf("fallback" + i) < 0, "Fallback plugin " + i + " should not have sent the event");
-  }
-}
-
-function test_normal(plugin) {
-  is(gUnknown.length, 0, "Should not have been any unknown plugins");
-  is(gDisabled.length, 0, "Should not have been any disabled plugins");
-  is(gBlocked.length, 0, "Should not have been any blocked plugins");
-  test_style("solid");
-  plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_DISABLED;
-  load_frame(test_disabled, "file_bug391728");
-}
-
-function test_disabled(plugin) {
-  is(gUnknown.length, 0, "Should not have been any unknown plugins");
-  is(gDisabled.length, PLUGIN_COUNT, "Should have been disabled plugins");
-  test_list(gDisabled);
-  is(gBlocked.length, 0, "Should not have been any blocked plugins");
-  test_style("dotted");
-  ok(plugin.disabled, "Plugin lost its disabled status");
-  plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED;
-
-  setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
-    function() {
-      load_frame(test_blocked, "file_bug391728");
-    });
-}
-
-function test_blocked(plugin) {
-  is(gUnknown.length, 0, "Should not have been any unknown plugins");
-  is(gDisabled.length, 0, "Should not have been any disabled plugins");
-  is(gBlocked.length, PLUGIN_COUNT, "Should have been blocked plugins");
-  test_list(gBlocked);
-  test_style("dashed");
-  ok(plugin.blocklisted, "Plugin lost its blocklist status");
-  load_frame(test_unknown, "file_bug391728_2");
-}
-
-function test_unknown(plugin) {
-  is(gUnknown.length, PLUGIN_COUNT, "Should have been unknown plugins");
-  test_list(gUnknown);
-  is(gDisabled.length, 0, "Should not have been any disabled plugins");
-  is(gBlocked.length, 0, "Should not have been any blocked plugins");
-  test_style("none");
-  setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
-    ok(!plugin.blocklisted, "Plugin shouldn't remain blocklisted");
-    finish_test(plugin);
-  });
-}
-
-SimpleTest.waitForExplicitFinish();
-window.addEventListener("load", init_test, false);
-</script>
-</pre>
-</body>
-</html>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -386,17 +386,16 @@ skip-if = buildapp == 'b2g' # b2g(bug 90
 [test_bug422403-2.xhtml]
 skip-if = buildapp == 'b2g'
 [test_bug422537.html]
 [test_bug424212.html]
 [test_bug424359-1.html]
 skip-if = buildapp == 'b2g'
 [test_bug424359-2.html]
 skip-if = buildapp == 'b2g'
-[test_bug425013.html]
 [test_bug426308.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
 [test_bug426646.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug428847.html]
 [test_bug429157.html]
 [test_bug431082.html]
 [test_bug431701.html]
--- a/dom/base/test/test_bug368972.html
+++ b/dom/base/test/test_bug368972.html
@@ -75,40 +75,46 @@ Object height=100 (stylesheet width:400p
 <object id="object11" type="bogus" height="100">
 </object><br>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 function check_size(id, width, height) {
   var element = document.getElementById(id);
   ok(element, "Plugin element " + id + " did not exist");
+  if (width != "auto") {
+    width = width + "px";
+  }
+  if (height != "auto") {
+    height = height + "px";
+  }
   var style = window.getComputedStyle(element, null);
-  is(style.width, width + "px", "Plugin element " + id + " had an incorrect width");
-  is(style.height, height + "px", "Plugin element " + id + " had an incorrect height");
+  is(style.width, width, "Plugin element " + id + " had an incorrect width");
+  is(style.height, height, "Plugin element " + id + " had an incorrect height");
 }
 
-check_size("embed1", 240, 200);
+check_size("embed1", "auto", "auto");
 check_size("embed2", 0, 0);
 check_size("embed3", 100, 100);
-check_size("embed4", 240, 100);
-check_size("embed5", 100, 200);
+check_size("embed4", "auto", 100);
+check_size("embed5", 100, "auto");
 check_size("embed6", 100, 100);
 check_size("embed7", 100, 100);
-check_size("embed8", 240, 100);
+check_size("embed8", "auto", 100);
 check_size("embed9", 400, 100);
 check_size("embed10", 400, 100);
 check_size("embed11", 400, 400);
 
-check_size("object1", 240, 200);
+check_size("object1", "auto", "auto");
 check_size("object2", 0, 0);
 check_size("object3", 100, 100);
-check_size("object4", 240, 100);
-check_size("object5", 100, 200);
+check_size("object4", "auto", 100);
+check_size("object5", 100, "auto");
 check_size("object6", 100, 100);
 check_size("object7", 100, 100);
-check_size("object8", 240, 100);
+check_size("object8", "auto", 100);
 check_size("object9", 400, 100);
 check_size("object10", 400, 100);
 check_size("object11", 400, 400);
 </script>
 </pre>
 </body>
 </html>
deleted file mode 100644
--- a/dom/base/test/test_bug425013.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=425013
--->
-<head>
-  <title>Test for Bug 425013</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body onload="runtests();">
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=425013">Mozilla Bug 425013</a>
-<br>
-
-<script type="text/javascript;version=1.7">
-var missingPlugins = new Array();
-var OBJLC = SpecialPowers.Ci.nsIObjectLoadingContent;
-
-function pluginBinding(event)
-{
-  var plugin = event.target;
-  plugin instanceof OBJLC;
-  if (SpecialPowers.wrap(plugin).pluginFallbackType == OBJLC.PLUGIN_UNSUPPORTED)
-    missingPlugins.push(plugin);
-}
-
-document.addEventListener("PluginBindingAttached", pluginBinding, true);
-</script>
-
-<object type="foo/bar" id="obj1"></object>
-
-<object type="foo/bar" id="obj2">
-  <embed type="a/b" id="embed1"></embed>
-</object>
-
-<object type="foo/bar"
-        data="data:foo/bar,bah" id="obj3">
-<param name="movie" value="data:foo/bar,bah">
-</object>
-
-<object type="foo/bar"
-        data="data:foo/bar,bah" id="obj4">
-<param name="movie" value="data:foo/bar,bah">
-<p>Alternate content</p>
-</object>
-
-<object type="text/html"
-        data="data:text/html,an html document in an object tag" id="obj5">
-</object>
-
-<object type="text/html"
-        data="data:text/html,an html document in an object tag" id="obj6">
-<p>Alternate content</p>
-</object>
-
-<embed type="a/b" id="embed2"></embed>
-
-<script class="testbody" type="text/javascript">
-function runtests()
-{
-  // Force layout flush so the binding is attached and the event is fired
-  document.getElementById("obj1").clientTop;
-  document.getElementById("obj3").clientTop;
-  document.getElementById("embed1").clientTop;
-  document.getElementById("embed2").clientTop;
-
-  // Let pending events flush
-  SimpleTest.executeSoon(function () {
-    ok(missingPlugins.indexOf(document.getElementById("obj1")) >= 0, "Missing plugin element obj1");
-    ok(missingPlugins.indexOf(document.getElementById("embed1")) >= 0, "Missing plugin element embed1");
-    ok(missingPlugins.indexOf(document.getElementById("embed2")) >= 0, "Missing plugin element embed2");
-    ok(missingPlugins.indexOf(document.getElementById("obj3")) >= 0, "Missing plugin element obj3");
-
-    is(missingPlugins.length, 4, "Wrong number of missing plugins");
-
-    SimpleTest.finish();
-  });
-}
-
-SimpleTest.waitForExplicitFinish();
-</script>
-</pre>
-</body>
-</html>
--- a/dom/cache/CacheStorage.cpp
+++ b/dom/cache/CacheStorage.cpp
@@ -114,17 +114,16 @@ IsTrusted(const PrincipalInfo& aPrincipa
   nsresult rv = urlParser->ParseURL(url, flatURL.Length(),
                                     &schemePos, &schemeLen,
                                     &authPos, &authLen,
                                     nullptr, nullptr);      // ignore path
   if (NS_WARN_IF(NS_FAILED(rv))) { return false; }
 
   nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
   if (scheme.LowerCaseEqualsLiteral("https") ||
-      scheme.LowerCaseEqualsLiteral("app") ||
       scheme.LowerCaseEqualsLiteral("file")) {
     return true;
   }
 
   uint32_t hostPos;
   int32_t hostLen;
 
   rv = urlParser->ParseAuthority(url + authPos, authLen,
--- a/dom/cache/TypeUtils.cpp
+++ b/dom/cache/TypeUtils.cpp
@@ -395,18 +395,17 @@ TypeUtils::ProcessURL(nsACString& aUrl, 
   aRv = urlParser->ParseURL(url, flatURL.Length(), &schemePos, &schemeLen,
                             nullptr, nullptr,       // ignore authority
                             &pathPos, &pathLen);
   if (NS_WARN_IF(aRv.Failed())) { return; }
 
   if (aSchemeValidOut) {
     nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
     *aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") ||
-                       scheme.LowerCaseEqualsLiteral("https") ||
-                       scheme.LowerCaseEqualsLiteral("app");
+                       scheme.LowerCaseEqualsLiteral("https");
   }
 
   uint32_t queryPos;
   int32_t queryLen;
 
   aRv = urlParser->ParsePath(url + pathPos, flatURL.Length() - pathPos,
                              nullptr, nullptr,               // ignore filepath
                              &queryPos, &queryLen,
--- a/dom/devicestorage/test/test_app_permissions.html
+++ b/dom/devicestorage/test/test_app_permissions.html
@@ -638,24 +638,18 @@ try {
   f.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
   } catch(e) {}
 }
 
 createTestFile('.txt');
 var gTestRunner = runTest();
 SpecialPowers.addPermission("browser", true, gTestUri);
 
-// We are more permissive with CSP in our testing environment....
-const DEFAULT_CSP_PRIV = "default-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'";
-const DEFAULT_CSP_CERT = "default-src *; script-src 'self'; style-src 'self'; object-src 'none'";
-
 SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
                                    ["device.storage.enabled", true],
                                    ["device.storage.testing", true],
-                                   ["device.storage.prompt.testing", false],
-                                   ["security.apps.privileged.CSP.default", DEFAULT_CSP_PRIV],
-                                   ["security.apps.certified.CSP.default", DEFAULT_CSP_CERT]]},
+                                   ["device.storage.prompt.testing", false]]},
   function() {  gTestRunner.next(); });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/devicestorage/test/test_fs_app_permissions.html
+++ b/dom/devicestorage/test/test_fs_app_permissions.html
@@ -813,24 +813,18 @@ function createTestFile(extension) {
     f.appendRelativePath("testfile" + extension);
     f.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
   } catch(e) {}
 }
 
 let gTestRunner = runTest();
 SpecialPowers.addPermission("browser", true, gTestUri);
 
-// We are more permissive with CSP in our testing environment....
-const DEFAULT_CSP_PRIV = "default-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'";
-const DEFAULT_CSP_CERT = "default-src *; script-src 'self'; style-src 'self'; object-src 'none'";
-
 SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
                                    ["device.storage.enabled", true],
                                    ["device.storage.testing", true],
-                                   ["device.storage.prompt.testing", false],
-                                   ["security.apps.privileged.CSP.default", DEFAULT_CSP_PRIV],
-                                   ["security.apps.certified.CSP.default", DEFAULT_CSP_CERT]]},
+                                   ["device.storage.prompt.testing", false]]},
   function() { gTestRunner.next(); });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/events/EventStates.h
+++ b/dom/events/EventStates.h
@@ -249,18 +249,16 @@ private:
 #define NS_EVENT_STATE_BROKEN        NS_DEFINE_EVENT_STATE_MACRO(20)
 // Content disabled by the user (images turned off, say).
 #define NS_EVENT_STATE_USERDISABLED  NS_DEFINE_EVENT_STATE_MACRO(21)
 // Content suppressed by the user (ad blocking, etc).
 #define NS_EVENT_STATE_SUPPRESSED    NS_DEFINE_EVENT_STATE_MACRO(22)
 // Content is still loading such that there is nothing to show the
 // user (eg an image which hasn't started coming in yet).
 #define NS_EVENT_STATE_LOADING       NS_DEFINE_EVENT_STATE_MACRO(23)
-// Content is of a type that gecko can't handle.
-#define NS_EVENT_STATE_TYPE_UNSUPPORTED NS_DEFINE_EVENT_STATE_MACRO(24)
 #define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL NS_DEFINE_EVENT_STATE_MACRO(25)
 // Handler for the content has been blocked.
 #define NS_EVENT_STATE_HANDLER_BLOCKED NS_DEFINE_EVENT_STATE_MACRO(26)
 // Handler for the content has been disabled.
 #define NS_EVENT_STATE_HANDLER_DISABLED NS_DEFINE_EVENT_STATE_MACRO(27)
 // Handler for the content has crashed
 #define NS_EVENT_STATE_HANDLER_CRASHED NS_DEFINE_EVENT_STATE_MACRO(28)
 // Content has focus and should show a ring.
@@ -283,18 +281,16 @@ private:
 // Content is in the suboptimal region.
 #define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(37)
 // Content is in the sub-suboptimal region.
 #define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(38)
 // Handler for click to play plugin (vulnerable w/update)
 #define NS_EVENT_STATE_VULNERABLE_UPDATABLE NS_DEFINE_EVENT_STATE_MACRO(39)
 // 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)
 // 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)
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -1242,35 +1242,29 @@ Geolocation::GetCurrentPosition(GeoPosit
     NS_DispatchToMainThread(ev);
     return NS_OK;
   }
 
   if (!mOwner && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
-  return GetCurrentPositionReady(request);
-}
-
-nsresult
-Geolocation::GetCurrentPositionReady(nsGeolocationRequest* aRequest)
-{
   if (mOwner) {
-    if (!RegisterRequestWithPrompt(aRequest)) {
+    if (!RegisterRequestWithPrompt(request)) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     return NS_OK;
   }
 
   if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(true, aRequest);
+  nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(true, request);
   NS_DispatchToMainThread(ev);
 
   return NS_OK;
 }
 
 int32_t
 Geolocation::WatchPosition(PositionCallback& aCallback,
                            PositionErrorCallback* aErrorCallback,
@@ -1329,34 +1323,28 @@ Geolocation::WatchPosition(GeoPositionCa
     NS_DispatchToMainThread(ev);
     return NS_OK;
   }
 
   if (!mOwner && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
-  return WatchPositionReady(request);
-}
-
-nsresult
-Geolocation::WatchPositionReady(nsGeolocationRequest* aRequest)
-{
   if (mOwner) {
-    if (!RegisterRequestWithPrompt(aRequest))
+    if (!RegisterRequestWithPrompt(request))
       return NS_ERROR_NOT_AVAILABLE;
 
     return NS_OK;
   }
 
   if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
-  aRequest->Allow(JS::UndefinedHandleValue);
+  request->Allow(JS::UndefinedHandleValue);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Geolocation::ClearWatch(int32_t aWatchId)
 {
   if (aWatchId < 0) {
@@ -1385,30 +1373,16 @@ Geolocation::ClearWatch(int32_t aWatchId
       mPendingRequests.RemoveElementAt(i);
       break;
     }
   }
 
   return NS_OK;
 }
 
-void
-Geolocation::ServiceReady()
-{
-  for (uint32_t length = mPendingRequests.Length(); length > 0; --length) {
-    if (mPendingRequests[0]->IsWatch()) {
-      WatchPositionReady(mPendingRequests[0]);
-    } else {
-      GetCurrentPositionReady(mPendingRequests[0]);
-    }
-
-    mPendingRequests.RemoveElementAt(0);
-  }
-}
-
 bool
 Geolocation::WindowOwnerStillExists()
 {
   // an owner was never set when Geolocation
   // was created, which means that this object
   // is being used without a window.
   if (mOwner == nullptr) {
     return true;
--- a/dom/geolocation/nsGeolocation.h
+++ b/dom/geolocation/nsGeolocation.h
@@ -166,36 +166,29 @@ public:
   nsIWeakReference* GetOwner() { return mOwner; }
 
   // Check to see if the window still exists
   bool WindowOwnerStillExists();
 
   // Check to see if any active request requires high accuracy
   bool HighAccuracyRequested();
 
-  // Notification from the service:
-  void ServiceReady();
-
 private:
 
   ~Geolocation();
 
   nsresult GetCurrentPosition(GeoPositionCallback aCallback,
                               GeoPositionErrorCallback aErrorCallback,
                               nsAutoPtr<PositionOptions>&& aOptions);
   nsresult WatchPosition(GeoPositionCallback aCallback,
                          GeoPositionErrorCallback aErrorCallback,
                          nsAutoPtr<PositionOptions>&& aOptions, int32_t* aRv);
 
   bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
 
-  // Methods for the service when it's ready to process requests:
-  nsresult GetCurrentPositionReady(nsGeolocationRequest* aRequest);
-  nsresult WatchPositionReady(nsGeolocationRequest* aRequest);
-
   // Check if clearWatch is already called
   bool IsAlreadyCleared(nsGeolocationRequest* aRequest);
 
   // Two callback arrays.  The first |mPendingCallbacks| holds objects for only
   // one callback and then they are released/removed from the array.  The second
   // |mWatchingCallbacks| holds objects until the object is explictly removed or
   // there is a page change. All requests held by either array are active, that
   // is, they have been allowed and expect to be fulfilled.
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Likely.h"
 
 #include "nscore.h"
@@ -182,22 +183,28 @@ nsGenericHTMLElement::CopyInnerTo(Elemen
   for (i = 0; i < count; ++i) {
     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
     const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
 
     nsAutoString valStr;
     value->ToString(valStr);
 
     if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) &&
-        value->Type() == nsAttrValue::eGeckoCSSDeclaration) {
+        value->Type() == nsAttrValue::eCSSDeclaration) {
+      DeclarationBlock* decl = value->GetCSSDeclarationValue();
+      if (decl->IsServo()) {
+        MOZ_CRASH("stylo: clone not implemented");
+        continue;
+      }
+
       // We can't just set this as a string, because that will fail
       // to reparse the string into style data until the node is
       // inserted into the document.  Clone the Rule instead.
-      RefPtr<css::Declaration> declClone =
-        new css::Declaration(*value->GetGeckoCSSDeclarationValue());
+      RefPtr<css::Declaration>
+        declClone = new css::Declaration(*decl->AsGecko());
 
       rv = aDst->SetInlineStyleDeclaration(declClone, &valStr, false);
       NS_ENSURE_SUCCESS(rv, rv);
 
       continue;
     }
 
     rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
--- a/dom/interfaces/apps/nsIAppsService.idl
+++ b/dom/interfaces/apps/nsIAppsService.idl
@@ -42,26 +42,16 @@ interface nsIAppsService : nsISupports
   mozIApplication getAppByLocalId(in unsigned long localId);
 
   /**
    * Returns the manifest URL associated to this localId.
    */
   DOMString getManifestURLByLocalId(in unsigned long localId);
 
   /**
-   * Returns the manifest CSP associated to this localId.
-   */
-  DOMString getManifestCSPByLocalId(in unsigned long localId);
-
-  /**
-   * Returns the default CSP associated to this localId.
-   */
-  DOMString getDefaultCSPByLocalId(in unsigned long localId);
-
-  /**
    * Returns the basepath for core apps
    */
   DOMString getCoreAppsBasePath();
 
   /**
    * Returns the basepath for regular packaged apps
    */
   DOMString getWebAppsBasePath();
--- a/dom/interfaces/notification/moz.build
+++ b/dom/interfaces/notification/moz.build
@@ -1,13 +1,12 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
-    'nsIDOMDesktopNotification.idl',
     'nsINotificationStorage.idl',
 ]
 
 XPIDL_MODULE = 'dom_notification'
 
deleted file mode 100644
--- a/dom/interfaces/notification/nsIDOMDesktopNotification.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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 "domstubs.idl"
-
-interface nsIObserver;
-
-// Notification service that also provides the manifest URL
-[scriptable, uuid(50cb17d2-dc8a-4aa6-bcd3-94d76af14e20)]
-interface nsIAppNotificationService : nsISupports
-{
-    void showAppNotification(in AString  imageUrl,
-                             in AString  title,
-                             in AString  text,
-                             in nsIObserver alertListener,
-                             // details should be a WebIDL
-                             // AppNotificationServiceOptions Dictionary object
-                             in jsval    details);
-};
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -243,18 +243,23 @@ public:
     auto s = new S(master);
 
     MOZ_ASSERT(master->mState != s->GetState() ||
                master->mState == DECODER_STATE_SEEKING);
 
     SLOG("change state to: %s", ToStateStr(s->GetState()));
 
     Exit();
+
+    // Note |aArgs| might reference data members of |this|. We need to keep
+    // |this| alive until |s->Enter()| returns.
+    UniquePtr<StateObject> deathGrip(master->mStateObj.release());
+
     master->mState = s->GetState();
-    master->mStateObj.reset(s); // Will delete |this|!
+    master->mStateObj.reset(s);
     return s->Enter(Forward<Ts>(aArgs)...);
   }
 
 protected:
   // Take a raw pointer in order not to change the life cycle of MDSM.
   // It is guaranteed to be valid by MDSM.
   Master* mMaster;
 };
@@ -326,17 +331,17 @@ private:
 };
 
 class MediaDecoderStateMachine::WaitForCDMState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit WaitForCDMState(Master* aPtr) : StateObject(aPtr) {}
 
-  void Enter() {}
+  void Enter(bool aPendingDormant) { mPendingDormant = aPendingDormant; }
 
   State GetState() const override
   {
     return DECODER_STATE_WAIT_FOR_CDM;
   }
 
   bool HandleDormant(bool aDormant) override;
 
@@ -344,16 +349,19 @@ public:
 
   RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override
   {
     SLOG("Not Enough Data to seek at this stage, queuing seek");
     mMaster->mQueuedSeek.RejectIfExists(__func__);
     mMaster->mQueuedSeek.mTarget = aTarget;
     return mMaster->mQueuedSeek.mPromise.Ensure(__func__);
   }
+
+private:
+  bool mPendingDormant = false;
 };
 
 class MediaDecoderStateMachine::DormantState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit DormantState(Master* aPtr) : StateObject(aPtr) {}
 
@@ -971,63 +979,55 @@ DecodeMetadataState::OnMetadataRead(Meta
 
   mMaster->mNotifyMetadataBeforeFirstFrame =
     mMaster->mDuration.Ref().isSome() || waitingForCDM;
 
   if (mMaster->mNotifyMetadataBeforeFirstFrame) {
     mMaster->EnqueueLoadedMetadataEvent();
   }
 
-  if (mPendingDormant) {
-    // No need to store mQueuedSeek because we are at position 0.
-    SetState<DormantState>();
-    return;
-  }
-
   if (waitingForCDM) {
     // Metadata parsing was successful but we're still waiting for CDM caps
     // to become available so that we can build the correct decryptor/decoder.
-    SetState<WaitForCDMState>();
-    return;
+    SetState<WaitForCDMState>(mPendingDormant);
+  } else if (mPendingDormant) {
+    SetState<DormantState>();
+  } else {
+    SetState<DecodingFirstFrameState>();
   }
-
-  SetState<DecodingFirstFrameState>();
 }
 
 bool
 MediaDecoderStateMachine::
 WaitForCDMState::HandleDormant(bool aDormant)
 {
-  if (aDormant) {
-    // No need to store mQueuedSeek because we are at position 0.
-    SetState<DormantState>();
-  }
+  mPendingDormant = aDormant;
   return true;
 }
 
 bool
 MediaDecoderStateMachine::
 DormantState::HandleDormant(bool aDormant)
 {
   if (!aDormant) {
-    // Exit dormant state. Check if we need the CDMProxy to start decoding.
-    if (Info().IsEncrypted() && !mMaster->mCDMProxy) {
-      SetState<WaitForCDMState>();
-    } else {
-      SetState<DecodingFirstFrameState>();
-    }
+    MOZ_ASSERT(!Info().IsEncrypted() || mMaster->mCDMProxy);
+    SetState<DecodingFirstFrameState>();
   }
   return true;
 }
 
 bool
 MediaDecoderStateMachine::
 WaitForCDMState::HandleCDMProxyReady()
 {
-  SetState<DecodingFirstFrameState>();
+  if (mPendingDormant) {
+    SetState<DormantState>();
+  } else {
+    SetState<DecodingFirstFrameState>();
+  }
   return true;
 }
 
 void
 MediaDecoderStateMachine::
 DecodingFirstFrameState::Enter()
 {
   // Handle pending seek.
@@ -3142,17 +3142,22 @@ MediaDecoderStateMachine::DumpDebugInfo(
       "mAudioStatus=%s mVideoStatus=%s mDecodedAudioEndTime=%lld mDecodedVideoEndTime=%lld "
       "mAudioCompleted=%d mVideoCompleted=%d",
       GetMediaTime(), mMediaSink->IsStarted() ? GetClock() : -1, mMediaSink.get(),
       ToStateStr(), mPlayState.Ref(), mSentFirstFrameLoadedEvent, IsPlaying(),
       AudioRequestStatus(), VideoRequestStatus(), mDecodedAudioEndTime, mDecodedVideoEndTime,
       mAudioCompleted.Ref(), mVideoCompleted.Ref());
   });
 
-  OwnerThread()->DispatchStateChange(r.forget());
+  // Since the task is run asynchronously, it is possible other tasks get first
+  // and change the object states before we print them. Therefore we want to
+  // dispatch this task immediately without waiting for the tail dispatching
+  // phase so object states are less likely to change before being printed.
+  OwnerThread()->Dispatch(r.forget(),
+    AbstractThread::AssertDispatchSuccess, AbstractThread::TailDispatch);
 }
 
 void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
                                                bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   DECODER_LOG("AddOutputStream aStream=%p!", aStream);
   mOutputStreamManager->Add(aStream, aFinishWhenEnded);
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -345,34 +345,47 @@ already_AddRefed<Promise>
 MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
 {
   RefPtr<DetailedPromise> promise(MakePromise(aRv,
     NS_LITERAL_CSTRING("MediaKeySession.load")));
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  if (aSessionId.IsEmpty()) {
-    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR,
-                         NS_LITERAL_CSTRING("Trying to load a session with empty session ID"));
-    // "The sessionId parameter is empty."
-    EME_LOG("MediaKeySession[%p,''] Load() failed, no sessionId", this);
+  // 1. If this object is closed, return a promise rejected with an InvalidStateError.
+  if (IsClosed()) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
+                         NS_LITERAL_CSTRING("Session is closed in MediaKeySession.load()"));
+    EME_LOG("MediaKeySession[%p,'%s'] Load() failed, closed",
+      this, NS_ConvertUTF16toUTF8(aSessionId).get());
     return promise.forget();
   }
 
+  // 2.If this object's uninitialized value is false, return a promise rejected
+  // with an InvalidStateError.
   if (!mUninitialized) {
-    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR,
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                          NS_LITERAL_CSTRING("Session is already initialized in MediaKeySession.load()"));
     EME_LOG("MediaKeySession[%p,'%s'] Load() failed, uninitialized",
       this, NS_ConvertUTF16toUTF8(aSessionId).get());
     return promise.forget();
   }
 
+  // 3.Let this object's uninitialized value be false.
   mUninitialized = false;
 
+  // 4. If sessionId is the empty string, return a promise rejected with a newly created TypeError.
+  if (aSessionId.IsEmpty()) {
+    promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR,
+                         NS_LITERAL_CSTRING("Trying to load a session with empty session ID"));
+    // "The sessionId parameter is empty."
+    EME_LOG("MediaKeySession[%p,''] Load() failed, no sessionId", this);
+    return promise.forget();
+  }
+
   // We now know the sessionId being loaded into this session. Remove the
   // session from its owning MediaKey's set of sessions awaiting a sessionId.
   RefPtr<MediaKeySession> session(mKeys->GetPendingSession(Token()));
   MOZ_ASSERT(session == this, "Session should be awaiting id on its own token");
 
   // Associate with the known sessionId.
   SetSessionId(aSessionId);
 
--- a/dom/media/mediasource/test/mochitest.ini
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -41,16 +41,18 @@ support-files =
   aac51-48000-128000-1.m4s aac51-48000-128000-1.m4s^headers^
   aac51-48000-128000-2.m4s aac51-48000-128000-2.m4s^headers^
   bipbop/bipbop_480_624kbps-videoinit.mp4 bipbop/bipbop_480_624kbps-videoinit.mp4^headers^
   bipbop/bipbop_480_624kbps-video1.m4s bipbop/bipbop_480_624kbps-video1.m4s^headers^
   bipbop/bipbop_480_624kbps-video2.m4s bipbop/bipbop_480_624kbps-video2.m4s^headers^
 
 [test_AudioChange_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3
+[test_AutoRevocation.html]
+tags = firstpartyisolation
 [test_BufferedSeek.html]
 [test_BufferedSeek_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3
 [test_BufferingWait.html]
 skip-if = toolkit == 'android' #timeout android bug 1199531
 [test_BufferingWait_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3
 [test_DrainOnMissingData_mp4.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/mediasource/test/test_AutoRevocation.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>MSE: auto-revocation</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="mediasource.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(function () {
+  var ms = new MediaSource();
+  var o = URL.createObjectURL(ms);
+  var v = document.createElement("video");
+
+  v.addEventListener("error", function (e) {
+    ok(true, "ObjectURL should be auto-revoked");
+    SimpleTest.finish();
+  });
+
+  v.addEventListener("stalled", function (e) {
+    ok(false, "If auto-revocation is gone, please turn on TODOs in browser_mediaSourceURL.js");
+    SimpleTest.finish();
+  });
+
+  setTimeout(function() {
+    v.src = o;
+    v.preload = "auto";
+    document.body.appendChild(v);
+  }, 0);
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -53,22 +53,22 @@ public:
 
   void OnInputExhausted()
   {
     if (mDecoderCallback) {
       mDecoderCallback->InputExhausted();
     }
   }
 
-  virtual void HandleOutput(jni::ByteArray::Param aBytes, BufferInfo::Param aInfo) = 0;
+  virtual void HandleOutput(Sample::Param aSample) = 0;
 
-  void OnOutput(jni::ByteArray::Param aBytes, jni::Object::Param aInfo)
+  void OnOutput(jni::Object::Param aSample)
   {
     if (mDecoderCallback) {
-      HandleOutput(aBytes, BufferInfo::Ref::From(aInfo));
+      HandleOutput(Sample::Ref::From(aSample));
     }
   }
 
   virtual void HandleOutputFormatChanged(MediaFormat::Param aFormat) {};
 
   void OnOutputFormatChanged(jni::Object::Param aFormat)
   {
     if (mDecoderCallback) {
@@ -119,37 +119,39 @@ public:
   public:
     CallbacksSupport(RemoteVideoDecoder* aDecoder, MediaDataDecoderCallback* aCallback)
       : JavaCallbacksSupport(aCallback)
       , mDecoder(aDecoder)
     {}
 
     virtual ~CallbacksSupport() {}
 
-    void HandleOutput(jni::ByteArray::Param aBytes, BufferInfo::Param aInfo) override
+    void HandleOutput(Sample::Param aSample) override
     {
       Maybe<int64_t> durationUs = mDecoder->mInputDurations.Get();
       if (!durationUs) {
         return;
       }
 
+      BufferInfo::LocalRef info = aSample->Info();
+
       int32_t flags;
-      bool ok = NS_SUCCEEDED(aInfo->Flags(&flags));
+      bool ok = NS_SUCCEEDED(info->Flags(&flags));
       MOZ_ASSERT(ok);
 
       int32_t offset;
-      ok |= NS_SUCCEEDED(aInfo->Offset(&offset));
+      ok |= NS_SUCCEEDED(info->Offset(&offset));
       MOZ_ASSERT(ok);
 
       int64_t presentationTimeUs;
-      ok |= NS_SUCCEEDED(aInfo->PresentationTimeUs(&presentationTimeUs));
+      ok |= NS_SUCCEEDED(info->PresentationTimeUs(&presentationTimeUs));
       MOZ_ASSERT(ok);
 
       int32_t size;
-      ok |= NS_SUCCEEDED(aInfo->Size(&size));
+      ok |= NS_SUCCEEDED(info->Size(&size));
       MOZ_ASSERT(ok);
 
       NS_ENSURE_TRUE_VOID(ok);
 
       if (size > 0 && durationUs.value() > 0) {
         RefPtr<layers::Image> img =
           new SurfaceTextureImage(mDecoder->mSurfaceTexture.get(), mDecoder->mConfig.mDisplay,
                                   gl::OriginPos::BottomLeft);
@@ -323,32 +325,34 @@ private:
   public:
     CallbacksSupport(RemoteAudioDecoder* aDecoder, MediaDataDecoderCallback* aCallback)
       : JavaCallbacksSupport(aCallback)
       , mDecoder(aDecoder)
     {}
 
     virtual ~CallbacksSupport() {}
 
-    void HandleOutput(jni::ByteArray::Param aBytes, BufferInfo::Param aInfo) override
+    void HandleOutput(Sample::Param aSample) override
     {
+      BufferInfo::LocalRef info = aSample->Info();
+
       int32_t flags;
-      bool ok = NS_SUCCEEDED(aInfo->Flags(&flags));
+      bool ok = NS_SUCCEEDED(info->Flags(&flags));
       MOZ_ASSERT(ok);
 
       int32_t offset;
-      ok |= NS_SUCCEEDED(aInfo->Offset(&offset));
+      ok |= NS_SUCCEEDED(info->Offset(&offset));
       MOZ_ASSERT(ok);
 
       int64_t presentationTimeUs;
-      ok |= NS_SUCCEEDED(aInfo->PresentationTimeUs(&presentationTimeUs));
+      ok |= NS_SUCCEEDED(info->PresentationTimeUs(&presentationTimeUs));
       MOZ_ASSERT(ok);
 
       int32_t size;
-      ok |= NS_SUCCEEDED(aInfo->Size(&size));
+      ok |= NS_SUCCEEDED(info->Size(&size));
       MOZ_ASSERT(ok);
 
       NS_ENSURE_TRUE_VOID(ok);
 
       if (size > 0) {
 #ifdef MOZ_SAMPLE_TYPE_S16
         const int32_t numSamples = size / 2;
 #else
@@ -356,20 +360,18 @@ private:
 #endif
 
         const int32_t numFrames = numSamples / mOutputChannels;
         AlignedAudioBuffer audio(numSamples);
         if (!audio) {
           return;
         }
 
-        JNIEnv* const env = jni::GetEnvForThread();
-        jbyteArray bytes = aBytes.Get();
-        env->GetByteArrayRegion(bytes, offset, size,
-                                reinterpret_cast<jbyte*>(audio.get()));
+        jni::ByteBuffer::LocalRef dest = jni::ByteBuffer::New(audio.get(), size);
+        aSample->WriteToByteBuffer(dest);
 
         RefPtr<AudioData> data = new AudioData(0, presentationTimeUs,
                                               FramesToUsecs(numFrames, mOutputSampleRate).value(),
                                               numFrames,
                                               Move(audio),
                                               mOutputChannels,
                                               mOutputSampleRate);
 
@@ -465,25 +467,18 @@ RemoteDataDecoder::Shutdown()
   mFormat = nullptr;
 }
 
 void
 RemoteDataDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(aSample != nullptr);
 
-  JNIEnv* const env = jni::GetEnvForThread();
-
-  // Copy sample data into Java byte array.
-  uint32_t length = aSample->Size();
-  jbyteArray data = env->NewByteArray(length);
-  env->SetByteArrayRegion(data, 0, length, reinterpret_cast<const jbyte*>(aSample->Data()));
-
-  jni::ByteArray::LocalRef bytes(env);
-  bytes = jni::Object::LocalRef::Adopt(env, data);
+  jni::ByteBuffer::LocalRef bytes = jni::ByteBuffer::New(const_cast<uint8_t*>(aSample->Data()),
+                                                         aSample->Size());
 
   BufferInfo::LocalRef bufferInfo;
   nsresult rv = BufferInfo::New(&bufferInfo);
   if (NS_FAILED(rv)) {
     mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__));
     return;
   }
   bufferInfo->Set(0, aSample->Size(), aSample->mTime, 0);
deleted file mode 100644
--- a/dom/notification/ChromeNotifications.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-
-function debug(s) {
-  dump("-*- ChromeNotifications.js: " + s + "\n");
-}
-
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
-                                  "resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
-                                   "@mozilla.org/childprocessmessagemanager;1",
-                                   "nsIMessageSender");
-
-XPCOMUtils.defineLazyServiceGetter(this, "appNotifier",
-                                   "@mozilla.org/system-alerts-service;1",
-                                   "nsIAppNotificationService");
-
-const CHROMENOTIFICATIONS_CID = "{74f94093-8b37-497e-824f-c3b250a911da}";
-const CHROMENOTIFICATIONS_CONTRACTID = "@mozilla.org/mozChromeNotifications;1";
-
-function ChromeNotifications() {
-  this.innerWindowID = null;
-  this.resendCallback = null;
-}
-
-ChromeNotifications.prototype = {
-
-  init: function(aWindow) {
-    let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIDOMWindowUtils);
-    this.innerWindowID = util.currentInnerWindowID;
-    Services.obs.addObserver(this, "inner-window-destroyed", false);
-    cpmm.addMessageListener("Notification:GetAllCrossOrigin:Return:OK", this);
-  },
-
-  performResend: function(notifications) {
-    let resentNotifications = 0;
-
-    notifications.forEach(function(notification) {
-      let behavior;
-      try {
-        behavior = JSON.parse(notification.mozbehavior);
-      } catch(e) {
-        behavior = undefined;
-      }
-
-      if (behavior && behavior.showOnlyOnce === true) {
-        return;
-      }
-
-      appNotifier.showAppNotification(
-        notification.icon,
-        notification.title,
-        notification.body,
-        null,
-        {
-          manifestURL: notification.origin,
-          id: notification.alertName,
-          dir: notification.dir,
-          lang: notification.lang,
-          tag: notification.tag,
-          dbId: notification.id,
-          timestamp: notification.timestamp,
-          data: notification.data,
-          mozbehavior: behavior
-        }
-      );
-      resentNotifications++;
-    });
-
-    try {
-      this.resendCallback && this.resendCallback(resentNotifications);
-    } catch (ex) {
-      if (DEBUG) debug("Content sent exception: " + ex);
-    }
-  },
-
-  mozResendAllNotifications: function(resendCallback) {
-    this.resendCallback = resendCallback;
-    cpmm.sendAsyncMessage("Notification:GetAllCrossOrigin", {});
-  },
-
-  receiveMessage: function(message) {
-    switch (message.name) {
-      case "Notification:GetAllCrossOrigin:Return:OK":
-        this.performResend(message.data.notifications);
-        break;
-
-      default:
-        if (DEBUG) { debug("Unrecognized message: " + message.name); }
-        break;
-    }
-  },
-
-  observe: function(aSubject, aTopic, aData) {
-    if (DEBUG) debug("Topic: " + aTopic);
-    if (aTopic == "inner-window-destroyed") {
-      let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
-      if (wId != this.innerWindowID) {
-        return;
-      }
-      Services.obs.removeObserver(this, "inner-window-destroyed");
-      cpmm.removeMessageListener("Notification:GetAllCrossOrigin:Return:OK", this);
-    }
-  },
-
-  classID : Components.ID(CHROMENOTIFICATIONS_CID),
-  contractID : CHROMENOTIFICATIONS_CONTRACTID,
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIChromeNotifications,
-                                         Ci.nsIDOMGlobalPropertyInitializer,
-                                         Ci.nsIObserver,
-                                         Ci.nsIMessageListener]),
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ChromeNotifications]);
deleted file mode 100644
--- a/dom/notification/ChromeNotifications.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-# ChromeNotifications.js
-component {74f94093-8b37-497e-824f-c3b250a911da} ChromeNotifications.js
-contract @mozilla.org/mozChromeNotifications;1 {74f94093-8b37-497e-824f-c3b250a911da}
--- a/dom/notification/DesktopNotification.cpp
+++ b/dom/notification/DesktopNotification.cpp
@@ -6,20 +6,18 @@
 #include "mozilla/dom/DesktopNotification.h"
 #include "mozilla/dom/DesktopNotificationBinding.h"
 #include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentPermissionHelper.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/dom/PBrowserChild.h"
-#include "nsIDOMDesktopNotification.h"
 #include "mozilla/Preferences.h"
 #include "nsGlobalWindow.h"
-#include "nsIAppsService.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 #include "PermissionMessageUtils.h"
 #include "nsILoadContext.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -68,44 +66,16 @@ uint32_t DesktopNotification::sCount = 0
 
 nsresult
 DesktopNotification::PostDesktopNotification()
 {
   if (!mObserver) {
     mObserver = new AlertServiceObserver(this);
   }
 
-#ifdef MOZ_B2G
-  nsCOMPtr<nsIAppNotificationService> appNotifier =
-    do_GetService("@mozilla.org/system-alerts-service;1");
-  if (appNotifier) {
-    nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
-    uint32_t appId = window ? window->GetDoc()->NodePrincipal()->GetAppId()
-                            : nsIScriptSecurityManager::UNKNOWN_APP_ID;
-
-    if (appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-      nsCOMPtr<nsIAppsService> appsService = do_GetService("@mozilla.org/AppsService;1");
-      nsString manifestUrl = EmptyString();
-      appsService->GetManifestURLByLocalId(appId, manifestUrl);
-      mozilla::AutoSafeJSContext cx;
-      JS::Rooted<JS::Value> val(cx);
-      AppNotificationServiceOptions ops;
-      ops.mTextClickable = true;
-      ops.mManifestURL = manifestUrl;
-
-      if (!ToJSValue(cx, ops, &val)) {
-        return NS_ERROR_FAILURE;
-      }
-
-      return appNotifier->ShowAppNotification(mIconURL, mTitle, mDescription,
-                                              mObserver, val);
-    }
-  }
-#endif
-
   nsCOMPtr<nsIAlertsService> alerts = do_GetService("@mozilla.org/alerts-service;1");
   if (!alerts) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // Generate a unique name (which will also be used as a cookie) because
   // the nsIAlertsService will coalesce notifications with the same name.
   // In the case of IPC, the parent process will use the cookie to map
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -26,17 +26,16 @@
 #include "nsAlertsUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentPermissionHelper.h"
 #include "nsContentUtils.h"
 #include "nsCRTGlue.h"
 #include "nsDOMJSUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIAlertsService.h"
-#include "nsIAppsService.h"
 #include "nsIContentPermissionPrompt.h"
 #include "nsIDocument.h"
 #include "nsILoadContext.h"
 #include "nsINotificationStorage.h"
 #include "nsIPermissionManager.h"
 #include "nsIPermission.h"
 #include "nsIPushService.h"
 #include "nsIScriptSecurityManager.h"
@@ -51,20 +50,16 @@
 #include "nsThreadUtils.h"
 #include "nsToolkitCompsCID.h"
 #include "nsXULAppAPI.h"
 #include "ServiceWorkerManager.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WorkerScope.h"
 
-#ifdef MOZ_B2G
-#include "nsIDOMDesktopNotification.h"
-#endif
-
 namespace mozilla {
 namespace dom {
 
 using namespace workers;
 
 struct NotificationStrings
 {
   const nsString mID;
@@ -1501,25 +1496,16 @@ MainThreadNotificationObserver::Observe(
         // Browser UI may use DOMWebNotificationClicked to focus the tab
         // from which the event was dispatched.
         nsContentUtils::DispatchChromeEvent(doc, window->GetOuterWindow(),
                                             NS_LITERAL_STRING("DOMWebNotificationClicked"),
                                             true, true);
       }
     }
   } else if (!strcmp("alertfinished", aTopic)) {
-    // In b2g-desktop, if the app is closed, closing a notification still
-    // triggers the observer which might be alive even though the owner window
-    // was closed. Keeping this until we remove the close event (Bug 1139363)
-    // from implementation.
-    nsCOMPtr<nsPIDOMWindowInner> window = notification->GetOwner();
-    if (NS_WARN_IF(!window || !window->IsCurrentInnerWindow())) {
-      return NS_ERROR_FAILURE;
-    }
-
     notification->UnpersistNotification();
     notification->mIsClosed = true;
     notification->DispatchTrustedEvent(NS_LITERAL_STRING("close"));
   } else if (!strcmp("alertshow", aTopic)) {
     notification->DispatchTrustedEvent(NS_LITERAL_STRING("show"));
   }
   return NS_OK;
 }
@@ -1779,62 +1765,16 @@ Notification::ShowInternal()
                                                      behavior);
   }
   MOZ_ASSERT(observer);
   nsCOMPtr<nsIObserver> alertObserver = new NotificationObserver(observer,
                                                                  GetPrincipal(),
                                                                  IsInPrivateBrowsing());
 
 
-#ifdef MOZ_B2G
-  nsCOMPtr<nsIAppNotificationService> appNotifier =
-    do_GetService("@mozilla.org/system-alerts-service;1");
-  if (appNotifier) {
-    uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
-    if (mWorkerPrivate) {
-      appId = mWorkerPrivate->GetPrincipal()->GetAppId();
-    } else {
-      nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
-      if (window) {
-        appId = window->GetDoc()->NodePrincipal()->GetAppId();
-      }
-    }
-
-    if (appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-      nsCOMPtr<nsIAppsService> appsService = do_GetService("@mozilla.org/AppsService;1");
-      nsString manifestUrl = EmptyString();
-      nsresult rv = appsService->GetManifestURLByLocalId(appId, manifestUrl);
-      if (NS_SUCCEEDED(rv)) {
-        mozilla::AutoSafeJSContext cx;
-        JS::Rooted<JS::Value> val(cx);
-        AppNotificationServiceOptions ops;
-        ops.mTextClickable = true;
-        ops.mManifestURL = manifestUrl;
-        GetAlertName(ops.mId);
-        ops.mDbId = mID;
-        ops.mDir = DirectionToString(mDir);
-        ops.mLang = mLang;
-        ops.mTag = mTag;
-        ops.mData = mDataAsBase64;
-        ops.mMozbehavior = mBehavior;
-        ops.mMozbehavior.mSoundFile = soundUrl;
-
-        if (!ToJSValue(cx, ops, &val)) {
-          NS_WARNING("Converting dict to object failed!");
-          return;
-        }
-
-        appNotifier->ShowAppNotification(iconUrl, mTitle, mBody,
-                                         alertObserver, val);
-        return;
-      }
-    }
-  }
-#endif
-
   // In the case of IPC, the parent process uses the cookie to map to
   // nsIObserver. Thus the cookie must be unique to differentiate observers.
   nsString uniqueCookie = NS_LITERAL_STRING("notification:");
   uniqueCookie.AppendInt(sCount++);
   bool inPrivateBrowsing = IsInPrivateBrowsing();
 
   bool requireInteraction = mRequireInteraction;
   if (!Preferences::GetBool("dom.webnotifications.requireinteraction.enabled", false)) {
@@ -2359,33 +2299,18 @@ Notification::CloseInternal()
 
 nsresult
 Notification::GetOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
 {
   if (!aPrincipal) {
     return NS_ERROR_FAILURE;
   }
 
-  uint16_t appStatus = aPrincipal->GetAppStatus();
-  uint32_t appId = aPrincipal->GetAppId();
-
-  nsresult rv;
-  if (appStatus == nsIPrincipal::APP_STATUS_NOT_INSTALLED ||
-      appId == nsIScriptSecurityManager::NO_APP_ID ||
-      appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-    rv = nsContentUtils::GetUTFOrigin(aPrincipal, aOrigin);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    // If we are in "app code", use manifest URL as unique origin since
-    // multiple apps can share the same origin but not same notifications.
-    nsCOMPtr<nsIAppsService> appsService =
-      do_GetService("@mozilla.org/AppsService;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    appsService->GetManifestURLByLocalId(appId, aOrigin);
-  }
+  nsresult rv = nsContentUtils::GetUTFOrigin(aPrincipal, aOrigin);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 bool
 Notification::RequireInteraction() const
 {
   return mRequireInteraction;
@@ -2822,32 +2747,17 @@ Notification::Observe(nsISupports* aSubj
     if (SameCOMIdentity(aSubject, window)) {
       nsCOMPtr<nsIObserverService> obs =
         mozilla::services::GetObserverService();
       if (obs) {
         obs->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
         obs->RemoveObserver(this, DOM_WINDOW_FROZEN_TOPIC);
       }
 
-      uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
-      uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
-
-      nsCOMPtr<nsIDocument> doc = window ? window->GetExtantDoc() : nullptr;
-      nsCOMPtr<nsIPrincipal> nodePrincipal = doc ? doc->NodePrincipal() :
-                                             nullptr;
-      if (nodePrincipal) {
-        appStatus = nodePrincipal->GetAppStatus();
-        appId = nodePrincipal->GetAppId();
-      }
-
-      if (appStatus == nsIPrincipal::APP_STATUS_NOT_INSTALLED ||
-          appId == nsIScriptSecurityManager::NO_APP_ID ||
-          appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-        CloseInternal();
-      }
+      CloseInternal();
     }
   }
 
   return NS_OK;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/notification/NotificationDB.jsm
+++ b/dom/notification/NotificationDB.jsm
@@ -30,18 +30,17 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 const NOTIFICATION_STORE_DIR = OS.Constants.Path.profileDir;
 const NOTIFICATION_STORE_PATH =
         OS.Path.join(NOTIFICATION_STORE_DIR, "notificationstore.json");
 
 const kMessages = [
   "Notification:Save",
   "Notification:Delete",
-  "Notification:GetAll",
-  "Notification:GetAllCrossOrigin"
+  "Notification:GetAll"
 ];
 
 var NotificationDB = {
 
   // Ensure we won't call init() while xpcom-shutdown is performed
   _shutdownInProgress: false,
 
   init: function() {
@@ -192,29 +191,16 @@ var NotificationDB = {
           returnMessage("Notification:GetAll:Return:KO", {
             requestID: message.data.requestID,
             origin: message.data.origin,
             errorMsg: error
           });
         });
         break;
 
-      case "Notification:GetAllCrossOrigin":
-        this.queueTask("getallaccrossorigin", message.data).then(
-          function(notifications) {
-            returnMessage("Notification:GetAllCrossOrigin:Return:OK", {
-              notifications: notifications
-            });
-          }).catch(function(error) {
-            returnMessage("Notification:GetAllCrossOrigin:Return:KO", {
-              errorMsg: error
-            });
-          });
-        break;
-
       case "Notification:Save":
         this.queueTask("save", message.data).then(function() {
           returnMessage("Notification:Save:Return:OK", {
             requestID: message.data.requestID
           });
         }).catch(function(error) {
           returnMessage("Notification:Save:Return:KO", {
             requestID: message.data.requestID,
@@ -281,20 +267,16 @@ var NotificationDB = {
     .then(function() {
       var task = this.runningTask;
 
       switch (task.operation) {
         case "getall":
           return this.taskGetAll(task.data);
           break;
 
-        case "getallaccrossorigin":
-          return this.taskGetAllCrossOrigin();
-          break;
-
         case "save":
           return this.taskSave(task.data);
           break;
 
         case "delete":
           return this.taskDelete(task.data);
           break;
       }
@@ -325,41 +307,16 @@ var NotificationDB = {
     if (this.notifications[origin]) {
       for (var i in this.notifications[origin]) {
         notifications.push(this.notifications[origin][i]);
       }
     }
     return Promise.resolve(notifications);
   },
 
-  taskGetAllCrossOrigin: function() {
-    if (DEBUG) { debug("Task, getting all whatever origin"); }
-    var notifications = [];
-    for (var origin in this.notifications) {
-      if (!this.notifications[origin]) {