test_ext_worker_offline_fetch.js (3855B)
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 const { TestUtils } = ChromeUtils.importESModule( 6 "resource://testing-common/TestUtils.sys.mjs" 7 ); 8 9 const { AddonTestUtils } = ChromeUtils.importESModule( 10 "resource://testing-common/AddonTestUtils.sys.mjs" 11 ); 12 13 const { ExtensionTestUtils } = ChromeUtils.importESModule( 14 "resource://testing-common/ExtensionXPCShellUtils.sys.mjs" 15 ); 16 17 const { createHttpServer } = AddonTestUtils; 18 19 // Force ServiceWorkerRegistrar to init by calling do_get_profile. 20 // (This has to be called before AddonTestUtils.init, because it does 21 // also call do_get_profile internally but it doesn't notify 22 // profile-after-change). 23 do_get_profile(true); 24 25 AddonTestUtils.init(this); 26 ExtensionTestUtils.init(this); 27 28 const server = createHttpServer({ hosts: ["example.com"] }); 29 server.registerPathHandler("/dummy", (request, response) => { 30 response.setStatusLine(request.httpVersion, 200, "OK"); 31 response.setHeader("Content-Type", "text/html", false); 32 response.write("dummy page"); 33 }); 34 35 add_setup(() => { 36 info("Making sure Services.io.offline is true"); 37 // Explicitly setting Services.io.offline to true makes this test able 38 // to hit on Desktop builds the same issue that test_ext_cache_api.js 39 // was hitting on Android builds (Bug 1844825). 40 Services.io.offline = true; 41 }); 42 43 // Regression test derived from Bug 1844825. 44 add_task(async function test_fetch_request_from_ext_shared_worker() { 45 if (!WebExtensionPolicy.useRemoteWebExtensions) { 46 // Ensure RemoteWorkerService has been initialized in the main 47 // process. 48 Services.obs.notifyObservers(null, "profile-after-change"); 49 } 50 51 const background = async function () { 52 const testUrl = `http://example.com/dummy`; 53 const worker = new SharedWorker("worker.js"); 54 const { data: result } = await new Promise(resolve => { 55 worker.port.onmessage = resolve; 56 worker.port.postMessage(["worker-fetch-test", testUrl]); 57 }); 58 59 browser.test.sendMessage("test-sharedworker-fetch:done", result); 60 }; 61 62 const extension = ExtensionTestUtils.loadExtension({ 63 background, 64 manifest: { permissions: ["http://example.com/*"] }, 65 files: { 66 "worker.js": function () { 67 self.onconnect = evt => { 68 const port = evt.ports[0]; 69 port.onmessage = async evt => { 70 let result = {}; 71 let message; 72 try { 73 const [msg, url] = evt.data; 74 message = msg; 75 const response = await fetch(url); 76 dump(`fetch call resolved: ${response}\n`); 77 result.fetchResolvesTo = `${response}`; 78 } catch (err) { 79 dump(`fetch call rejected: ${err}\n`); 80 result.error = err.name; 81 throw err; 82 } finally { 83 port.postMessage([`${message}:result`, result]); 84 } 85 }; 86 }; 87 }, 88 }, 89 }); 90 91 await extension.startup(); 92 const result = await extension.awaitMessage("test-sharedworker-fetch:done"); 93 if (Services.io.offline && WebExtensionPolicy.useRemoteWebExtensions) { 94 // If the network is offline and the extensions are running in the 95 // child extension process, expect the fetch call to be rejected 96 // with an TypeError. 97 Assert.deepEqual( 98 ["worker-fetch-test:result", { error: "TypeError" }], 99 result, 100 "fetch should have been rejected with an TypeError" 101 ); 102 } else { 103 // If the network is not offline or the extension are running in the 104 // parent process, we expect the fetch call to resolve to a Response. 105 Assert.deepEqual( 106 ["worker-fetch-test:result", { fetchResolvesTo: "[object Response]" }], 107 result, 108 "fetch should have been resolved to a Response instance" 109 ); 110 } 111 await extension.unload(); 112 });