1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
"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"));
|