Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

"use strict";
// Testing if 2 child processes are correctly managed when they both try to do
// an SW update.
const BASE_URI =
add_task(async function test_update() {
info("Setting the prefs to having multi-e10s enabled");
await SpecialPowers.pushPrefEnv({
set: [
["dom.ipc.processCount", 4],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
],
});
let url = BASE_URI + "file_multie10s_update.html";
info("Creating the first tab...");
let tab1 = BrowserTestUtils.addTab(gBrowser, url);
let browser1 = gBrowser.getBrowserForTab(tab1);
await BrowserTestUtils.browserLoaded(browser1);
info("Creating the second tab...");
let tab2 = BrowserTestUtils.addTab(gBrowser, url);
let browser2 = gBrowser.getBrowserForTab(tab2);
await BrowserTestUtils.browserLoaded(browser2);
let sw = BASE_URI + "server_multie10s_update.sjs";
info("Let's make sure there are no existing registrations...");
let existingCount = await SpecialPowers.spawn(
browser1,
[],
async function () {
const regs = await content.navigator.serviceWorker.getRegistrations();
return regs.length;
}
);
is(existingCount, 0, "Previous tests should have cleaned up!");
info("Let's start the test...");
/* eslint-disable no-shadow */
let status = await SpecialPowers.spawn(browser1, [sw], function (url) {
// Let the SW be served immediately once by triggering a relase immediately.
// We don't need to await this. We do this from a frame script because
// it has fetch.
content.fetch(url + "?release");
// Registration of the SW
return (
content.navigator.serviceWorker
.register(url)
// Activation
.then(function (r) {
content.registration = r;
return new content.window.Promise(resolve => {
let worker = r.installing;
worker.addEventListener("statechange", () => {
if (worker.state === "installed") {
resolve(true);
}
});
});
})
// Waiting for the result.
.then(() => {
return new content.window.Promise(resolveResults => {
// Once both updates have been issued and a single update has failed, we
// can tell the .sjs to release a single copy of the SW script.
let updateCount = 0;
const uc = new content.window.BroadcastChannel("update");
// This promise tracks the updates tally.
const updatesIssued = new Promise(resolveUpdatesIssued => {
uc.onmessage = function (e) {
updateCount++;
console.log("got update() number", updateCount);
if (updateCount === 2) {
resolveUpdatesIssued();
}
};
});
let results = [];
const rc = new content.window.BroadcastChannel("result");
// This promise resolves when an update has failed.
const oneFailed = new Promise(resolveOneFailed => {
rc.onmessage = function (e) {
console.log("got result", e.data);
results.push(e.data);
if (e.data === 1) {
resolveOneFailed();
}
if (results.length != 2) {
return;
}
resolveResults(results[0] + results[1]);
};
});
Promise.all([updatesIssued, oneFailed]).then(() => {
console.log("releasing update");
content.fetch(url + "?release").catch(ex => {
console.error("problem releasing:", ex);
});
});
// Let's inform the tabs.
const sc = new content.window.BroadcastChannel("start");
sc.postMessage("go");
});
})
);
});
/* eslint-enable no-shadow */
if (status == 0) {
ok(false, "both succeeded. This is wrong.");
} else if (status == 1) {
ok(true, "one succeded, one failed. This is good.");
} else {
ok(false, "both failed. This is definitely wrong.");
}
// let's clean up the registration and get the fetch count. The count
// should be 1 for the initial fetch and 1 for the update.
/* eslint-disable no-shadow */
const count = await SpecialPowers.spawn(browser1, [sw], async function (url) {
// We stored the registration on the frame script's wrapper, hence directly
// accesss content without using wrappedJSObject.
await content.registration.unregister();
const { count } = await content
.fetch(url + "?get-and-clear-count")
.then(r => r.json());
return count;
});
/* eslint-enable no-shadow */
is(count, 2, "SW should have been fetched only twice");
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
});