browser_multie10s_update.js (5032B)
1 "use strict"; 2 3 // Testing if 2 child processes are correctly managed when they both try to do 4 // an SW update. 5 6 const BASE_URI = 7 "http://mochi.test:8888/browser/dom/serviceworkers/test/isolated/multi-e10s-update/"; 8 9 add_task(async function test_update() { 10 info("Setting the prefs to having multi-e10s enabled"); 11 await SpecialPowers.pushPrefEnv({ 12 set: [ 13 ["dom.ipc.processCount", 4], 14 ["dom.serviceWorkers.enabled", true], 15 ["dom.serviceWorkers.testing.enabled", true], 16 ], 17 }); 18 19 let url = BASE_URI + "file_multie10s_update.html"; 20 21 info("Creating the first tab..."); 22 let tab1 = BrowserTestUtils.addTab(gBrowser, url); 23 let browser1 = gBrowser.getBrowserForTab(tab1); 24 await BrowserTestUtils.browserLoaded(browser1); 25 26 info("Creating the second tab..."); 27 let tab2 = BrowserTestUtils.addTab(gBrowser, url); 28 let browser2 = gBrowser.getBrowserForTab(tab2); 29 await BrowserTestUtils.browserLoaded(browser2); 30 31 let sw = BASE_URI + "server_multie10s_update.sjs"; 32 33 info("Let's make sure there are no existing registrations..."); 34 let existingCount = await SpecialPowers.spawn( 35 browser1, 36 [], 37 async function () { 38 const regs = await content.navigator.serviceWorker.getRegistrations(); 39 return regs.length; 40 } 41 ); 42 is(existingCount, 0, "Previous tests should have cleaned up!"); 43 44 info("Let's start the test..."); 45 /* eslint-disable no-shadow */ 46 let status = await SpecialPowers.spawn(browser1, [sw], function (url) { 47 // Let the SW be served immediately once by triggering a relase immediately. 48 // We don't need to await this. We do this from a frame script because 49 // it has fetch. 50 content.fetch(url + "?release"); 51 52 // Registration of the SW 53 return ( 54 content.navigator.serviceWorker 55 .register(url) 56 57 // Activation 58 .then(function (r) { 59 content.registration = r; 60 return new content.window.Promise(resolve => { 61 let worker = r.installing; 62 worker.addEventListener("statechange", () => { 63 if (worker.state === "installed") { 64 resolve(true); 65 } 66 }); 67 }); 68 }) 69 70 // Waiting for the result. 71 .then(() => { 72 return new content.window.Promise(resolveResults => { 73 // Once both updates have been issued and a single update has failed, we 74 // can tell the .sjs to release a single copy of the SW script. 75 let updateCount = 0; 76 const uc = new content.window.BroadcastChannel("update"); 77 // This promise tracks the updates tally. 78 const updatesIssued = new Promise(resolveUpdatesIssued => { 79 uc.onmessage = function (e) { 80 updateCount++; 81 console.log("got update() number", updateCount); 82 if (updateCount === 2) { 83 resolveUpdatesIssued(); 84 } 85 }; 86 }); 87 88 let results = []; 89 const rc = new content.window.BroadcastChannel("result"); 90 // This promise resolves when an update has failed. 91 const oneFailed = new Promise(resolveOneFailed => { 92 rc.onmessage = function (e) { 93 console.log("got result", e.data); 94 results.push(e.data); 95 if (e.data === 1) { 96 resolveOneFailed(); 97 } 98 if (results.length != 2) { 99 return; 100 } 101 102 resolveResults(results[0] + results[1]); 103 }; 104 }); 105 106 Promise.all([updatesIssued, oneFailed]).then(() => { 107 console.log("releasing update"); 108 content.fetch(url + "?release").catch(ex => { 109 console.error("problem releasing:", ex); 110 }); 111 }); 112 113 // Let's inform the tabs. 114 const sc = new content.window.BroadcastChannel("start"); 115 sc.postMessage("go"); 116 }); 117 }) 118 ); 119 }); 120 /* eslint-enable no-shadow */ 121 122 if (status == 0) { 123 ok(false, "both succeeded. This is wrong."); 124 } else if (status == 1) { 125 ok(true, "one succeded, one failed. This is good."); 126 } else { 127 ok(false, "both failed. This is definitely wrong."); 128 } 129 130 // let's clean up the registration and get the fetch count. The count 131 // should be 1 for the initial fetch and 1 for the update. 132 /* eslint-disable no-shadow */ 133 const count = await SpecialPowers.spawn(browser1, [sw], async function (url) { 134 // We stored the registration on the frame script's wrapper, hence directly 135 // accesss content without using wrappedJSObject. 136 await content.registration.unregister(); 137 const { count } = await content 138 .fetch(url + "?get-and-clear-count") 139 .then(r => r.json()); 140 return count; 141 }); 142 /* eslint-enable no-shadow */ 143 is(count, 2, "SW should have been fetched only twice"); 144 145 BrowserTestUtils.removeTab(tab1); 146 BrowserTestUtils.removeTab(tab2); 147 });