test_remoteworker_launch_new_process.js (3820B)
1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ 2 /* vim: set sts=2 sw=2 et tw=80: */ 3 "use strict"; 4 5 // We don't normally allow localhost channels to be proxied, but this 6 // is easier than updating all the certs and/or domains. 7 Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); 8 registerCleanupFunction(() => { 9 Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); 10 }); 11 12 const { TestUtils } = ChromeUtils.importESModule( 13 "resource://testing-common/TestUtils.sys.mjs" 14 ); 15 16 const { AddonTestUtils } = ChromeUtils.importESModule( 17 "resource://testing-common/AddonTestUtils.sys.mjs" 18 ); 19 const { createHttpServer } = AddonTestUtils; 20 21 // Force ServiceWorkerRegistrar to init by calling do_get_profile. 22 // (This has to be called before AddonTestUtils.init, because it does 23 // also call do_get_profile internally but it doesn't notify 24 // profile-after-change). 25 do_get_profile(true); 26 27 AddonTestUtils.init(this); 28 29 const server = createHttpServer({ hosts: ["localhost"] }); 30 31 server.registerPathHandler("/sw.js", (request, response) => { 32 info(`/sw.js is being requested: ${JSON.stringify(request)}`); 33 response.setHeader("Content-Type", "application/javascript"); 34 response.write(""); 35 }); 36 37 add_task(async function setup_prefs() { 38 // Enable nsIServiceWorkerManager.registerForTest. 39 Services.prefs.setBoolPref("dom.serviceWorkers.testing.enabled", true); 40 41 registerCleanupFunction(() => { 42 Services.prefs.clearUserPref("dom.serviceWorkers.testing.enabled"); 43 }); 44 }); 45 46 /** 47 * This test installs a ServiceWorker via test API and verify that the install 48 * process spawns a new process. (Normally ServiceWorker installation won't 49 * cause a new content process to be spawned because the call to register must 50 * be coming from within an existing content process, but the registerForTest 51 * API allows us to bypass this restriction.) 52 * 53 * This models the real-world situation of a push notification being received 54 * from the network which results in a ServiceWorker being spawned without their 55 * necessarily being an existing content process to host it (especially under Fission). 56 */ 57 add_task(async function launch_remoteworkers_in_new_processes() { 58 const swm = Cc["@mozilla.org/serviceworkers/manager;1"].getService( 59 Ci.nsIServiceWorkerManager 60 ); 61 62 const ssm = Services.scriptSecurityManager; 63 64 const initialChildCount = Services.ppmm.childCount; 65 66 // A test service worker that should spawn a regular web content child process. 67 const swRegInfoWeb = await swm.registerForTest( 68 ssm.createContentPrincipal(Services.io.newURI("http://localhost"), {}), 69 "http://localhost/scope", 70 "http://localhost/sw.js" 71 ); 72 swRegInfoWeb.QueryInterface(Ci.nsIServiceWorkerRegistrationInfo); 73 74 info( 75 `web content service worker registered: ${JSON.stringify({ 76 principal: swRegInfoWeb.principal.spec, 77 scope: swRegInfoWeb.scope, 78 })}` 79 ); 80 81 info("Wait new process to be launched"); 82 await TestUtils.waitForCondition(() => { 83 return Services.ppmm.childCount - initialChildCount >= 1; 84 }, "wait for a new child processes to be started"); 85 86 // Wait both workers to become active to ensure script loading completed 87 // successfully. Note that when this test was originally introduced, we had a 88 // method IsRemoteTypeAllowed which would be run in the content process as an 89 // additional check that we ended up in the process we expected. Improvements 90 // in bug 1901851 and other bugs eliminated that concern, so now all we care 91 // about is that script loading completes and thereby allows the SW to advance 92 // to active. 93 info("Wait for webcontent worker to become active"); 94 await TestUtils.waitForCondition( 95 () => swRegInfoWeb.activeWorker, 96 `wait workers for scope ${swRegInfoWeb.scope} to be active` 97 ); 98 });