summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/tabs/browser_tabSpinnerProbe.js')
-rw-r--r--browser/base/content/test/tabs/browser_tabSpinnerProbe.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/browser/base/content/test/tabs/browser_tabSpinnerProbe.js b/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
new file mode 100644
index 0000000000..9115d4fc6c
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
@@ -0,0 +1,101 @@
+"use strict";
+
+/**
+ * Tests the FX_TAB_SWITCH_SPINNER_VISIBLE_MS and
+ * FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS telemetry probes
+ */
+const MIN_HANG_TIME = 500; // ms
+const MAX_HANG_TIME = 5 * 1000; // ms
+
+/**
+ * Returns the sum of all values in an array.
+ * @param {Array} aArray An array of integers
+ * @return {Number} The sum of the integers in the array
+ */
+function sum(aArray) {
+ return aArray.reduce(function (previousValue, currentValue) {
+ return previousValue + currentValue;
+ });
+}
+
+/**
+ * Causes the content process for a remote <xul:browser> to run
+ * some busy JS for aMs milliseconds.
+ *
+ * @param {<xul:browser>} browser
+ * The browser that's running in the content process that we're
+ * going to hang.
+ * @param {int} aMs
+ * The amount of time, in milliseconds, to hang the content process.
+ *
+ * @return {Promise}
+ * Resolves once the hang is done.
+ */
+function hangContentProcess(browser, aMs) {
+ return ContentTask.spawn(browser, aMs, function (ms) {
+ let then = Date.now();
+ while (Date.now() - then < ms) {
+ // Let's burn some CPU...
+ }
+ });
+}
+
+/**
+ * A generator intended to be run as a Task. It tests one of the tab spinner
+ * telemetry probes.
+ * @param {String} aProbe The probe to test. Should be one of:
+ * - FX_TAB_SWITCH_SPINNER_VISIBLE_MS
+ * - FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS
+ */
+async function testProbe(aProbe) {
+ info(`Testing probe: ${aProbe}`);
+ let histogram = Services.telemetry.getHistogramById(aProbe);
+ let delayTime = MIN_HANG_TIME + 1; // Pick a bucket arbitrarily
+
+ // The tab spinner does not show up instantly. We need to hang for a little
+ // bit of extra time to account for the tab spinner delay.
+ delayTime += gBrowser.selectedTab.linkedBrowser
+ .getTabBrowser()
+ ._getSwitcher().TAB_SWITCH_TIMEOUT;
+
+ // In order for a spinner to be shown, the tab must have presented before.
+ let origTab = gBrowser.selectedTab;
+ let hangTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
+ let hangBrowser = hangTab.linkedBrowser;
+ ok(hangBrowser.isRemoteBrowser, "New tab should be remote.");
+ ok(hangBrowser.frameLoader.remoteTab.hasPresented, "New tab has presented.");
+
+ // Now switch back to the original tab and set up our hang.
+ await BrowserTestUtils.switchTab(gBrowser, origTab);
+
+ let tabHangPromise = hangContentProcess(hangBrowser, delayTime);
+ histogram.clear();
+ let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, hangTab);
+ await tabHangPromise;
+ await hangTabSwitch;
+
+ // Now we should have a hang in our histogram.
+ let snapshot = histogram.snapshot();
+ BrowserTestUtils.removeTab(hangTab);
+ ok(
+ sum(Object.values(snapshot.values)) > 0,
+ `Spinner probe should now have a value in some bucket`
+ );
+}
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.ipc.processCount", 1],
+ // We can interrupt JS to paint now, which is great for
+ // users, but bad for testing spinners. We temporarily
+ // disable that feature for this test so that we can
+ // easily get ourselves into a predictable tab spinner
+ // state.
+ ["browser.tabs.remote.force-paint", false],
+ ],
+ });
+});
+
+add_task(testProbe.bind(null, "FX_TAB_SWITCH_SPINNER_VISIBLE_MS"));
+add_task(testProbe.bind(null, "FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS"));