Bug 1467136 Ensure extension messaging cannot miss the startup event r=kmag

When a background page has a messaging listener but the background page
is started in response to something other than an extension message, we
were missing the background "startup" event.  Fix that by setting up the
listener earlier.

MozReview-Commit-ID: Cr58EyCoY6W

--HG--
extra : rebase_source : 0d309e01be35e2ef7ab5e489726d0191571ca371
This commit is contained in:
Andrew Swan 2018-06-06 13:58:43 -07:00
parent 8922082362
commit efbc1f62aa
2 changed files with 60 additions and 5 deletions

View file

@ -1804,10 +1804,11 @@ class EventManager {
let primed = {pendingEvents: []};
listener.primed = primed;
let wakeup = () => new Promise(resolve => {
extension.once("startup", resolve);
let bgStartupPromise = new Promise(r => extension.once("startup", r));
let wakeup = () => {
extension.emit("background-page-event");
});
return bgStartupPromise;
};
let fireEvent = (...args) => new Promise((resolve, reject) => {
primed.pendingEvents.push({args, resolve, reject});

View file

@ -17,6 +17,8 @@ let {
Services.prefs.setBoolPref("extensions.webextensions.background-delayed-startup", true);
const PAGE_HTML = `<!DOCTYPE html><meta charset="utf-8"><script src="script.js"></script>`;
function trackEvents(wrapper) {
let events = new Map();
for (let event of ["background-page-event", "start-background-page"]) {
@ -42,7 +44,7 @@ async function test(what, background, script) {
},
files: {
"page.html": `<!DOCTYPE html><meta charset="utf-8"><script src="script.js"></script>`,
"page.html": PAGE_HTML,
"script.js": script,
},
@ -121,8 +123,8 @@ async function test(what, background, script) {
await page.close();
await extension.unload();
ExtensionParent._resetStartupPromises();
await promiseShutdownManager();
ExtensionParent._resetStartupPromises();
}
add_task(function test_onMessage() {
@ -174,3 +176,55 @@ add_task(function test_onConnect() {
return test("onConnect", background, script);
});
// Test that messaging works if the background page is started before
// any messages are exchanged. (See bug 1467136 for an example of how
// this broke at one point).
add_task(async function test_other_startup() {
await promiseStartupManager();
let extension = ExtensionTestUtils.loadExtension({
useAddonManager: "permanent",
async background() {
browser.runtime.onMessage.addListener(msg => {
browser.test.notifyPass("startup");
});
// addListener() returns right away but make a round trip to the
// main process to ensure the persistent onMessage listener is recorded.
await browser.runtime.getBrowserInfo();
browser.test.sendMessage("bg-ran");
},
files: {
"page.html": PAGE_HTML,
"script.js"() {
browser.runtime.sendMessage("ping");
},
},
});
await extension.startup();
await extension.awaitMessage("bg-ran");
await promiseRestartManager();
await extension.awaitStartup();
// Start the background page. No message have been sent at this point.
Services.obs.notifyObservers(null, "sessionstore-windows-restored");
await extension.awaitMessage("bg-ran");
// Now that the background page is fully started, load a new page that
// sends a message to the background page.
let url = extension.extension.baseURI.resolve("page.html");
let page = await ExtensionTestUtils.loadContentPage(url, {extension});
await extension.awaitFinish("startup");
await page.close();
await extension.unload();
await promiseShutdownManager();
ExtensionParent._resetStartupPromises();
});