Merge mozilla-inbound to mozilla-central r=merge a=merge
authorDorel Luca <dluca@mozilla.com>
Thu, 18 Jan 2018 11:43:47 +0200
changeset 454080 abbe0ca5d9693e06484fcb52bbcac189c3461f50
parent 454079 a9f3d83fec60cc212c5b99673b3b25a2403b5839 (current diff)
parent 454078 710b3c4c7a2904b70f11ea83b571dce5ec0e5180 (diff)
child 454081 0a543687fd36bc0dc4188c3d33d117b0a8174721
child 454093 683dbd9a3330d378a950134970e0c7d152f6e0d5
child 454116 7bc2219779f7bec698834234797b09fd16db1051
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.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 mozilla-inbound to mozilla-central r=merge a=merge
layout/painting/RetainedDisplayListBuilder.cpp
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/Scalars.yaml
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -29,21 +29,33 @@ var gEMEHandler = {
       return false;
     }
     if (keySystem == "com.widevine.alpha" &&
         Services.prefs.getPrefType("media.gmp-widevinecdm.visible")) {
       return Services.prefs.getBoolPref("media.gmp-widevinecdm.visible");
     }
     return true;
   },
-  getLearnMoreLink(msgId) {
-    let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel");
+  getEMEDisabledFragment(msgId) {
+    let mainMessage = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.message");
+    let [prefix, suffix] = mainMessage.split(/%(?:\$\d)?S/).map(s => document.createTextNode(s));
+    let text = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.learnMoreLabel");
     let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
-    return "<label class='text-link' href='" + baseURL + "drm-content'>" +
-           text + "</label>";
+    let link = document.createElement("label");
+    link.className = "text-link";
+    link.setAttribute("href", baseURL + "drm-content");
+    link.textContent = text;
+
+    let fragment = document.createDocumentFragment();
+    [prefix, link, suffix].forEach(n => fragment.appendChild(n));
+    return fragment;
+  },
+  getMessageWithBrandName(notificationId) {
+    let msgId = "emeNotifications." + notificationId + ".message";
+    return gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]);
   },
   receiveMessage({target: browser, data: data}) {
     let parsedData;
     try {
       parsedData = JSON.parse(data);
     } catch (ex) {
       Cu.reportError("Malformed EME video message with data: " + data);
       return;
@@ -51,91 +63,75 @@ var gEMEHandler = {
     let {status: status, keySystem: keySystem} = parsedData;
     // Don't need to show if disabled or keysystem not visible.
     if (!this.uiEnabled || !this.isKeySystemVisible(keySystem)) {
       return;
     }
 
     let notificationId;
     let buttonCallback;
-    let params = [];
+    // Notification message can be either a string or a DOM fragment.
+    let notificationMessage;
     switch (status) {
       case "available":
       case "cdm-created":
         // Only show the chain icon for proprietary CDMs. Clearkey is not one.
         if (keySystem != "org.w3.clearkey") {
           this.showPopupNotificationForSuccess(browser, keySystem);
         }
         // ... and bail!
         return;
 
       case "api-disabled":
       case "cdm-disabled":
         notificationId = "drmContentDisabled";
         buttonCallback = gEMEHandler.ensureEMEEnabled.bind(gEMEHandler, browser, keySystem);
-        params = [this.getLearnMoreLink(notificationId)];
+        notificationMessage = this.getEMEDisabledFragment();
         break;
 
       case "cdm-insufficient-version":
         notificationId = "drmContentCDMInsufficientVersion";
-        params = [this._brandShortName];
+        notificationMessage = this.getMessageWithBrandName(notificationId);
         break;
 
       case "cdm-not-installed":
         notificationId = "drmContentCDMInstalling";
-        params = [this._brandShortName];
+        notificationMessage = this.getMessageWithBrandName(notificationId);
         break;
 
       case "cdm-not-supported":
         // Not to pop up user-level notification because they cannot do anything
         // about it.
         return;
       default:
         Cu.reportError(new Error("Unknown message ('" + status + "') dealing with EME key request: " + data));
         return;
     }
 
-    this.showNotificationBar(browser, notificationId, keySystem, params, buttonCallback);
-  },
-  showNotificationBar(browser, notificationId, keySystem, labelParams, callback) {
+    // Now actually create the notification
+
     let box = gBrowser.getNotificationBox(browser);
     if (box.getNotificationWithValue(notificationId)) {
       return;
     }
 
-    let msgPrefix = "emeNotifications." + notificationId + ".";
-    let msgId = msgPrefix + "message";
-
-    let message = labelParams.length ?
-                  gNavigatorBundle.getFormattedString(msgId, labelParams) :
-                  gNavigatorBundle.getString(msgId);
-
     let buttons = [];
-    if (callback) {
+    if (buttonCallback) {
+      let msgPrefix = "emeNotifications." + notificationId + ".";
       let btnLabelId = msgPrefix + "button.label";
       let btnAccessKeyId = msgPrefix + "button.accesskey";
       buttons.push({
         label: gNavigatorBundle.getString(btnLabelId),
         accessKey: gNavigatorBundle.getString(btnAccessKeyId),
-        callback
+        callback: buttonCallback,
       });
     }
 
     let iconURL = "chrome://browser/skin/drm-icon.svg";
-
-    // Do a little dance to get rich content into the notification:
-    let fragment = document.createDocumentFragment();
-    let descriptionContainer = document.createElement("description");
-    // eslint-disable-next-line no-unsanitized/property
-    descriptionContainer.innerHTML = message;
-    while (descriptionContainer.childNodes.length) {
-      fragment.appendChild(descriptionContainer.childNodes[0]);
-    }
-
-    box.appendNotification(fragment, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM,
+    box.appendNotification(notificationMessage, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM,
                            buttons);
   },
   showPopupNotificationForSuccess(browser, keySystem) {
     // We're playing EME content! Remove any "we can't play because..." messages.
     var box = gBrowser.getNotificationBox(browser);
     ["drmContentDisabled",
      "drmContentCDMInstalling"
      ].forEach(function(value) {
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/consoleApi.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/consoleApi.js
@@ -1502,16 +1502,17 @@ stubPackets.set("console.log('foobar', '
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924471,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1528,16 +1529,17 @@ stubPackets.set("console.log(undefined)"
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924479,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1552,16 +1554,17 @@ stubPackets.set("console.warn('danger, w
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "warn",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924487,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1578,16 +1581,17 @@ stubPackets.set("console.log(NaN)", {
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924495,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1604,16 +1608,17 @@ stubPackets.set("console.log(null)", {
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924501,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1628,16 +1633,17 @@ stubPackets.set("console.log('鼬')", {
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924506,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1650,16 +1656,17 @@ stubPackets.set("console.clear()", {
     "arguments": [],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "clear",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924512,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -1677,16 +1684,17 @@ stubPackets.set("console.count('bar')", 
       "count": 1,
       "label": "bar"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924515,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -1724,16 +1732,17 @@ stubPackets.set("console.assert(false, {
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "assert",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924521,
     "timer": null,
     "stacktrace": [
       {
         "columnNumber": 27,
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
@@ -1756,16 +1765,17 @@ stubPackets.set("console.log('hello \nfr
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924528,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1780,16 +1790,17 @@ stubPackets.set("console.log('úṇĩçödê țĕșť')", {
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924586,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1816,16 +1827,17 @@ stubPackets.set("console.dirxml(window)"
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "dirxml",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924596,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -1858,16 +1870,17 @@ stubPackets.set("console.log('myarray', 
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924604,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1892,16 +1905,17 @@ stubPackets.set("console.log('myregex', 
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924610,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -1933,16 +1947,17 @@ stubPackets.set("console.table(['red', '
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "table",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924612,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -1993,16 +2008,17 @@ stubPackets.set("console.log('myobject',
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924614,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2017,16 +2033,17 @@ stubPackets.set("console.debug('debug me
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "debug",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924621,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2041,16 +2058,17 @@ stubPackets.set("console.info('info mess
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "info",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924625,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2065,16 +2083,17 @@ stubPackets.set("console.error('error me
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "error",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924628,
     "timer": null,
     "stacktrace": [
       {
         "columnNumber": 27,
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
@@ -2120,16 +2139,17 @@ stubPackets.set("console.log('mymap')", 
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 5,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924631,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2161,16 +2181,17 @@ stubPackets.set("console.log('myset')", 
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924746,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2183,16 +2204,17 @@ stubPackets.set("console.trace()", {
     "arguments": [],
     "columnNumber": 3,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "testStacktraceFiltering",
     "groupName": "",
     "level": "trace",
     "lineNumber": 3,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924752,
     "timer": null,
     "stacktrace": [
       {
         "columnNumber": 3,
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
         "functionName": "testStacktraceFiltering",
@@ -2227,16 +2249,17 @@ stubPackets.set("console.time('bar')", {
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "time",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924757,
     "timer": {
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev"
@@ -2253,16 +2276,17 @@ stubPackets.set("timerAlreadyExists", {
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "time",
     "lineNumber": 3,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924758,
     "timer": {
       "error": "timerAlreadyExists",
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
@@ -2280,16 +2304,17 @@ stubPackets.set("console.timeEnd('bar')"
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "timeEnd",
     "lineNumber": 4,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924759,
     "timer": {
       "duration": 1.2149999999999181,
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
@@ -2307,16 +2332,17 @@ stubPackets.set("timerDoesntExist", {
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "timeEnd",
     "lineNumber": 5,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924759,
     "timer": {
       "error": "timerDoesntExist",
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
@@ -2334,16 +2360,17 @@ stubPackets.set("console.table('bar')", 
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "table",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924801,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2375,16 +2402,17 @@ stubPackets.set("console.table(['a', 'b'
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "table",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924859,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2399,16 +2427,17 @@ stubPackets.set("console.group('bar')", 
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "bar",
     "level": "group",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924863,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2421,16 +2450,17 @@ stubPackets.set("console.groupEnd('bar')
     "arguments": [],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "bar",
     "level": "groupEnd",
     "lineNumber": 3,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924864,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2445,16 +2475,17 @@ stubPackets.set("console.groupCollapsed(
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "foo",
     "level": "groupCollapsed",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924870,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2467,16 +2498,17 @@ stubPackets.set("console.groupEnd('foo')
     "arguments": [],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "foo",
     "level": "groupEnd",
     "lineNumber": 3,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924871,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2489,16 +2521,17 @@ stubPackets.set("console.group()", {
     "arguments": [],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "group",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [],
     "timeStamp": 1502884924878,
     "timer": null,
     "workerType": "none",
     "category": "webdev"
   }
 });
@@ -2511,16 +2544,17 @@ stubPackets.set("console.groupEnd()", {
     "arguments": [],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "groupEnd",
     "lineNumber": 3,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924879,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2536,16 +2570,17 @@ stubPackets.set("console.log(%cfoobar)",
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "log",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [
       "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
       "color:red;background:url('http://example.com/test')"
     ],
     "timeStamp": 1502884924883,
     "timer": null,
     "workerType": "none",
@@ -2564,16 +2599,17 @@ stubPackets.set("console.group(%cfoo%cba
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "foo bar",
     "level": "group",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [
       "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
       "color:red;background:url('http://example.com/test')"
     ],
     "timeStamp": 1502884924887,
     "timer": null,
     "workerType": "none",
@@ -2589,16 +2625,17 @@ stubPackets.set("console.groupEnd(%cfoo%
     "arguments": [],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "foo bar",
     "level": "groupEnd",
     "lineNumber": 6,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924887,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2614,16 +2651,17 @@ stubPackets.set("console.groupCollapsed(
     ],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "foo baz",
     "level": "groupCollapsed",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "styles": [
       "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
       "color:red;background:url('http://example.com/test')"
     ],
     "timeStamp": 1502884924892,
     "timer": null,
     "workerType": "none",
@@ -2639,16 +2677,17 @@ stubPackets.set("console.groupEnd(%cfoo%
     "arguments": [],
     "columnNumber": 1,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "foo baz",
     "level": "groupEnd",
     "lineNumber": 6,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924893,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2704,16 +2743,17 @@ stubPackets.set("console.dir({C, M, Y, K
     ],
     "columnNumber": 27,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "dir",
     "lineNumber": 1,
+    "prefix": "",
     "private": false,
     "timeStamp": 1502884924899,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2731,16 +2771,17 @@ stubPackets.set("console.count | default
       "count": 1,
       "label": "default"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 2,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913333,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2758,16 +2799,17 @@ stubPackets.set("console.count | default
       "count": 2,
       "label": "default"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 3,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913334,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2785,16 +2827,17 @@ stubPackets.set("console.count | test co
       "count": 1,
       "label": "test counter"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 4,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913334,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2812,16 +2855,17 @@ stubPackets.set("console.count | test co
       "count": 2,
       "label": "test counter"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 5,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913334,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2839,16 +2883,17 @@ stubPackets.set("console.count | default
       "count": 3,
       "label": "default"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 6,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913334,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2861,16 +2906,17 @@ stubPackets.set("console.count | clear",
     "arguments": [],
     "columnNumber": 5,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "clear",
     "lineNumber": 7,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913334,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2888,16 +2934,17 @@ stubPackets.set("console.count | default
       "count": 4,
       "label": "default"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 8,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913335,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
@@ -2915,16 +2962,17 @@ stubPackets.set("console.count | test co
       "count": 3,
       "label": "test counter"
     },
     "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
     "functionName": "triggerPacket",
     "groupName": "",
     "level": "count",
     "lineNumber": 9,
+    "prefix": "",
     "private": false,
     "timeStamp": 1511365913335,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev"
   }
 });
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -12,16 +12,18 @@
 #include "mozilla/Base64.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/IdleDeadline.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
 #include "nsThreadUtils.h"
+#include "mozJSComponentLoader.h"
+#include "GeckoProfiler.h"
 
 namespace mozilla {
 namespace dom {
 
 /* static */ void
 ChromeUtils::NondeterministicGetWeakMapKeys(GlobalObject& aGlobal,
                                             JS::Handle<JS::Value> aMap,
                                             JS::MutableHandle<JS::Value> aRetval,
@@ -368,16 +370,63 @@ ChromeUtils::IdleDispatch(const GlobalOb
   if (aOptions.mTimeout.WasPassed()) {
     aRv = NS_IdleDispatchToCurrentThread(runnable.forget(), aOptions.mTimeout.Value());
   } else {
     aRv = NS_IdleDispatchToCurrentThread(runnable.forget());
   }
 }
 
 /* static */ void
+ChromeUtils::Import(const GlobalObject& aGlobal,
+                    const nsAString& aResourceURI,
+                    const Optional<JS::Handle<JSObject*>>& aTargetObj,
+                    JS::MutableHandle<JSObject*> aRetval,
+                    ErrorResult& aRv)
+{
+
+  RefPtr<mozJSComponentLoader> moduleloader = mozJSComponentLoader::Get();
+  MOZ_ASSERT(moduleloader);
+
+  NS_ConvertUTF16toUTF8 registryLocation(aResourceURI);
+
+  AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(
+    "ChromeUtils::Import", OTHER, registryLocation);
+
+  JSContext* cx = aGlobal.Context();
+  JS::Rooted<JS::Value> targetObj(cx);
+  uint8_t optionalArgc;
+  if (aTargetObj.WasPassed()) {
+    targetObj.setObjectOrNull(aTargetObj.Value());
+    optionalArgc = 1;
+  } else {
+    targetObj.setUndefined();
+    optionalArgc = 0;
+  }
+
+  JS::Rooted<JS::Value> retval(cx);
+  nsresult rv = moduleloader->Import(registryLocation, targetObj, cx,
+                                     optionalArgc, &retval);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  // Import() on the component loader can return NS_OK while leaving an
+  // exception on the JSContext.  Check for that case.
+  if (JS_IsExceptionPending(cx)) {
+    aRv.NoteJSContextException(cx);
+    return;
+  }
+
+  // Now we better have an object.
+  MOZ_ASSERT(retval.isObject());
+  aRetval.set(&retval.toObject());
+}
+
+/* static */ void
 ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
                                       const dom::OriginAttributesDictionary& aAttrs,
                                       nsCString& aSuffix)
 
 {
   OriginAttributes attrs(aAttrs);
   attrs.CreateSuffix(aSuffix);
 }
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -149,14 +149,20 @@ public:
                            const IdleRequestOptions& options,
                            ErrorResult& aRv);
 
   static void GetRecentJSDevError(GlobalObject& aGlobal,
                                   JS::MutableHandleValue aRetval,
                                   ErrorResult& aRv);
 
   static void ClearRecentJSDevError(GlobalObject& aGlobal);
+
+  static void Import(const GlobalObject& aGlobal,
+                     const nsAString& aResourceURI,
+                     const Optional<JS::Handle<JSObject*>>& aTargetObj,
+                     JS::MutableHandle<JSObject*> aRetval,
+                     ErrorResult& aRv);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ChromeUtils__
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -439,16 +439,17 @@ LOCAL_INCLUDES += [
     '/dom/u2f',
     '/dom/workers',
     '/dom/xbl',
     '/dom/xml',
     '/dom/xslt/xpath',
     '/dom/xul',
     '/gfx/2d',
     '/image',
+    '/js/xpconnect/loader',
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
     '/layout/base',
     '/layout/forms',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
     '/layout/xul',
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -1532,16 +1532,17 @@ Console::PopulateConsoleNotificationInTh
     // mConsoleEventNotifier.
     event.mID.Value().SetAsUnsignedLongLong() = 0;
     event.mInnerID.Value().SetAsUnsignedLongLong() = 0;
   }
 
   event.mConsoleID = mConsoleID;
   event.mLevel = aData->mMethodString;
   event.mFilename = frame.mFilename;
+  event.mPrefix = mPrefix;
 
   nsCOMPtr<nsIURI> filenameURI;
   nsAutoCString pass;
   if (NS_IsMainThread() &&
       NS_SUCCEEDED(NS_NewURI(getter_AddRefs(filenameURI), frame.mFilename)) &&
       NS_SUCCEEDED(filenameURI->GetPassword(pass)) && !pass.IsEmpty()) {
     nsCOMPtr<nsISensitiveInfoHiddenURI> safeURI = do_QueryInterface(filenameURI);
     nsAutoCString spec;
@@ -2597,18 +2598,18 @@ Console::MaybeExecuteDumpFunction(JSCont
     return;
   }
 
   nsAutoString message;
   message.AssignLiteral("console.");
   message.Append(aMethodName);
   message.AppendLiteral(": ");
 
-  if (!mDumpPrefix.IsEmpty()) {
-    message.Append(mDumpPrefix);
+  if (!mPrefix.IsEmpty()) {
+    message.Append(mPrefix);
     message.AppendLiteral(": ");
   }
 
   for (uint32_t i = 0; i < aData.Length(); ++i) {
     JS::Rooted<JS::Value> v(aCx, aData[i]);
     JS::Rooted<JSString*> jsString(aCx, JS_ValueToSource(aCx, v));
     if (!jsString) {
       continue;
@@ -2635,18 +2636,18 @@ Console::MaybeExecuteDumpFunctionForTrac
 {
   if (!aStack || (!mDumpFunction && !mDumpToStdout)) {
     return;
   }
 
   nsAutoString message;
   message.AssignLiteral("console.trace:\n");
 
-  if (!mDumpPrefix.IsEmpty()) {
-    message.Append(mDumpPrefix);
+  if (!mPrefix.IsEmpty()) {
+    message.Append(mPrefix);
     message.AppendLiteral(": ");
   }
 
   nsCOMPtr<nsIStackFrame> stack(aStack);
 
   while (stack) {
     nsAutoString filename;
     nsresult rv = stack->GetFilename(aCx, filename);
--- a/dom/console/Console.h
+++ b/dom/console/Console.h
@@ -439,17 +439,17 @@ private:
   uint64_t mOuterID;
   uint64_t mInnerID;
 
   // Set only by ConsoleInstance:
   nsString mConsoleID;
   nsString mPassedInnerID;
   RefPtr<ConsoleInstanceDumpCallback> mDumpFunction;
   bool mDumpToStdout;
-  nsString mDumpPrefix;
+  nsString mPrefix;
   bool mChromeInstance;
   ConsoleLogLevel mMaxLogLevel;
 
   enum {
     eUnknown,
     eInitialized,
     eShuttingDown
   } mStatus;
--- a/dom/console/ConsoleInstance.cpp
+++ b/dom/console/ConsoleInstance.cpp
@@ -74,17 +74,17 @@ ConsoleInstance::ConsoleInstance(const C
 
   if (aOptions.mDump.WasPassed()) {
     mConsole->mDumpFunction = &aOptions.mDump.Value();
   } else {
     // For historical reasons, ConsoleInstance prints messages on stdout.
     mConsole->mDumpToStdout = true;
   }
 
-  mConsole->mDumpPrefix = aOptions.mPrefix;
+  mConsole->mPrefix = aOptions.mPrefix;
 
   // Let's inform that this is a custom instance.
   mConsole->mChromeInstance = true;
 
   if (aOptions.mMaxLogLevel.WasPassed()) {
     mConsole->mMaxLogLevel = aOptions.mMaxLogLevel.Value();
   }
 
--- a/dom/console/tests/test_jsm.xul
+++ b/dom/console/tests/test_jsm.xul
@@ -33,29 +33,32 @@ consoleListener.prototype  = {
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "console-api-log-event") {
       var obj = aSubject.wrappedJSObject;
       if (obj.innerID == JSM) {
         is(obj.ID, "jsm", "ID and InnerID are correctly set.");
         is(obj.arguments[0], "Hello world!", "Message matches");
         is(obj.consoleID, "", "No consoleID for console API");
+        is(obj.prefix, "", "prefix is empty by default");
 
         // We want to see 2 messages from this innerID, the first is generated
         // by console.log, the second one from createInstance().log();
         ++this.count;
       } else if (obj.innerID == "CUSTOM INNER") {
         is(obj.ID, "jsm", "ID and InnerID are correctly set.");
         is(obj.arguments[0], "Hello world!", "Message matches");
         is(obj.consoleID, "wow", "consoleID is set by consoleInstance");
+        is(obj.prefix, "_PREFIX_", "prefix is set by consoleInstance");
         ++this.count;
       } else if (obj.innerID == "LEVEL") {
         // Nothing special... just we don't want to see 'invisible' messages.
         is(obj.ID, "jsm", "ID and InnerID are correctly set.");
         is(obj.arguments[0], "Hello world!", "Message matches");
+        is(obj.prefix, "", "prefix is empty by default");
         ++this.count;
       }
 
       if (this.count == 4) {
         is(dumpCalled, 2, "Dump has been called!");
         SpecialPowers.removeObserver(this, "console-api-log-event");
         SimpleTest.finish();
       }
--- a/dom/webidl/ChromeUtils.webidl
+++ b/dom/webidl/ChromeUtils.webidl
@@ -229,16 +229,43 @@ partial namespace ChromeUtils {
   /**
    * Dispatches the given callback to the main thread when it would be
    * otherwise idle. Similar to Window.requestIdleCallback, but not bound to a
    * particular DOM windw.
    */
   [Throws]
   void idleDispatch(IdleRequestCallback callback,
                     optional IdleRequestOptions options);
+
+  /**
+   * Synchronously loads and evaluates the js file located at
+   * 'aResourceURI' with a new, fully privileged global object.
+   *
+   * If 'aTargetObj' is specified and null, this method just returns
+   * the module's global object. Otherwise (if 'aTargetObj' is not
+   * specified, or 'aTargetObj' is != null) looks for a property
+   * 'EXPORTED_SYMBOLS' on the new global object. 'EXPORTED_SYMBOLS'
+   * is expected to be an array of strings identifying properties on
+   * the global object.  These properties will be installed as
+   * properties on 'targetObj', or, if 'aTargetObj' is not specified,
+   * on the caller's global object. If 'EXPORTED_SYMBOLS' is not
+   * found, an error is thrown.
+   *
+   * @param aResourceURI A resource:// URI string to load the module from.
+   * @param aTargetObj the object to install the exported properties on or null.
+   * @returns the module code's global object.
+   *
+   * The implementation maintains a hash of aResourceURI->global obj.
+   * Subsequent invocations of import with 'aResourceURI' pointing to
+   * the same file will not cause the module to be re-evaluated, but
+   * the symbols in EXPORTED_SYMBOLS will be exported into the
+   * specified target object and the global object returned as above.
+   */
+  [Throws]
+  object import(DOMString aResourceURI, optional object? aTargetObj);
 };
 
 /**
  * Used by principals and the script security manager to represent origin
  * attributes. The first dictionary is designed to contain the full set of
  * OriginAttributes, the second is used for pattern-matching (i.e. does this
  * OriginAttributesDictionary match the non-empty attributes in this pattern).
  *
--- a/dom/webidl/Console.webidl
+++ b/dom/webidl/Console.webidl
@@ -73,16 +73,17 @@ dictionary ConsoleEvent {
   // lazily.  Note that we're not making this whole thing an interface because
   // consumers expect to see own properties on it, which would mean making the
   // props unforgeable, which means lots of JSFunction allocations.  Maybe we
   // should fix those consumers, of course....
   // sequence<ConsoleStackEntry> stacktrace;
   DOMString groupName = "";
   any timer = null;
   any counter = null;
+  DOMString prefix = "";
 };
 
 // Event for profile operations
 dictionary ConsoleProfileEvent {
   DOMString action = "";
   sequence<any> arguments;
 };
 
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -749,16 +749,22 @@ GLContext::InitWithPrefixImpl(const char
         // this has been fixed in Mac OS X 10.9. See 907946
         // and it also works in 10.8.3 and higher.  See 1094338.
         if (Vendor() == gl::GLVendor::NVIDIA &&
             !nsCocoaFeatures::IsAtLeastVersion(10,8,3))
         {
             MarkUnsupported(GLFeature::depth_texture);
         }
 #endif
+
+        const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
+        if (strstr(versionStr, "Mesa")) {
+            // DrawElementsInstanced hangs the driver.
+            MarkUnsupported(GLFeature::robust_buffer_access_behavior);
+        }
     }
 
     if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
         MOZ_ASSERT((mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
                    "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
                    " being available!");
     }
 
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -8,21 +8,41 @@
 
 #include "mozilla/layers/ImageClient.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "mozilla/layers/WebRenderMessages.h"
 #include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/SharedSurfacesChild.h"
 #include "nsDisplayListInvalidation.h"
+#include "nsIFrame.h"
 #include "WebRenderCanvasRenderer.h"
 
 namespace mozilla {
 namespace layers {
 
+/* static */ bool
+WebRenderUserData::SupportsAsyncUpdate(nsIFrame* aFrame)
+{
+  if (!aFrame ||
+      !aFrame->HasProperty(nsIFrame::WebRenderUserDataProperty())) {
+    return false;
+  }
+  RefPtr<WebRenderUserData> data;
+  nsIFrame::WebRenderUserDataTable* userDataTable =
+    aFrame->GetProperty(nsIFrame::WebRenderUserDataProperty());
+
+  userDataTable->Get(static_cast<uint32_t>(DisplayItemType::TYPE_VIDEO), getter_AddRefs(data));
+  if (data && data->AsImageData()) {
+    return data->AsImageData()->IsAsync();
+  }
+
+  return false;
+}
+
 WebRenderUserData::WebRenderUserData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
   : mWRManager(aWRManager)
   , mFrame(aItem->Frame())
   , mDisplayItemKey(aItem->GetPerFrameKey())
   , mTable(aWRManager->GetWebRenderUserDataTable())
   , mUsed(false)
 {
 }
@@ -52,17 +72,17 @@ WebRenderUserData::WrBridge() const
 WebRenderImageData::WebRenderImageData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
   : WebRenderUserData(aWRManager, aItem)
   , mOwnsKey(false)
 {
 }
 
 WebRenderImageData::~WebRenderImageData()
 {
-  ClearCachedResources();
+  DoClearCachedResources();
 }
 
 void
 WebRenderImageData::ClearImageKey()
 {
   if (mKey) {
     // If we don't own the key, then the owner is responsible for discarding the
     // key when appropriate.
@@ -72,16 +92,22 @@ WebRenderImageData::ClearImageKey()
     mKey.reset();
   }
   mOwnsKey = false;
 }
 
 void
 WebRenderImageData::ClearCachedResources()
 {
+  DoClearCachedResources();
+}
+
+void
+WebRenderImageData::DoClearCachedResources()
+{
   ClearImageKey();
 
   if (mExternalImageId) {
     WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
     mExternalImageId.reset();
   }
 
   if (mPipelineId) {
@@ -254,16 +280,24 @@ WebRenderFallbackData::WebRenderFallback
   , mInvalid(false)
 {
 }
 
 WebRenderFallbackData::~WebRenderFallbackData()
 {
 }
 
+void
+WebRenderFallbackData::ClearCachedResources()
+{
+  WebRenderImageData::ClearCachedResources();
+  mBasicLayerManager = nullptr;
+  mInvalid = true;
+}
+
 nsDisplayItemGeometry*
 WebRenderFallbackData::GetGeometry()
 {
   return mGeometry.get();
 }
 
 void
 WebRenderFallbackData::SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
@@ -291,22 +325,28 @@ WebRenderAnimationData::~WebRenderAnimat
 
 WebRenderCanvasData::WebRenderCanvasData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
   : WebRenderUserData(aWRManager, aItem)
 {
 }
 
 WebRenderCanvasData::~WebRenderCanvasData()
 {
-  ClearCachedResources();
+  DoClearCachedResources();
 }
 
 void
 WebRenderCanvasData::ClearCachedResources()
 {
+  DoClearCachedResources();
+}
+
+void
+WebRenderCanvasData::DoClearCachedResources()
+{
   if (mCanvasRenderer) {
     mCanvasRenderer->ClearCachedResources();
   }
 }
 
 void
 WebRenderCanvasData::ClearCanvasRenderer()
 {
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -8,16 +8,17 @@
 #define GFX_WEBRENDERUSERDATA_H
 
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/layers/AnimationInfo.h"
 
 class nsDisplayItemGeometry;
+class nsIFrame;
 
 namespace mozilla {
 namespace wr {
 class IpcResourceUpdateQueue;
 }
 
 namespace layers {
 class CanvasLayer;
@@ -30,16 +31,18 @@ class WebRenderImageData;
 class WebRenderFallbackData;
 class WebRenderLayerManager;
 
 class WebRenderUserData
 {
 public:
   typedef nsTHashtable<nsRefPtrHashKey<WebRenderUserData> > WebRenderUserDataRefTable;
 
+  static bool SupportsAsyncUpdate(nsIFrame* aFrame);
+
   NS_INLINE_DECL_REFCOUNTING(WebRenderUserData)
 
   WebRenderUserData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem);
 
   virtual WebRenderImageData* AsImageData() { return nullptr; }
   virtual WebRenderFallbackData* AsFallbackData() { return nullptr; }
   virtual WebRenderCanvasData* AsCanvasData() { return nullptr; }
 
@@ -96,19 +99,26 @@ public:
                                          const gfx::Matrix4x4& aSCTransform,
                                          const gfx::MaybeIntSize& aScaleToSize,
                                          const wr::ImageRendering& aFilter,
                                          const wr::MixBlendMode& aMixBlendMode,
                                          bool aIsBackfaceVisible);
 
   void CreateImageClientIfNeeded();
   void ClearCachedResources() override;
+
+  bool IsAsync()
+  {
+    return mPipelineId.isSome();
+  }
+
 protected:
   void ClearImageKey();
   void CreateExternalImageIfNeeded();
+  void DoClearCachedResources();
 
   wr::MaybeExternalImageId mExternalImageId;
   Maybe<wr::ImageKey> mKey;
   RefPtr<ImageClient> mImageClient;
   Maybe<wr::PipelineId> mPipelineId;
   RefPtr<ImageContainer> mContainer;
   bool mOwnsKey;
 };
@@ -117,16 +127,17 @@ class WebRenderFallbackData : public Web
 {
 public:
   explicit WebRenderFallbackData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem);
   virtual ~WebRenderFallbackData();
 
   virtual WebRenderFallbackData* AsFallbackData() override { return this; }
   virtual UserDataType GetType() override { return UserDataType::eFallback; }
   static UserDataType Type() { return UserDataType::eFallback; }
+  void ClearCachedResources() override;
   nsDisplayItemGeometry* GetGeometry() override;
   void SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
   nsRect GetBounds() { return mBounds; }
   void SetBounds(const nsRect& aRect) { mBounds = aRect; }
   void SetInvalid(bool aInvalid) { mInvalid = aInvalid; }
   void SetScale(gfx::Size aScale) { mScale = aScale; }
   gfx::Size GetScale() { return mScale; }
   bool IsInvalid() { return mInvalid; }
@@ -163,15 +174,17 @@ public:
   virtual UserDataType GetType() override { return UserDataType::eCanvas; }
   static UserDataType Type() { return UserDataType::eCanvas; }
 
   void ClearCanvasRenderer();
   WebRenderCanvasRendererAsync* GetCanvasRenderer();
   WebRenderCanvasRendererAsync* CreateCanvasRenderer();
   void ClearCachedResources() override;
 protected:
+  void DoClearCachedResources();
+
   UniquePtr<WebRenderCanvasRendererAsync> mCanvasRenderer;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERUSERDATA_H */
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2010,17 +2010,17 @@ gfxFont::DrawMissingGlyph(const TextRunD
                  height, advanceDevUnits) :
             Rect(pt.x, pt.y - height,
                  advanceDevUnits, height);
 
         // If there's a fake-italic skew in effect as part
         // of the drawTarget's transform, we need to undo
         // this before drawing the hexbox. (Bug 983985)
         gfxContextMatrixAutoSaveRestore matrixRestore;
-        if (aFontParams.needsOblique && !textDrawer) {
+        if (aFontParams.needsOblique && !aFontParams.isVerticalFont && !textDrawer) {
             matrixRestore.SetContext(aRunParams.context);
             gfx::Matrix mat =
                 aRunParams.context->CurrentMatrix().
                 PreTranslate(pt).
                 PreMultiply(gfx::Matrix(1, 0, OBLIQUE_SKEW_FACTOR, 1, 0, 0)).
                 PreTranslate(-pt);
             aRunParams.context->SetMatrix(mat);
         }
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -963,16 +963,18 @@ xpc::GlobalProperties::Parse(JSContext* 
         } else if (!strcmp(name.ptr(), "caches")) {
             caches = true;
         } else if (!strcmp(name.ptr(), "FileReader")) {
             fileReader = true;
         } else if (!strcmp(name.ptr(), "MessageChannel")) {
             messageChannel = true;
         } else if (!strcmp(name.ptr(), "InspectorUtils")) {
             inspectorUtils = true;
+        } else if (!strcmp(name.ptr(), "ChromeUtils")) {
+            ChromeUtils = true;
         } else {
             JS_ReportErrorUTF8(cx, "Unknown property name: %s", name.ptr());
             return false;
         }
     }
     return true;
 }
 
@@ -1052,16 +1054,19 @@ xpc::GlobalProperties::Define(JSContext*
         (!dom::MessageChannelBinding::GetConstructorObject(cx) ||
          !dom::MessagePortBinding::GetConstructorObject(cx)))
         return false;
 
     if (inspectorUtils &&
         !dom::InspectorUtilsBinding::GetConstructorObject(cx))
         return false;
 
+    if (ChromeUtils && !dom::ChromeUtilsBinding::GetConstructorObject(cx))
+        return false;
+
     return true;
 }
 
 bool
 xpc::GlobalProperties::DefineInXPCComponents(JSContext* cx, JS::HandleObject obj)
 {
     if (indexedDB &&
         !IndexedDatabaseManager::DefineIndexedDB(cx, obj))
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2693,16 +2693,17 @@ struct GlobalProperties {
     bool Directory : 1;
     bool File : 1;
     bool crypto : 1;
     bool rtcIdentityProvider : 1;
     bool fetch : 1;
     bool caches : 1;
     bool fileReader: 1;
     bool messageChannel: 1;
+    bool ChromeUtils : 1;
     bool inspectorUtils : 1;
 private:
     bool Define(JSContext* cx, JS::HandleObject obj);
 };
 
 // Infallible.
 already_AddRefed<nsIXPCComponents_utils_Sandbox>
 NewSandboxConstructor();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -7218,16 +7218,23 @@ nsIFrame::InvalidateLayer(DisplayItemTyp
 {
   NS_ASSERTION(aDisplayItemKey > DisplayItemType::TYPE_ZERO, "Need a key");
 
   Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
 
   nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
   InvalidateRenderingObservers(displayRoot, this);
 
+  // Check if frame supports WebRender's async update
+  if ((aFlags & UPDATE_IS_ASYNC) &&
+      WebRenderUserData::SupportsAsyncUpdate(this)) {
+    // WebRender does not use layer, then return nullptr.
+    return nullptr;
+  }
+
   // If the layer is being updated asynchronously, and it's being forwarded
   // to a compositor, then we don't need to invalidate.
   if ((aFlags & UPDATE_IS_ASYNC) && layer && layer->SupportsAsyncUpdate()) {
     return layer;
   }
 
   if (!layer) {
     if (aFrameDamageRect && aFrameDamageRect->IsEmpty()) {
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -981,16 +981,23 @@ nsInlineFrame::UpdateStyleOfOwnedAnonBox
     // We don't want to just walk through using GetNextContinuationWithSameStyle
     // here, because we want to set updated style contexts on both our
     // ib-sibling blocks and inlines.
     for (nsIFrame* cont = blockFrame; cont; cont = cont->GetNextContinuation()) {
       cont->SetStyleContext(newContext);
     }
 
     nsIFrame* nextInline = blockFrame->GetProperty(nsIFrame::IBSplitSibling());
+
+    // This check is here due to bug 1431232.  Please remove it once
+    // that bug is fixed.
+    if (MOZ_UNLIKELY(!nextInline)) {
+      break;
+    }
+
     MOZ_ASSERT(nextInline, "There is always a trailing inline in an IB split");
 
     for (nsIFrame* cont = nextInline; cont; cont = cont->GetNextContinuation()) {
       cont->SetStyleContext(ourStyle);
     }
     blockFrame = nextInline->GetProperty(nsIFrame::IBSplitSibling());
   }
 }
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -1223,16 +1223,17 @@ class PackageFrontend(MachCommandBase):
             unpack_file,
         )
         from requests.adapters import HTTPAdapter
         import redo
         import requests
         import shutil
 
         from taskgraph.generator import load_graph_config, Kind
+        from taskgraph.parameters import Parameters
         from taskgraph.util.taskcluster import (
             get_artifact_url,
             list_artifacts,
         )
         import yaml
 
         self._set_log_level(verbose)
         # Normally, we'd use self.log_manager.enable_unstructured(),
@@ -1346,17 +1347,17 @@ class PackageFrontend(MachCommandBase):
                 'pushlog_id': 0,
                 'owner': '',
             }
 
             # TODO: move to the taskcluster package
             def tasks(kind_name):
                 root_path = mozpath.join(self.topsrcdir, 'taskcluster', 'ci')
                 graph_config = load_graph_config(root_path)
-                tasks = Kind.load(root_path, graph_config, kind_name).load_tasks(params, {})
+                tasks = Kind.load(root_path, graph_config, kind_name).load_tasks(Parameters(**params), {})
                 return {
                     task.task['metadata']['name']: task
                     for task in tasks
                 }
 
             toolchains = tasks('toolchain')
 
             aliases = {}
--- a/testing/mozharness/mozharness/mozilla/testing/talos.py
+++ b/testing/mozharness/mozharness/mozilla/testing/talos.py
@@ -418,35 +418,38 @@ class Talos(TestingMixin, MercurialScrip
                     unzip = self.query_exe('unzip')
                     unzip_cmd = [unzip, '-q', '-o', archive, '-d', src_talos_pageset]
                     self.run_command(unzip_cmd, halt_on_failure=True)
                 else:
                     self.info("pageset already available")
             else:
                 self.info("Not downloading pageset because the no-download option was specified")
 
-        # if running speedometer locally, need to copy speedometer source into talos/tests
-        if self.config.get('run_local') and 'speedometer' in self.suite:
-            self.get_speedometer_source()
+        # if running webkit tests locally, need to copy webkit source into talos/tests
+        if self.config.get('run_local') and ('speedometer' in self.suite or
+           'stylebench' in self.suite or
+           'motionmark' in self.suite):
+            self.get_webkit_source()
 
-    def get_speedometer_source(self):
-        # in production the build system auto copies speedometer source into place;
+    def get_webkit_source(self):
+        # in production the build system auto copies webkit source into place;
         # but when run locally we need to do this manually, so that talos can find it
         src = os.path.join(self.repo_path, 'third_party', 'webkit',
-                                 'PerformanceTests', 'Speedometer')
+                                 'PerformanceTests')
         dest = os.path.join(self.talos_path, 'talos', 'tests', 'webkit',
-                                      'PerformanceTests', 'Speedometer')
-        if not os.path.exists(dest):
-            self.info("Copying speedometer source from %s to %s" % (src, dest))
-            try:
-                shutil.copytree(src, dest)
-            except:
-                self.critical("Error copying speedometer source from %s to %s" % (src, dest))
-        else:
-            self.info("Speedometer source already found at %s" % dest)
+                                      'PerformanceTests')
+
+        if os.path.exists(dest):
+            shutil.rmtree(dest)
+
+        self.info("Copying webkit benchmarks from %s to %s" % (src, dest))
+        try:
+            shutil.copytree(src, dest)
+        except:
+            self.critical("Error copying webkit benchmarks from %s to %s" % (src, dest))
 
     def setup_mitmproxy(self):
         """Some talos tests require the use of mitmproxy to playback the pages,
         set it up here.
         """
         if not self.query_mitmproxy_recording_set():
             self.info("Skipping: mitmproxy is not required")
             return
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -79,17 +79,17 @@
         "perf-reftest-singletons-e10s": {
             "tests": ["perf_reftest_singletons"]
         },
         "perf-reftest-singletons-stylo-disabled-e10s": {
             "tests": ["perf_reftest_singletons"],
             "talos_options": ["--disable-stylo"]
         },
         "speedometer-e10s": {
-            "tests": ["speedometer"]
+            "tests": ["speedometer", "stylebench"]
         },
         "speedometer-stylo-disabled-e10s": {
             "talos_options": ["--disable-stylo"],
             "tests": ["speedometer"]
         },
         "tp5o-e10s": {
             "tests": ["tp5o"],
             "pagesets_name": "tp5n.zip"
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -839,16 +839,31 @@ class speedometer(PageloaderTest):
     tpmozafterpaint = False
     tpchrome = False
     format_pagename = False
     lower_is_better = False
     unit = 'score'
 
 
 @register_test()
+class stylebench(PageloaderTest):
+    """
+    StyleBench benchmark used by many browser vendors (from webkit)
+    """
+    tpmanifest = '${talos}/tests/stylebench/stylebench.manifest'
+    tpcycles = 1
+    tppagecycles = 5
+    tpmozafterpaint = False
+    tpchrome = False
+    format_pagename = False
+    lower_is_better = False
+    unit = 'score'
+
+
+@register_test()
 class perf_reftest(PageloaderTest):
     """
     Style perf-reftest a set of tests where the result is the difference of base vs ref pages
     """
     base_vs_ref = True  # compare the two test pages with eachother and report comparison
     tpmanifest = '${talos}/tests/perf-reftest/perf_reftest.manifest'
     tpcycles = 1
     tppagecycles = 10
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/stylebench/stylebench.manifest
@@ -0,0 +1,1 @@
+% http://localhost/tests/webkit/PerformanceTests/StyleBench/index.html?gecko
--- a/third_party/webkit/PerformanceTests/StyleBench/index.html
+++ b/third_party/webkit/PerformanceTests/StyleBench/index.html
@@ -1,24 +1,27 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
 <html>
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <title>StyleBench 0.1</title>
     <link rel="stylesheet" href="../Speedometer/resources/main.css">
     <script src="../Speedometer/resources/main.js" defer></script>
     <script src="../Speedometer/resources/benchmark-runner.js" defer></script>
     <script src="../Speedometer/resources/benchmark-report.js" defer></script>
     <script src="../resources/statistics.js" defer></script>
     <script src="resources/style-bench.js" defer></script>
     <script src="resources/tests.js" defer></script>
     <script>
         addEventListener('load', () => {
             if (!window.location.protocol.startsWith('http'))
                 showSection('local-message', false);
+
+            if (location.search("?gecko"))
+                startTest();
         });
     </script>
 </head>
 <body>
 <main>
     <a id="logo-link" href="javascript:showHome()"></a>
 
     <section id="home" class="selected">
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1254,34 +1254,32 @@
     "alert_emails": ["mds@mozilla.com"],
     "expires_in_version": "60",
     "kind": "boolean",
     "bug_numbers": [1255198],
     "description": "This metric is recorded every time a navigator.geolocation.watchPosition() request gets allowed/fulfilled. A false value is recorded if the owner is not visible according to document.isVisible."
   },
   "GPU_PROCESS_LAUNCH_TIME_MS_2" : {
     "record_in_processes": ["main", "content"],
-    "alert_emails": ["danderson@mozilla.com"],
-    "expires_in_version": "never",
+    "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"],
+    "expires_in_version": "66",
     "bug_numbers": [1297790, 1317796],
     "kind": "exponential",
     "high": 64000,
     "n_buckets": 100,
-    "releaseChannelCollection": "opt-out",
     "description": "GPU process launch time in milliseconds"
   },
   "GPU_PROCESS_INITIALIZATION_TIME_MS" : {
     "record_in_processes": ["main", "content", "gpu"],
-    "alert_emails": ["danderson@mozilla.com"],
-    "expires_in_version": "never",
+    "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"],
+    "expires_in_version": "66",
     "bug_numbers": [1324095],
     "kind": "exponential",
     "high": 64000,
     "n_buckets": 100,
-    "releaseChannelCollection": "opt-out",
     "description": "GPU process initialization (excluding XPCOM and fork time) time in milliseconds"
   },
   "GPU_PROCESS_CRASH_FALLBACKS": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["cpearce@mozilla.com", "gsquelart@mozilla.com"],
     "expires_in_version": "60",
     "bug_numbers": [1338011],
     "kind": "enumerated",
@@ -12255,17 +12253,17 @@
     "alert_emails": ["push@mozilla.com"],
     "expires_in_version": "60",
     "kind": "count",
     "description": "Number of push messages that were successfully decrypted and delivered to a ServiceWorker."
   },
   "D3D11_SYNC_HANDLE_FAILURE": {
     "record_in_processes": ["main", "content", "gpu"],
     "alert_emails": ["gfx-telemetry-alerts@mozilla.com","bschouten@mozilla.com","danderson@mozilla.com","msreckovic@mozilla.com","ashughes@mozilla.com"],
-    "expires_in_version": "60",
+    "expires_in_version": "66",
     "releaseChannelCollection": "opt-out",
     "kind": "count",
     "description": "Number of times the D3D11 compositor failed to get a texture sync handle."
   },
   "GFX_CONTENT_FAILED_TO_ACQUIRE_DEVICE": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"],
     "expires_in_version": "never",
@@ -12440,17 +12438,17 @@
     "bug_numbers": [1219030],
     "expires_in_version": "60",
     "kind": "enumerated",
     "n_values": 10,
     "description": "Number of origins with the web notifications permission (0 = denied, 1 = allowed)."
   },
   "PLUGIN_DRAWING_MODEL": {
     "record_in_processes": ["main", "content"],
-    "alert_emails": ["danderson@mozilla.com"],
+    "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "bug_numbers": [1229961],
     "n_values": 12,
     "description": "Plugin drawing model. 0 when windowed, otherwise NPDrawingModel + 1."
   },
   "DOM_SCRIPT_SRC_ENCODING": {
     "record_in_processes": ["main", "content"],
@@ -12619,17 +12617,17 @@
     "kind": "linear",
     "high": 100,
     "n_buckets": 50,
     "bug_numbers": [1238433],
     "description": "Percentage of frames decoded frames dropped in an HTMLVideoElement"
   },
   "MEDIA_DECODER_BACKEND_USED": {
     "record_in_processes": ["main", "content", "gpu"],
-    "alert_emails": ["danderson@mozilla.com"],
+    "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"],
     "bug_numbers": [1259695],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 10,
     "description": "Media decoder backend (0=WMF Software, 1=DXVA2D3D9, 2=DXVA2D3D11)"
   },
   "IPC_MESSAGE_SIZE2": {
     "record_in_processes": ["main", "content", "gpu"],
@@ -13013,29 +13011,29 @@
     "expires_in_version": "58",
     "kind": "exponential",
     "high": 50000,
     "n_buckets": 100,
     "description": "Time in milliseconds from the first non-blank paint to the creation time of the next click, key, mouse or scroll event per top-level content browsing context."
   },
   "CONTENT_PAINT_TIME": {
     "record_in_processes": ["main", "content"],
-    "alert_emails": ["danderson@mozilla.com","gfx-telemetry-alerts@mozilla.com"],
+    "alert_emails": ["mwoodrow@mozilla.com","gfx-telemetry-alerts@mozilla.com"],
     "bug_numbers": [1309442],
-    "expires_in_version": "60",
+    "expires_in_version": "66",
     "kind": "exponential",
     "high": 1000,
     "n_buckets": 50,
     "description": "Time spent in the paint pipeline for content."
   },
   "CONTENT_LARGE_PAINT_PHASE_WEIGHT": {
     "record_in_processes": ["main", "content"],
-    "alert_emails": ["danderson@mozilla.com","gfx-telemetry-alerts@mozilla.com"],
+    "alert_emails": ["mwoodrow@mozilla.com","gfx-telemetry-alerts@mozilla.com"],
     "bug_numbers": [1309442],
-    "expires_in_version": "60",
+    "expires_in_version": "66",
     "keyed": true,
     "kind": "linear",
     "high": 100,
     "n_buckets": 10,
     "description": "Percentage of time taken by phases in expensive content paints."
   },
   "NARRATE_CONTENT_BY_LANGUAGE_2": {
     "record_in_processes": ["main", "content"],
@@ -13836,18 +13834,18 @@
     "high": 300000,
     "n_buckets": 22,
     "keyed": true,
     "bug_numbers": [1341569],
     "description": "Milliseconds between starting to fill an autofill-eligible form field and submitting the form, keyed by the combination of form type and filling type."
   },
   "GFX_OMTP_PAINT_WAIT_TIME": {
     "record_in_processes": ["content"],
-    "alert_emails": ["gfx-telemetry-alerts@mozilla.com","danderson@mozilla.com"],
-    "expires_in_version": "61",
+    "alert_emails": ["gfx-telemetry-alerts@mozilla.com","rhunt@mozilla.com"],
+    "expires_in_version": "66",
     "kind": "exponential",
     "high": 200,
     "n_buckets": 50,
     "description": "Amount of time in milliseconds the main thread spends waiting for the paint thread to complete, if the time was greater than 200us.",
     "bug_numbers": [1386968]
   },
   "STYLO_PARALLEL_RESTYLE_FRACTION": {
     "record_in_processes": ["content"],
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -1086,20 +1086,20 @@ gfx.omtp:
   paint_wait_ratio:
     bug_numbers:
       - 1386968
     description: >
       Ratio (in units of 1/100th of a percent) of how many times OMTP waited
       for a paint for more than 200us, versus the total number of paints.
     keyed: false
     kind: uint
-    expires: "61"
+    expires: "66"
     notification_emails:
       - gfx-telemetry-alerts@mozilla.com
-      - danderson@mozilla.com
+      - rhunt@mozilla.com
     record_in_processes:
       - 'content'
 
 # The following section contains the form autofill related scalars.
 formautofill:
   availability:
     bug_numbers:
       - 1386959