Bug 1499609 Convert tabpaint to webextension r=mconley
authorAndrew Swan <aswan@mozilla.com>
Tue, 23 Oct 2018 21:39:05 +0000
changeset 491022 3d84f10a7e99dd56fef9dcd48c5bfa9bcfa8a828
parent 491021 3f5f46ca8ca0df1c34a9077fd4b479e291997a3f
child 491023 e19cd8da255dd2fedd21c69a99545d4b5f0f1ef3
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersmconley
bugs1499609
milestone65.0a1
Bug 1499609 Convert tabpaint to webextension r=mconley Differential Revision: https://phabricator.services.mozilla.com/D8953
testing/talos/talos/test.py
testing/talos/talos/tests/tabpaint/api.js
testing/talos/talos/tests/tabpaint/bootstrap.js
testing/talos/talos/tests/tabpaint/chrome.manifest
testing/talos/talos/tests/tabpaint/content/tabpaint.html
testing/talos/talos/tests/tabpaint/content/target.html
testing/talos/talos/tests/tabpaint/framescript.js
testing/talos/talos/tests/tabpaint/install.rdf
testing/talos/talos/tests/tabpaint/manifest.json
testing/talos/talos/tests/tabpaint/schema.json
testing/talos/talos/tests/tabpaint/tabpaint.html
testing/talos/talos/tests/tabpaint/tabpaint.manifest
testing/talos/talos/tests/tabpaint/target.html
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -318,16 +318,17 @@ class tabpaint(PageloaderTest):
     preferences = {
         # By default, Talos is configured to open links from
         # content in new windows. We're overriding them so that
         # they open in new tabs instead.
         # See http://kb.mozillazine.org/Browser.link.open_newwindow
         # and http://kb.mozillazine.org/Browser.link.open_newwindow.restriction
         'browser.link.open_newwindow': 3,
         'browser.link.open_newwindow.restriction': 2,
+        'browser.newtab.preload': False,
     }
 
 
 @register_test()
 class tps(PageloaderTest):
     """
     Tests the amount of time it takes to switch between tabs
     """
rename from testing/talos/talos/tests/tabpaint/bootstrap.js
rename to testing/talos/talos/tests/tabpaint/api.js
--- a/testing/talos/talos/tests/tabpaint/bootstrap.js
+++ b/testing/talos/talos/tests/tabpaint/api.js
@@ -15,199 +15,168 @@
  *    the user has clicked on a link in a separate application which is opening
  *    in this browser, so the message to open the tab and display the content
  *    comes from the operating system, to the parent.
  *
  * 2) The tab has been opened by clicking on a link in content. It is possible
  *    for certain types of links (_blank links for example) to open new tabs.
  */
 
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource://gre/modules/Task.jsm");
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "Services",
+                               "resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyScriptGetter(this, "TalosParentProfiler",
+                                  "resource://talos-powers/TalosParentProfiler.js");
 
 const ANIMATION_PREF = "toolkit.cosmeticAnimations.enabled";
-
 const MULTI_OPT_OUT_PREF = "dom.ipc.multiOptOut";
 
-const TARGET_URI = "chrome://tabpaint/content/target.html";
-
-var TabPaint = {
-  MESSAGES: [
-    "TabPaint:Go",
-    "TabPaint:Painted",
-  ],
-
-  /**
-   * We'll hold the original tab animation preference here so
-   * we can restore it once the test is done.
-   */
-  originalTabsAnimate: null,
+const MESSAGES = [
+  "TabPaint:Go",
+  "TabPaint:Painted",
+];
 
-  /**
-   * We'll store a callback here to be fired once the TARGET_URI
-   * reports that it has painted.
-   */
-  paintCallback: null,
-
-  /**
-   * Shortcut to getting at the TalosParentProfiler.
-   */
-  get Profiler() {
-    delete this.Profiler;
-    let context = {};
-    Services.scriptloader.loadSubScript("resource://talos-powers/TalosParentProfiler.js", context);
-    return this.Profiler = context.TalosParentProfiler;
-  },
-
-  init() {
+/* globals ExtensionAPI */
+this.tabpaint = class extends ExtensionAPI {
+  onStartup() {
     // We don't have a window in this scope, and in fact, there might
     // not be any browser windows around. Since pageloader is loading
     // this add-on, along with the tabpaint.html content, what we'll do
     // is wait for the tabpaint.html content to send us a message to
     // get us moving.
-    for (let msgName of this.MESSAGES) {
+    for (let msgName of MESSAGES) {
       Services.mm.addMessageListener(msgName, this);
     }
 
+    this.framescriptURL = this.extension.baseURI.resolve("/framescript.js");
+    Services.mm.loadFrameScript(this.framescriptURL, true);
+
     this.originalAnimate = Services.prefs.getBoolPref(ANIMATION_PREF);
     Services.prefs.setBoolPref(ANIMATION_PREF, false);
     Services.prefs.setIntPref(MULTI_OPT_OUT_PREF,
                               Services.appinfo.E10S_MULTI_EXPERIMENT);
-  },
 
-  uninit() {
-    for (let msgName of this.MESSAGES) {
+    /**
+     * We'll store a callback here to be fired once the target page
+     * reports that it has painted.
+     */
+    this.paintCallback = null;
+  }
+
+  onShutdown() {
+    for (let msgName of MESSAGES) {
       Services.mm.removeMessageListener(msgName, this);
     }
 
+    Services.mm.removeDelayedFrameScript(this.framescriptURL);
+
     Services.prefs.setBoolPref(ANIMATION_PREF, this.originalAnimate);
     Services.prefs.clearUserPref(MULTI_OPT_OUT_PREF);
-  },
+  }
 
   receiveMessage(msg) {
     let browser = msg.target;
 
     let gBrowser = browser.ownerGlobal.gBrowser;
 
     switch (msg.name) {
       case "TabPaint:Go": {
         // Our document has loaded, and we're off to the races!
-        this.go(gBrowser).then((results) => {
-          this.reportResults(results);
-        });
-
+        this.go(browser.messageManager, gBrowser, msg.data.target);
         break;
       }
 
       case "TabPaint:Painted": {
         // Content has reported that it has painted.
         if (!this.paintCallback) {
           throw new Error("TabPaint:Painted fired without a paintCallback set");
         }
 
         let tab = gBrowser.getTabForBrowser(browser);
         let delta = msg.data.delta;
         this.paintCallback({tab, delta});
         break;
       }
     }
-  },
+  }
 
   /**
    * Start a single run of the test. This will measure the time
    * to open a new tab from the parent, and then measure the time
    * to open a new tab from content.
    *
    * @param gBrowser (<xul:tabbrowser>)
    *        The tabbrowser of the window to use.
-   *
-   * @return Promise
-   *         Resolves with an object with two properties:
-   *
-   *          fromParent (int):
-   *            The time (ms) it took to present a tab that
-   *            was opened from the parent.
-   *
-   *          fromContent (int):
-   *            The time (ms) it took to present a tab that
-   *            was opened from content.
    */
-  go: Task.async(function* (gBrowser) {
-    let fromParent = yield this.openTabFromParent(gBrowser);
-    let fromContent = yield this.openTabFromContent(gBrowser);
+  async go(mm, gBrowser, target) {
+    let fromParent = await this.openTabFromParent(gBrowser, target);
+    let fromContent = await this.openTabFromContent(gBrowser);
 
-    return { fromParent, fromContent };
-  }),
+    mm.sendAsyncMessage("TabPaint:FinalResults", { fromParent, fromContent });
+  }
 
   /**
    * Opens a tab from the parent, waits until it is displayed, then
    * removes the tab.
    *
    * @param gBrowser (<xul:tabbrowser>)
    *        The tabbrowser of the window to use.
    *
    * @return Promise
    *         Resolves once the tab has been fully removed. Resolves
    *         with the time (in ms) it took to open the tab from the parent.
    */
-  openTabFromParent(gBrowser) {
-    return new Promise((resolve) => {
-      this.Profiler.resume("tabpaint parent start");
-
-      // eslint-disable-next-line mozilla/avoid-Date-timing
-      gBrowser.selectedTab = gBrowser.addTab(TARGET_URI + "?" + Date.now(), {
-        triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
-      });
+  async openTabFromParent(gBrowser, target) {
+    TalosParentProfiler.resume("tabpaint parent start");
 
-      this.whenTabShown().then(({tab, delta}) => {
-        this.Profiler.pause("tabpaint parent end");
-        this.removeTab(tab).then(() => {
-          resolve(delta);
-        });
-      });
+    // eslint-disable-next-line mozilla/avoid-Date-timing
+    gBrowser.selectedTab = gBrowser.addTab(`${target}?${Date.now()}`, {
+      triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
     });
-  },
+
+    let {tab, delta} = await this.whenTabShown();
+    TalosParentProfiler.pause("tabpaint parent end");
+    await this.removeTab(tab);
+    return delta;
+  }
 
   /**
    * Opens a tab from content, waits until it is displayed, then
    * removes the tab.
    *
    * @param gBrowser (<xul:tabbrowser>)
    *        The tabbrowser of the window to use.
    *
    * @return Promise
    *         Resolves once the tab has been fully removed. Resolves
    *         with the time (in ms) it took to open the tab from content.
    */
-  openTabFromContent(gBrowser) {
-    return new Promise((resolve) => {
-      this.Profiler.resume("tabpaint content start");
+  async openTabFromContent(gBrowser) {
+    TalosParentProfiler.resume("tabpaint content start");
 
-      Services.mm.broadcastAsyncMessage("TabPaint:OpenFromContent");
+    Services.mm.broadcastAsyncMessage("TabPaint:OpenFromContent");
 
-      this.whenTabShown().then(({tab, delta}) => {
-        this.Profiler.pause("tabpaint content end");
-        this.removeTab(tab).then(() => {
-          resolve(delta);
-        });
-      });
-    });
-  },
+    let {tab, delta} = await this.whenTabShown();
+    TalosParentProfiler.pause("tabpaint content end");
+    await this.removeTab(tab);
+    return delta;
+  }
 
   /**
    * Returns a Promise that will resolve once the next tab reports
    * it has shown.
    *
    * @return Promise
    */
   whenTabShown() {
     return new Promise((resolve) => {
       this.paintCallback = resolve;
     });
-  },
+  }
 
   /**
    * Returns a Promise that removes a tab, and resolves once the final
    * message from that tab has come up.
    *
    * @param tab (<xul:tab>)
    *        The tab to remove.
    *
@@ -220,43 +189,10 @@ var TabPaint = {
         if (msg.targetFrameLoader == frameLoader && msg.data.isFinal) {
           mm.removeMessageListener("SessionStore:update", onMessage);
           resolve();
         }
       }, true);
 
       tab.ownerGlobal.gBrowser.removeTab(tab);
     });
-  },
-
-  /**
-   * Sends the results down to the tabpaint-test.html page, which will
-   * pipe them out to the console.
-   *
-   * @param results (Object)
-   *        An object with the following properties:
-   *
-   *          fromParent (int):
-   *            The time (ms) it took to present a tab that
-   *            was opened from the parent.
-   *
-   *          fromContent (int):
-   *            The time (ms) it took to present a tab that
-   *            was opened from content.
-   */
-  reportResults(results) {
-    Services.mm.broadcastAsyncMessage("TabPaint:FinalResults", results);
-  },
+  }
 };
-
-// Bootstrap functions below
-
-function install(aData, aReason) {}
-
-function startup(aData, aReason) {
-  TabPaint.init();
-}
-
-function shutdown(aData, aReason) {
-  TabPaint.uninit();
-}
-
-function uninstall(aData, aReason) {}
deleted file mode 100644
--- a/testing/talos/talos/tests/tabpaint/chrome.manifest
+++ /dev/null
@@ -1,1 +0,0 @@
-content tabpaint content/ remoteenabled=yes contentaccessible=yes
\ No newline at end of file
rename from testing/talos/talos/tests/tabpaint/content/target.html
rename to testing/talos/talos/tests/tabpaint/framescript.js
--- a/testing/talos/talos/tests/tabpaint/content/target.html
+++ b/testing/talos/talos/tests/tabpaint/framescript.js
@@ -1,60 +1,80 @@
-<html>
-<head>
-<title>TABPAINT</title>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
-</head>
-<body>
-<p>TABPAINT</p>
-</body>
-<script>
-
-  /**
-   * When this page is loaded, we expect a search string to be
-   * appended with the "starting time" (in ms) of when the tab
-   * was opened.
-   *
-   * Example: target.html?1457063506846
-   */
-  addEventListener("MozAfterPaint", function onPaint(e) {
-    // Bug 1371332 - sometimes, MozAfterPaint events fire
-    // for "empty" paints, where nothing has actually been
-    // painted. We can detect that by looking at the rect
-    // for the region that has painted.
-    let rect = e.boundingClientRect;
-    if (!rect.width && !rect.height) {
+(function() {
+  addEventListener("load", loadevt => {
+    if (!content.location.pathname.endsWith("target.html")) {
       return;
     }
-    // The MozAfterPaint event comes with a paintTimeStamp
-    // which tells us when in this content's lifetime the
-    // paint actually occurred. Note that this is not a
-    // measurement of when this paint occurred from
-    // the UNIX epoch. This makes it a little tricky to
-    // calculate when the paint actually occurred relative
-    // to the starting time that's been appended to the
-    // page's URL.
-    //
-    // Thankfully, the PerformanceTiming API gives us a
-    // sense of when this page's lifetime started, relative
-    // to the UNIX epoch - the "fetchStart". Taking that
-    // time and adding the paintTimeStamp should give us
-    // a pretty decent approximation of when since the
-    // UNIX epoch the paint actually occurred for this
-    // content.
-    //
-    // We can then subtract the starting time to get the
-    // delta, which should now represent the time it took
-    // from requesting that the tab be opened, to the
-    // paint occurring within the tab.
-    let fetchStart = window.performance.timing.fetchStart;
-    let presented = fetchStart + e.paintTimeStamp;
-    removeEventListener("MozAfterPaint", onPaint);
+
+    /**
+     * When a page is loaded, we expect a search string to be
+     * appended with the "starting time" (in ms) of when the tab
+     * was opened.
+     *
+     * Example: target.html?1457063506846
+     */
+    let opened = parseInt(content.location.search.substring(1), 10);
+
+    addEventListener("MozAfterPaint", function onPaint(e) {
+      // Bug 1371332 - sometimes, MozAfterPaint events fire
+      // for "empty" paints, where nothing has actually been
+      // painted. We can detect that by looking at the rect
+      // for the region that has painted.
+      let rect = e.boundingClientRect;
+      if (!rect.width && !rect.height) {
+        return;
+      }
+
+      removeEventListener("MozAfterPaint", onPaint);
 
-    let opened = parseInt(location.search.substring(1), 10);
-    let delta = presented - opened;
-
-    let mm = window.docShell.messageManager;
+      // The MozAfterPaint event comes with a paintTimeStamp
+      // which tells us when in this content's lifetime the
+      // paint actually occurred. Note that this is not a
+      // measurement of when this paint occurred from
+      // the UNIX epoch. This makes it a little tricky to
+      // calculate when the paint actually occurred relative
+      // to the starting time that's been appended to the
+      // page's URL.
+      //
+      // Thankfully, the PerformanceTiming API gives us a
+      // sense of when this page's lifetime started, relative
+      // to the UNIX epoch - the "fetchStart". Taking that
+      // time and adding the paintTimeStamp should give us
+      // a pretty decent approximation of when since the
+      // UNIX epoch the paint actually occurred for this
+      // content.
+      //
+      // We can then subtract the starting time to get the
+      // delta, which should now represent the time it took
+      // from requesting that the tab be opened, to the
+      // paint occurring within the tab.
+      let fetchStart = content.performance.timing.fetchStart;
+      let presented = fetchStart + e.paintTimeStamp;
+      let delta = presented - opened;
 
-    mm.sendAsyncMessage("TabPaint:Painted", { delta });
+      sendAsyncMessage("TabPaint:Painted", { delta });
+    });
+  }, true);
+
+  addEventListener("TabPaint:Ping", e => {
+    let evt = new content.CustomEvent("TabPaint:Pong", {bubbles: true});
+    content.dispatchEvent(evt);
+  }, false, true);
+
+  addEventListener("TabPaint:Go", e => {
+    sendAsyncMessage("TabPaint:Go", {target: e.detail.target});
+  }, false, true);
+
+  addMessageListener("TabPaint:OpenFromContent", msg => {
+    let evt = new content.CustomEvent("TabPaint:OpenFromContent",
+                                      {bubbles: true});
+    content.dispatchEvent(evt);
   });
-</script>
-</html>
+
+  addMessageListener("TabPaint:FinalResults", msg => {
+    let evt = Cu.cloneInto({
+      bubbles: true,
+      detail: msg.data,
+    }, content);
+
+    content.dispatchEvent(new content.CustomEvent("TabPaint:FinalResults", evt));
+  });
+})();
rename from testing/talos/talos/tests/tabpaint/install.rdf
rename to testing/talos/talos/tests/tabpaint/manifest.json
--- a/testing/talos/talos/tests/tabpaint/install.rdf
+++ b/testing/talos/talos/tests/tabpaint/manifest.json
@@ -1,24 +1,23 @@
-<?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">
-    <em:id>tabpaint-test@mozilla.org</em:id>
-    <em:type>2</em:type>
-    <em:name>tabpaint test</em:name>
-    <em:version>1.0.5</em:version>
-    <em:bootstrap>true</em:bootstrap>
-    <em:description>Measures the performance of opening tabs</em:description>
-    <em:creator>Mike Conley</em:creator>
-    <em:multiprocessCompatible>true</em:multiprocessCompatible>
+{
+  "manifest_version": 2,
+  "name": "tabpaint test",
+  "version": "1.1",
+  "description": "Measures the performance of opening tabs",
+
+  "applications": {
+    "gecko": {
+      "id": "tabpaint-test@mozilla.org"
+    }
+  },
 
-    <!-- Desktop -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>38.0</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-    <em:description>https://wiki.mozilla.org/Buildbot/Talos/Tests</em:description>
-    <em:homepageURL>https://wiki.mozilla.org/Buildbot/Talos/Tests</em:homepageURL>
-  </Description>
-</RDF>
+  "experiment_apis": {
+    "tabpaint": {
+      "schema": "schema.json",
+      "parent": {
+        "scopes": ["addon_parent"],
+        "script": "api.js",
+        "events": ["startup"]
+      }
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/schema.json
@@ -0,0 +1,1 @@
+[]
rename from testing/talos/talos/tests/tabpaint/content/tabpaint.html
rename to testing/talos/talos/tests/tabpaint/tabpaint.html
--- a/testing/talos/talos/tests/tabpaint/content/tabpaint.html
+++ b/testing/talos/talos/tests/tabpaint/tabpaint.html
@@ -1,36 +1,55 @@
 <html>
-  <head>
-    <script>
+<head>
+<script>
 
-      function init() {
-        if (document.location.hash.indexOf("#auto") == 0) {
-          let mm = window.docShell.messageManager;
+function init() {
+  let targetURL = new URL(window.location.href);
+  let i = targetURL.pathname.lastIndexOf("/");
+  targetURL.pathname = `${targetURL.pathname.substring(0, i)}/target.html`;
 
-          mm.addMessageListener("TabPaint:FinalResults", function onResults(msg) {
-            mm.removeMessageListener("TabPaint:FinalResults", onResults);
+  window.addEventListener("TabPaint:FinalResults", (event) => {
+    let { fromParent, fromContent } = event.detail;
+
+    tpRecordTime([fromParent, fromContent].join(","), 0, "tabpaint-from-parent, tabpaint-from-content");
+  }, {once: true});
 
-            let { fromParent, fromContent } = msg.data;
+  window.addEventListener("TabPaint:OpenFromContent", (event) => {
+    let target = document.getElementById("target");
+    let now = Date.now(); // eslint-disable-line mozilla/avoid-Date-timing
 
-            tpRecordTime([fromParent, fromContent].join(","), 0, "tabpaint-from-parent, tabpaint-from-content");
-          });
+    target.href = `${targetURL.href}?${now}`;
+    target.click();
+  });
 
-          mm.addMessageListener("TabPaint:OpenFromContent", function openFromContent() {
-            let target = document.getElementById("target");
-            let now = Date.now(); // eslint-disable-line mozilla/avoid-Date-timing
-            let href = "target.html?" + now;
-            target.href = href;
-            target.click();
-          });
+  async function tryPing() {
+    let pingPromise = new Promise(resolve => {
+      window.addEventListener("TabPaint:Pong", resolve, {once: true});
+      dispatchEvent(new CustomEvent("TabPaint:Ping", {bubbles: true}));
+    });
+    let timeoutPromise = new Promise((resolve, reject) => setTimeout(reject, 500));
+
+    try {
+      await Promise.race([pingPromise, timeoutPromise]);
+    } catch (e) {
+      return tryPing();
+    }
+    return null;
+  }
 
-          mm.sendAsyncMessage("TabPaint:Go");
-        }
-      }
+  tryPing().then(() => {
+    dispatchEvent(new CustomEvent("TabPaint:Go", {
+      bubbles: true,
+      detail: {
+        target: targetURL.href,
+      },
+    }));
+  });
+}
+</script>
+</head>
+<body onload="init();">
+  Hello, Talos!
 
-    </script>
-  </head>
-  <body onload="init();">
-    Hello, Talos!
-
-    <a href="#" id="target" target="_blank">I'll open a new tab</a>
-  </body>
+  <a href="#" id="target" target="_blank">I'll open a new tab</a>
+</body>
 </html>
--- a/testing/talos/talos/tests/tabpaint/tabpaint.manifest
+++ b/testing/talos/talos/tests/tabpaint/tabpaint.manifest
@@ -1,1 +1,2 @@
-% chrome://tabpaint/content/tabpaint.html#auto
+% http://localhost/tests/tabpaint/tabpaint.html
+
copy from testing/talos/talos/tests/tabpaint/content/target.html
copy to testing/talos/talos/tests/tabpaint/target.html
--- a/testing/talos/talos/tests/tabpaint/content/target.html
+++ b/testing/talos/talos/tests/tabpaint/target.html
@@ -1,60 +1,9 @@
 <html>
 <head>
 <title>TABPAINT</title>
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
 </head>
 <body>
 <p>TABPAINT</p>
 </body>
-<script>
-
-  /**
-   * When this page is loaded, we expect a search string to be
-   * appended with the "starting time" (in ms) of when the tab
-   * was opened.
-   *
-   * Example: target.html?1457063506846
-   */
-  addEventListener("MozAfterPaint", function onPaint(e) {
-    // Bug 1371332 - sometimes, MozAfterPaint events fire
-    // for "empty" paints, where nothing has actually been
-    // painted. We can detect that by looking at the rect
-    // for the region that has painted.
-    let rect = e.boundingClientRect;
-    if (!rect.width && !rect.height) {
-      return;
-    }
-    // The MozAfterPaint event comes with a paintTimeStamp
-    // which tells us when in this content's lifetime the
-    // paint actually occurred. Note that this is not a
-    // measurement of when this paint occurred from
-    // the UNIX epoch. This makes it a little tricky to
-    // calculate when the paint actually occurred relative
-    // to the starting time that's been appended to the
-    // page's URL.
-    //
-    // Thankfully, the PerformanceTiming API gives us a
-    // sense of when this page's lifetime started, relative
-    // to the UNIX epoch - the "fetchStart". Taking that
-    // time and adding the paintTimeStamp should give us
-    // a pretty decent approximation of when since the
-    // UNIX epoch the paint actually occurred for this
-    // content.
-    //
-    // We can then subtract the starting time to get the
-    // delta, which should now represent the time it took
-    // from requesting that the tab be opened, to the
-    // paint occurring within the tab.
-    let fetchStart = window.performance.timing.fetchStart;
-    let presented = fetchStart + e.paintTimeStamp;
-    removeEventListener("MozAfterPaint", onPaint);
-
-    let opened = parseInt(location.search.substring(1), 10);
-    let delta = presented - opened;
-
-    let mm = window.docShell.messageManager;
-
-    mm.sendAsyncMessage("TabPaint:Painted", { delta });
-  });
-</script>
 </html>