Merge mozilla-central to mozilla-inbound. a=merge
authorDaniel Varga <dvarga@mozilla.com>
Sat, 20 Oct 2018 14:03:04 +0300
changeset 500754 a83370778faf43b69e9a3b3540d25ce8b51da6a8
parent 500753 8784cdbf16d36c6e10a969bfaf47725ecec3b080 (current diff)
parent 500742 fb6f3dea0beaa9e17e58f8967ccfcf604f4d95fb (diff)
child 500755 7141a7da10208223603df9d309e1d738dbf91892
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.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-central to mozilla-inbound. a=merge
testing/talos/talos/tests/tart/addon/bootstrap.js
testing/talos/talos/tests/tart/addon/chrome.manifest
testing/talos/talos/tests/tart/addon/content/blank.icon.html
testing/talos/talos/tests/tart/addon/content/initialize_browser.js
testing/talos/talos/tests/tart/addon/content/tart.html
testing/talos/talos/tests/tart/addon/content/tart.ico
testing/talos/talos/tests/tart/addon/install.rdf
--- a/devtools/shared/css/constants.js
+++ b/devtools/shared/css/constants.js
@@ -6,17 +6,17 @@
 
 /**
  * All CSS <angle> types that properties can support.
  */
 exports.CSS_ANGLEUNIT = {
   "deg": "deg",
   "rad": "rad",
   "grad": "grad",
-  "turn": "turn"
+  "turn": "turn",
 };
 
 /**
  * All CSS types that properties can support. This list can be manually edited.
  *
  * The existing numbers are for backward compatibility so that newer versions
  * are still able to debug an old version correctly.
  */
rename from testing/talos/talos/tests/tart/addon/bootstrap.js
rename to testing/talos/talos/tests/tart/addon/api.js
--- a/testing/talos/talos/tests/tart/addon/bootstrap.js
+++ b/testing/talos/talos/tests/tart/addon/api.js
@@ -1,52 +1,91 @@
 "use strict";
 
-/* globals initializeBrowser */
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  Services: "resource://gre/modules/Services.jsm",
+});
 
-// PLEASE NOTE:
-//
-// The canonical version of this file lives in testing/talos/talos, and
-// is duplicated in a number of test add-ons in directories below it.
-// Please do not update one withput updating all.
+XPCOMUtils.defineLazyServiceGetter(this, "aomStartup",
+                                   "@mozilla.org/addons/addon-manager-startup;1",
+                                   "amIAddonManagerStartup");
 
-// Reads the chrome.manifest from a legacy non-restartless extension and loads
-// its overlays into the appropriate top-level windows.
+XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
+                                   "@mozilla.org/widget/clipboardhelper;1",
+                                   "nsIClipboardHelper");
+
+/* globals ExtensionAPI */
+
+const PREFIX = "tart@mozilla.org";
 
-ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
-ChromeUtils.import("resource://gre/modules/Services.jsm");
+this.tart = class extends ExtensionAPI {
+  constructor(...args) {
+    super(...args);
+    this.loadedWindows = new WeakSet();
+  }
 
-const windowTracker = {
-  init() {
-    Services.ww.registerNotification(this);
-  },
+  onStartup() {
+    const manifestURI = Services.io.newURI("manifest.json", null, this.extension.rootURI);
+    this.chromeHandle = aomStartup.registerChrome(manifestURI, [
+      ["content", "tart", "chrome/"],
+    ]);
 
-  async observe(window, topic, data) {
-    if (topic === "domwindowopened") {
-      await new Promise(resolve =>
-        window.addEventListener("DOMWindowCreated", resolve, {once: true}));
+    this.framescriptURL = this.extension.baseURI.resolve("/content/framescript.js");
+    Services.mm.loadFrameScript(this.framescriptURL, true);
+    Services.mm.addMessageListener(`${PREFIX}:chrome-exec-message`, this);
+  }
+
+  onShutdown() {
+    Services.mm.removeMessageListener(`${PREFIX}:chrome-exec-message`, this);
+    Services.mm.removeDelayedFrameScript(this.framescriptURL);
+    this.chromeHandle.destruct();
+  }
 
-      let {document} = window;
-      let {documentURI} = document;
+  receiveMessage({target, data}) {
+    let win = target.ownerGlobal;
+    if (!this.loadedWindows.has(win)) {
+      let {baseURI} = this.extension;
+      Services.scriptloader.loadSubScript(baseURI.resolve("/content/Profiler.js"), win);
+      Services.scriptloader.loadSubScript(baseURI.resolve("/content/tart.js"), win);
+      this.loadedWindows.add(win);
+    }
 
-      if (documentURI !== AppConstants.BROWSER_CHROME_URL) {
-        return;
-      }
-      initializeBrowser(window);
+    function sendResult(result) {
+      target.messageManager.sendAsyncMessage(`${PREFIX}:chrome-exec-reply`,
+                                             {id: data.id, result});
     }
-  },
-};
+
+    let {command} = data;
+
+    switch (command.name) {
+      case "ping":
+        sendResult();
+        break;
 
-function readSync(uri) {
-  let channel = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true});
-  let buffer = NetUtil.readInputStream(channel.open2());
-  return new TextDecoder().decode(buffer);
-}
+      case "runTest":
+        (new win.Tart()).startTest(sendResult, command.data);
+        break;
+
+      case "setASAP":
+        Services.prefs.setIntPref("layout.frame_rate", 0);
+        Services.prefs.setIntPref("docshell.event_starvation_delay_hint", 1);
+        sendResult();
+        break;
 
-function startup(data, reason) {
-  Services.scriptloader.loadSubScript(data.resourceURI.resolve("content/initialize_browser.js"));
-  windowTracker.init();
-}
+      case "unsetASAP":
+        Services.prefs.clearUserPref("layout.frame_rate");
+        Services.prefs.clearUserPref("docshell.event_starvation_delay_hint");
+        sendResult();
+        break;
 
-function shutdown(data, reason) {}
-function install(data, reason) {}
-function uninstall(data, reason) {}
+      case "toClipboard":
+        clipboardHelper.copyString(command.data);
+        sendResult();
+        break;
+
+      default:
+        Cu.reportError(`Unknown TART command ${command.name}\n`);
+        break;
+    }
+  }
+};
deleted file mode 100644
--- a/testing/talos/talos/tests/tart/addon/chrome.manifest
+++ /dev/null
@@ -1,1 +0,0 @@
-content tart content/
rename from testing/talos/talos/tests/tart/addon/content/blank.icon.html
rename to testing/talos/talos/tests/tart/addon/chrome/blank.icon.html
--- a/testing/talos/talos/tests/tart/addon/content/framescript.js
+++ b/testing/talos/talos/tests/tart/addon/content/framescript.js
@@ -1,25 +1,38 @@
 (function() {
   const TART_PREFIX = "tart@mozilla.org:";
 
   addEventListener(TART_PREFIX + "chrome-exec-event", function(e) {
-    if (content.document.documentURI.indexOf("chrome://tart/content/tart.html")) {
-      // Can have url fragment. Backward compatible version of !str.startsWidth("prefix")
-      throw new Error("Cannot be used outside of TART's launch page");
+    if (!content.location.pathname.endsWith("tart.html")) {
+      Cu.reportError(`Ignore chrome-exec-event on non-tart page ${content.location.href}`);
+      return;
+    }
+
+    function dispatchReply(result) {
+      let contentEvent = Cu.cloneInto({
+        bubbles: true,
+        detail: result,
+      }, content);
+      content.dispatchEvent(new content.CustomEvent(e.detail.replyEvent, contentEvent));
+    }
+
+    if (e.detail.command.name == "ping") {
+      dispatchReply();
+      return;
     }
 
     // eslint-disable-next-line mozilla/avoid-Date-timing
     var uniqueMessageId = TART_PREFIX + content.document.documentURI + Date.now() + Math.random();
 
     addMessageListener(TART_PREFIX + "chrome-exec-reply", function done(reply) {
       if (reply.data.id == uniqueMessageId) {
         removeMessageListener(TART_PREFIX + "chrome-exec-reply", done);
-        e.detail.doneCallback(reply.data.result);
+        dispatchReply(reply.data.result);
       }
     });
 
     sendAsyncMessage(TART_PREFIX + "chrome-exec-message", {
       command: e.detail.command,
       id: uniqueMessageId,
     });
-  }, false);
+  }, false, true);
 })();
deleted file mode 100644
--- a/testing/talos/talos/tests/tart/addon/content/initialize_browser.js
+++ /dev/null
@@ -1,54 +0,0 @@
-function initializeBrowser(win) {
-  Services.scriptloader.loadSubScript("chrome://tart/content/Profiler.js", win);
-  Services.scriptloader.loadSubScript("chrome://tart/content/tart.js", win);
-  var prefs = Services.prefs;
-
-  const TART_PREFIX = "tart@mozilla.org:";
-
-  // "services" which the framescript can execute at the chrome process
-  var proxiedServices = {
-    runTest(config, callback) {
-      (new win.Tart()).startTest(callback, config);
-    },
-
-    setASAP() {
-      prefs.setIntPref("layout.frame_rate", 0);
-      prefs.setIntPref("docshell.event_starvation_delay_hint", 1);
-    },
-
-    unsetASAP() {
-      prefs.clearUserPref("layout.frame_rate");
-      prefs.clearUserPref("docshell.event_starvation_delay_hint");
-    },
-
-    toClipboard(text) {
-      const gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"]
-                               .getService(Ci.nsIClipboardHelper);
-      gClipboardHelper.copyString(text);
-    },
-  };
-
-  var groupMM = win.getGroupMessageManager("browsers");
-  groupMM.loadFrameScript("chrome://tart/content/framescript.js", true);
-
-  // listener/executor on the chrome process for tart.html
-  groupMM.addMessageListener(TART_PREFIX + "chrome-exec-message", function listener(m) {
-    function sendResult(result) {
-      groupMM.broadcastAsyncMessage(TART_PREFIX + "chrome-exec-reply", {
-        id: m.data.id,
-        result,
-      });
-    }
-
-    var command = m.data.command;
-    if (!proxiedServices.hasOwnProperty(command.name))
-      throw new Error("TART: service doesn't exist: '" + command.name + "'");
-
-    var service = proxiedServices[command.name];
-    if (command.name == "runTest") // Needs async execution
-      service(command.data, sendResult);
-    else
-      sendResult(service(command.data));
-
-  });
-}
--- a/testing/talos/talos/tests/tart/addon/content/tart.js
+++ b/testing/talos/talos/tests/tart/addon/content/tart.js
@@ -388,37 +388,23 @@ Tart.prototype = {
     window.dump(str);
   },
 
   _logLine(str) {
     return this._log(str + "\n");
   },
 
   _reportAllResults() {
-    var testNames = [];
-    var testResults = [];
-
     var out = "";
     for (var i in this._results) {
       res = this._results[i];
       var disp = [].concat(res.value).map(function(a) { return (isNaN(a) ? -1 : a.toFixed(1)); }).join(" ");
       out += res.name + ": " + disp + "\n";
-
-      if (!Array.isArray(res.value)) { // Waw intervals array is not reported to talos
-        testNames.push(res.name);
-        testResults.push(res.value);
-      }
     }
     this._log("\n" + out);
-
-    if (content && content.tpRecordTime) {
-      content.tpRecordTime(testResults.join(","), 0, testNames.join(","));
-    } else {
-      // alert(out);
-    }
   },
 
   _onTestComplete: null,
 
   _doneInternal() {
     this._logLine("TART_RESULTS_JSON=" + JSON.stringify(this._results));
     this._reportAllResults();
     this._win.gBrowser.selectedTab = this._tartTab;
rename from testing/talos/talos/tests/tart/addon/install.rdf
rename to testing/talos/talos/tests/tart/addon/manifest.json
--- a/testing/talos/talos/tests/tart/addon/install.rdf
+++ b/testing/talos/talos/tests/tart/addon/manifest.json
@@ -1,21 +1,22 @@
-<?xml version="1.0"?><RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"     xmlns:em="http://www.mozilla.org/2004/em-rdf#"><Description about="urn:mozilla:install-manifest">
+{
+  "manifest_version": 2,
+  "name": "TART - Tab Animation regression Test",
+  "version": "2.0",
 
-<!-- Required Items -->
-<em:id>bug848358@mozilla.org</em:id>
-<em:name>TART - Tab Animation regression Test</em:name>
-<em:version>1.6.2</em:version>
-<em:bootstrap>true</em:bootstrap>
+  "applications": {
+    "gecko": {
+      "id": "bug848358@mozilla.org"
+    }
+  },
 
-<em:targetApplication>
-    <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>1.5</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-    </Description>
-</em:targetApplication>
-
-<!-- Optional Items -->
-<em:creator>Avi Halachmi</em:creator>
-<em:description>Bug 848358, bug 956388. To run: navigate to chrome://tart/content/tart.html</em:description>
-<em:homepageURL>https://bugzilla.mozilla.org/show_bug.cgi?id=848358</em:homepageURL>
-</Description></RDF>
+  "experiment_apis": {
+    "tart": {
+      "schema": "schema.json",
+      "parent": {
+        "scopes": ["addon_parent"],
+        "script": "api.js",
+        "events": ["startup"]
+      }
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tart/addon/schema.json
@@ -0,0 +1,1 @@
+[]
rename from testing/talos/talos/tests/tart/addon/content/tart.html
rename to testing/talos/talos/tests/tart/tart.html
--- a/testing/talos/talos/tests/tart/addon/content/tart.html
+++ b/testing/talos/talos/tests/tart/tart.html
@@ -1,9 +1,9 @@
-<html>
+<html>
 <head>
 
 <meta charset="UTF-8"/>
 <link id="tart-icon" rel="icon" href="tart.ico"/>
 <title>TART - Tab Animation Regression Test</title>
 
 <script type="application/x-javascript">
 
@@ -11,28 +11,33 @@ function $(id) {
   return document.getElementById(id);
 }
 
 // Executes command at the chrome process.
 // Limited to one argument (data), which is enough for TART.
 // doneCallback will be called once done and, if applicable, with the result as argument.
 // Execution might finish quickly (e.g. when setting prefs) or
 // take a while (e.g. when triggering the test run)
+let _replyId = 1;
 function chromeExec(commandName, data, doneCallback) {
-  // dispatch an event to the framescript which will take it from there.
-  doneCallback = doneCallback || function dummy() {};
+  let replyEvent = `tart@mozilla.org:chrome-exec-reply:${_replyId++}`;
+  if (doneCallback) {
+    addEventListener(replyEvent, e => { doneCallback(e.detail); },
+                     {once: true});
+  }
+
   dispatchEvent(
     new CustomEvent("tart@mozilla.org:chrome-exec-event", {
       bubbles: true,
       detail: {
         command: {
           name: commandName,
           data,
         },
-        doneCallback,
+        replyEvent,
       },
     })
   );
 }
 
 function setASAP() {
   chromeExec("setASAP");
 }
@@ -44,16 +49,32 @@ function unsetASAP() {
 function toClipboard(text) {
   chromeExec("toClipboard", text);
 }
 
 function runTest(config, doneCallback) {
   chromeExec("runTest", config, doneCallback);
 }
 
+// Returns a Promise that resolves when the test extension is loaded.
+function waitForLoad() {
+  async function tryPing() {
+    let pingPromise = new Promise(resolve => chromeExec("ping", null, resolve));
+    let timeoutPromise = new Promise((resolve, reject) => setTimeout(reject, 500));
+
+    try {
+      await Promise.race([pingPromise, timeoutPromise]);
+    } catch (e) {
+      return tryPing();
+    }
+    return null;
+  }
+  return tryPing();
+}
+
 
 function sum(values) {
   return values.reduce(function(a, b) { return a + b; });
 }
 
 function average(values) {
   return values.length ? sum(values) / values.length : 999999999;
 }
@@ -111,28 +132,39 @@ function doneTest(dispResult) {
         dispStats += s + "&nbsp;&nbsp;&nbsp;&nbsp;Average (" + stats[s].length + "): " + average(stats[s]).toFixed(2) + " stddev: " + stddev(stats[s]).toFixed(2) + "<br/>";
       }
 
       dispStats += "<hr/><b>Individual animations</b>:<br/>";
     }
 
     // eslint-disable-next-line no-unsanitized/property
     $("run-results").innerHTML = "<hr/><br/>Results <button onclick='toClipboard(lastResults)'>[ Copy to clipboard as JSON ]</button>:<br/>" + dispStats + dispResult.join("<br/>");
+
+    let testNames = [], testResults = [];
+    for (let result of JSON.parse(lastResults)) {
+      if (!Array.isArray(result.value)) {
+        testNames.push(result.name);
+        testResults.push(result.value);
+      }
+    }
+    window.tpRecordTime(testResults.join(","), 0, testNames.join(","));
   }
 }
 
 var config = {subtests: [], repeat: 1}; // Empty subtests interpreted as all subtests, since otherwise meaningless.
 
 function triggerStart() {
   updateConfig();
   $("hide-during-run").style.display = "none";
   $("show-during-run").style.display = "block";
   $("run-results").innerHTML = "";
 
-  runTest(config, doneTest);
+  waitForLoad().then(() => {
+    runTest(config, doneTest);
+  });
 }
 
 var defaultConfig = {
       repeat: 1,
       rest: 500,
       tickle: true,
       controlProfiler: true,  // If true, pause the profiler when not measuring. Else just add markers.
       subtests: {
rename from testing/talos/talos/tests/tart/addon/content/tart.ico
rename to testing/talos/talos/tests/tart/tart.ico
--- a/testing/talos/talos/tests/tart/tart.manifest
+++ b/testing/talos/talos/tests/tart/tart.manifest
@@ -1,1 +1,1 @@
-% chrome://tart/content/tart.html#auto
+% http://localhost/tests/tart/tart.html#auto