test_content_javascript_loads.html (4737B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Test for Bug 1647519</title> 5 <meta charset="utf-8"> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <script src="/tests/SimpleTest/EventUtils.js"></script> 8 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 9 </head> 10 <body> 11 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1647519">Mozilla Bug 1647519</a> 12 13 <script type="application/javascript"> 14 "use strict"; 15 16 function promiseMessage(source, filter = () => true) { 17 return new Promise(resolve => { 18 function listener(event) { 19 if (event.source == source && filter(event)) { 20 window.removeEventListener("message", listener); 21 resolve(event); 22 } 23 } 24 window.addEventListener("message", listener); 25 }); 26 } 27 28 async function runTests(resourcePath) { 29 /* globals Assert, content */ 30 let doc = content.document; 31 32 // Sends a message to the given target window and waits for a response a few 33 // times to (more or less) ensure that a `javascript:` load request has had 34 // time to succeed, if it were going to. 35 async function doSomeRoundTrips(target) { 36 for (let i = 0; i < 3; i++) { 37 // Note: The ping message needs to be sent from a script running in the 38 // content scope or there will be no source window for the reply to be 39 // sent to. 40 await content.wrappedJSObject.ping(target); 41 } 42 } 43 44 function promiseEvent(target, name) { 45 return new Promise(resolve => { 46 target.addEventListener(name, resolve, { once: true }); 47 }); 48 } 49 50 function createIframe(host, id) { 51 let iframe = doc.createElement("iframe"); 52 iframe.id = id; 53 iframe.name = id; 54 iframe.src = `https://${host}${resourcePath}file_content_javascript_loads_frame.html`; 55 doc.body.appendChild(iframe); 56 return promiseEvent(iframe, "load"); 57 } 58 59 const ID_SAME_ORIGIN = "frame-same-origin"; 60 const ID_SAME_BASE_DOMAIN = "frame-same-base-domain"; 61 const ID_CROSS_BASE_DOMAIN = "frame-cross-base-domain"; 62 63 await Promise.all([ 64 createIframe("example.com", ID_SAME_ORIGIN), 65 createIframe("test1.example.com", ID_SAME_BASE_DOMAIN), 66 createIframe("example.org", ID_CROSS_BASE_DOMAIN), 67 ]); 68 69 let gotJSLoadFrom = null; 70 let pendingJSLoadID = null; 71 content.addEventListener("message", event => { 72 if ("javascriptLoadID" in event.data) { 73 Assert.equal( 74 event.data.javascriptLoadID, 75 pendingJSLoadID, 76 "Message from javascript: load should have the expected ID" 77 ); 78 Assert.equal( 79 gotJSLoadFrom, 80 null, 81 "Should not have seen a previous load message this cycle" 82 ); 83 gotJSLoadFrom = event.source.name; 84 } 85 }); 86 87 async function watchForJSLoads(frameName, expected, task) { 88 let loadId = Math.random(); 89 90 let jsURI = 91 "javascript:" + 92 encodeURI(`parent.postMessage({ javascriptLoadID: ${loadId} }, "*")`); 93 94 pendingJSLoadID = loadId; 95 gotJSLoadFrom = null; 96 97 await task(jsURI); 98 99 await doSomeRoundTrips(content.wrappedJSObject[frameName]); 100 101 if (expected) { 102 Assert.equal( 103 gotJSLoadFrom, 104 frameName, 105 `Should have seen javascript: URI loaded into ${frameName}` 106 ); 107 } else { 108 Assert.equal( 109 gotJSLoadFrom, 110 null, 111 "Should not have seen javascript: URI loaded" 112 ); 113 } 114 } 115 116 let frames = [ 117 { name: ID_SAME_ORIGIN, expectLoad: true }, 118 { name: ID_SAME_BASE_DOMAIN, expectLoad: false }, 119 { name: ID_CROSS_BASE_DOMAIN, expectLoad: false }, 120 ]; 121 for (let { name, expectLoad } of frames) { 122 info(`Checking loads for frame "${name}". Expecting loads: ${expectLoad}`); 123 124 info("Checking location setter"); 125 await watchForJSLoads(name, expectLoad, jsURI => { 126 // Note: We need to do this from the content scope since security checks 127 // depend on the JS caller scope. 128 content.wrappedJSObject.setFrameLocation(name, jsURI); 129 }); 130 131 info("Checking targeted <a> load"); 132 await watchForJSLoads(name, expectLoad, jsURI => { 133 let a = doc.createElement("a"); 134 a.target = name; 135 a.href = jsURI; 136 doc.body.appendChild(a); 137 a.click(); 138 a.remove(); 139 }); 140 141 info("Checking targeted window.open load"); 142 await watchForJSLoads(name, expectLoad, jsURI => { 143 content.wrappedJSObject.open(jsURI, name); 144 }); 145 } 146 } 147 148 add_task(async function() { 149 const resourcePath = location.pathname.replace(/[^\/]+$/, ""); 150 151 let win = window.open( 152 `https://example.com${resourcePath}file_content_javascript_loads_root.html` 153 ); 154 await promiseMessage(win, event => event.data == "ready"); 155 156 await SpecialPowers.spawn(win, [resourcePath], runTests); 157 158 win.close(); 159 }); 160 </script> 161 162 </body> 163 </html>