history.sub.html (7216B)
1 <!DOCTYPE html> 2 <script src="/resources/testharness.js"></script> 3 <script src="/resources/testharnessreport.js"></script> 4 <script src="/common/utils.js"></script> 5 6 <meta http-equiv="Content-Security-Policy" content="img-src 'none'"> 7 8 <script> 9 let message_from = (source_token, starts_with) => { 10 return new Promise(resolve => { 11 window.addEventListener('message', msg => { 12 if (msg.data.token === source_token) { 13 if (!starts_with || msg.data.msg.startsWith(starts_with)) 14 resolve(msg.data.msg); 15 } 16 }); 17 }); 18 }; 19 20 const img_url = window.origin + "/content-security-policy/support/fail.png"; 21 22 const function_addImage_string = img_token => ` 23 function addImage() { 24 let img = document.createElement('img'); 25 img.src = '${img_url}'; 26 img.onload = () => opener.postMessage( 27 {msg: 'img loaded', token: '${img_token}'}, '*'); 28 img.onerror = () => opener.postMessage( 29 {msg: 'img blocked', token: '${img_token}'}, '*'); 30 document.body.appendChild(img); 31 } 32 `; 33 34 const img_tag_string = img_token => ` 35 <img src="${img_url}" 36 onload="opener.postMessage( 37 {msg: 'img loaded', token: '${img_token}'}, '*');" 38 onerror="opener.postMessage( 39 {msg: 'img blocked', token: '${img_token}'}, '*');" 40 > 41 `; 42 43 let write_img_to_popup = (popup, img_token) => { 44 let div = popup.document.createElement('div'); 45 div.innerHTML = img_tag_string(img_token); 46 popup.document.body.appendChild(div); 47 }; 48 49 // A beforeunload event listener disables bfcache (Firefox only). 50 // 51 // Note: Chrome enables bfcache only on HTTP/HTTPS documents, so a blob will 52 // never be put in the bfcache. Moreover with Chrome, bfcache needs a single 53 // top-level browsing context in the browsing context group. Since we are 54 // using window.open() below, the back-forward cache is not triggered. 55 const disable_bfcache = ` 56 window.addEventListener('beforeunload', function(event) { 57 eval('1+1'); 58 }); 59 `; 60 61 const blob_payload = blob_token => ` 62 <!doctype html> 63 <script>window.window_token = "${blob_token}";</scr`+`ipt> 64 <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt> 65 <body onpageshow="addImage();"></body> 66 `; 67 let blob_url = blob_token => URL.createObjectURL( 68 new Blob([blob_payload(blob_token)], { type: 'text/html' })); 69 70 const blob_payload_no_bfcache = blob_token => ` 71 <!doctype html> 72 <script>window.window_token = "${blob_token}";</scr`+`ipt> 73 <script>${disable_bfcache}</scr`+`ipt> 74 <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt> 75 <body onpageshow="addImage();"></body> 76 `; 77 let blob_url_no_bfcache = blob_token => URL.createObjectURL( 78 new Blob([blob_payload_no_bfcache(blob_token)], { type: 'text/html' })); 79 80 let testCases = [ 81 test_token => ({ 82 token: test_token, 83 url: "about:blank", 84 add_img_function: popup => write_img_to_popup(popup, test_token), 85 other_origin: window.origin, 86 name: '"about:blank" document is navigated back from history same-origin.', 87 }), 88 test_token => ({ 89 token: test_token, 90 url: "about:blank", 91 add_img_function: popup => write_img_to_popup(popup, test_token), 92 other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}", 93 name: '"about:blank" document is navigated back from history cross-origin.', 94 }), 95 test_token => ({ 96 token: test_token, 97 url: blob_url(test_token), 98 other_origin: window.origin, 99 name: 'blob URL document is navigated back from history same-origin.', 100 }), 101 test_token => ({ 102 token: test_token, 103 url: blob_url(test_token), 104 other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}", 105 name: 'blob URL document is navigated back from history cross-origin.', 106 }), 107 test_token => ({ 108 token: test_token, 109 url: blob_url_no_bfcache(test_token), 110 other_origin: window.origin, 111 name: 'blob URL document is navigated back from history (without bfcache on Firefox) same-origin.', 112 }), 113 test_token => ({ 114 token: test_token, 115 url: blob_url_no_bfcache(test_token), 116 other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}", 117 name: 'blob URL document is navigated back from history (without bfcache on Firefox) cross-origin.', 118 }), 119 ].map(f => f(token())); 120 121 let async_promise_test = (promise, description) => { 122 async_test(test => { 123 promise(test) 124 .then(() => {test.done();}) 125 .catch(test.step_func(error => { throw error; })); 126 }, description); 127 }; 128 129 testCases.forEach(testCase => { 130 async_promise_test(async t => { 131 // Create a popup. 132 let popup = window.open(); 133 134 // Closing fails sometimes on Firefox: 135 // https://bugzilla.mozilla.org/show_bug.cgi?id=1698093 136 t.add_cleanup(() => { popup.close(); }); 137 138 // Perform a real navigation in the popup. This is needed because the 139 // initial empty document is not stored in history (so there is no way of 140 // navigating back to it and test history inheritance). 141 const token_1 = token(); 142 let loaded_1 = message_from(token_1); 143 popup.location = testCase.other_origin + 144 `/content-security-policy/inheritance/support` + 145 `/postmessage-opener.html?token=${token_1}`; 146 assert_equals(await loaded_1, "ready", 147 "Could not open and navigate popup."); 148 149 // Navigate to the local scheme document. We need to wait for the 150 // navigation to succeed. 151 let wait = () => t.step_wait( 152 condition = () => { 153 try { 154 return popup.location.href == testCase.url; 155 } catch {} 156 return false; 157 }, 158 description = "Wait for the popup to navigate.", 159 timeout=3000, 160 interval=50); 161 162 let message = message_from(testCase.token); 163 popup.location = testCase.url; 164 await wait(); 165 if (testCase.add_img_function) { 166 testCase.add_img_function(popup); 167 } 168 169 // Check that the local scheme document inherits CSP from the initiator. 170 assert_equals(await message, "img blocked", 171 "Image should be blocked by CSP inherited from navigation initiator."); 172 173 const token_2 = token(); 174 let loaded_2 = message_from(token_2, "ready"); 175 let message_2 = message_from(testCase.token, "img"); 176 // Navigate to another page, which will navigate back. 177 popup.location = testCase.other_origin + 178 `/content-security-policy/inheritance/support` + 179 `/message-opener-and-navigate-back.html?token=${token_2}`; 180 assert_equals(await loaded_2, "ready", 181 "Could not navigate popup."); 182 183 // We need to wait for the history navigation to be performed. 184 await wait(); 185 186 // Check that the "about:blank" document reloaded from history has the 187 // original CSPs. 188 if (testCase.add_img_function) { 189 testCase.add_img_function(popup); 190 } 191 assert_equals(await message_2, "img blocked", 192 "Image should be blocked by CSP reloaded from history."); 193 }, "History navigation: " + testCase.name); 194 }); 195 </script>