browser_manifest-src-override-default-src.js (3805B)
1 /* 2 * Description of the tests: 3 * Tests check that default-src can be overridden by manifest-src. 4 */ 5 /*globals Cu, is, ok*/ 6 "use strict"; 7 const { ManifestObtainer } = ChromeUtils.importESModule( 8 "resource://gre/modules/ManifestObtainer.sys.mjs" 9 ); 10 const path = "/tests/dom/security/test/csp/"; 11 const testFile = `${path}file_web_manifest.html`; 12 const mixedContentFile = `${path}file_web_manifest_mixed_content.html`; 13 const server = `${path}file_testserver.sjs`; 14 const defaultURL = new URL(`https://example.org${server}`); 15 const mixedURL = new URL(`http://mochi.test:8888${server}`); 16 17 // Enable web manifest processing. 18 Services.prefs.setBoolPref("dom.manifest.enabled", true); 19 20 const tests = [ 21 // Check interaction with default-src and another origin, 22 // CSP allows fetching from example.org, so manifest should load. 23 { 24 expected: `CSP manifest-src overrides default-src of elsewhere.com`, 25 get tabURL() { 26 const url = new URL(defaultURL); 27 url.searchParams.append("file", testFile); 28 url.searchParams.append("cors", "*"); 29 url.searchParams.append( 30 "csp", 31 "default-src http://elsewhere.com; manifest-src http://example.org" 32 ); 33 return url.href; 34 }, 35 run(manifest) { 36 is(manifest.name, "loaded", this.expected); 37 }, 38 }, 39 // Check interaction with default-src none, 40 // CSP allows fetching manifest from example.org, so manifest should load. 41 { 42 expected: `CSP manifest-src overrides default-src`, 43 get tabURL() { 44 const url = new URL(mixedURL); 45 url.searchParams.append("file", mixedContentFile); 46 url.searchParams.append("cors", "http://test:80"); 47 url.searchParams.append( 48 "csp", 49 "default-src 'self'; manifest-src http://test:80" 50 ); 51 return url.href; 52 }, 53 run(manifest) { 54 is(manifest.name, "loaded", this.expected); 55 }, 56 }, 57 ]; 58 59 //jscs:disable 60 add_task(async function () { 61 //jscs:enable 62 const testPromises = tests.map(test => { 63 const tabOptions = { 64 gBrowser, 65 url: test.tabURL, 66 skipAnimation: true, 67 }; 68 return BrowserTestUtils.withNewTab(tabOptions, browser => 69 testObtainingManifest(browser, test) 70 ); 71 }); 72 await Promise.all(testPromises); 73 }); 74 75 async function testObtainingManifest(aBrowser, aTest) { 76 const expectsBlocked = aTest.expected.includes("block"); 77 const observer = expectsBlocked ? createNetObserver(aTest) : null; 78 // Expect an exception (from promise rejection) if there a content policy 79 // that is violated. 80 try { 81 const manifest = await ManifestObtainer.browserObtainManifest(aBrowser); 82 aTest.run(manifest); 83 } catch (e) { 84 const wasBlocked = e.message.includes( 85 "NetworkError when attempting to fetch resource" 86 ); 87 ok( 88 wasBlocked, 89 `Expected promise rejection obtaining ${aTest.tabURL}: ${e.message}` 90 ); 91 if (observer) { 92 await observer.untilFinished; 93 } 94 } 95 } 96 97 // Helper object used to observe policy violations. It waits 1 seconds 98 // for a response, and then times out causing its associated test to fail. 99 function createNetObserver(test) { 100 let finishedTest; 101 let success = false; 102 const finished = new Promise(resolver => { 103 finishedTest = resolver; 104 }); 105 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 106 const timeoutId = setTimeout(() => { 107 if (!success) { 108 test.run("This test timed out."); 109 finishedTest(); 110 } 111 }, 1000); 112 var observer = { 113 get untilFinished() { 114 return finished; 115 }, 116 observe(subject, topic) { 117 SpecialPowers.removeObserver(observer, "csp-on-violate-policy"); 118 test.run(topic); 119 finishedTest(); 120 clearTimeout(timeoutId); 121 success = true; 122 }, 123 }; 124 SpecialPowers.addObserver(observer, "csp-on-violate-policy"); 125 return observer; 126 }