NavigationUtils.js (5369B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // ///////////////////////////////////////////////////////////////////////// 6 // 7 // Utilities for navigation tests 8 // 9 // ///////////////////////////////////////////////////////////////////////// 10 11 var body = "This frame was navigated."; 12 var target_url = "navigation_target_url.html"; 13 14 var popup_body = "This is a popup"; 15 var target_popup_url = "navigation_target_popup_url.html"; 16 17 // ///////////////////////////////////////////////////////////////////////// 18 // Functions that navigate frames 19 // ///////////////////////////////////////////////////////////////////////// 20 21 function navigateByLocation(wnd) { 22 try { 23 wnd.location = target_url; 24 } catch (ex) { 25 // We need to keep our finished frames count consistent. 26 // Oddly, this ends up simulating the behavior of IE7. 27 window.open(target_url, "_blank", "width=10,height=10"); 28 } 29 } 30 31 function navigateByOpen(name) { 32 window.open(target_url, name, "width=10,height=10"); 33 } 34 35 function navigateByForm(name) { 36 var form = document.createElement("form"); 37 form.action = target_url; 38 form.method = "POST"; 39 form.target = name; 40 document.body.appendChild(form); 41 form.submit(); 42 } 43 44 var hyperlink_count = 0; 45 46 function navigateByHyperlink(name) { 47 var link = document.createElement("a"); 48 link.href = target_url; 49 link.target = name; 50 link.id = "navigation_hyperlink_" + hyperlink_count++; 51 document.body.appendChild(link); 52 sendMouseEvent({ type: "click" }, link.id); 53 } 54 55 // ///////////////////////////////////////////////////////////////////////// 56 // Functions that call into Mochitest framework 57 // ///////////////////////////////////////////////////////////////////////// 58 59 async function isNavigated(wnd, message) { 60 var result = null; 61 try { 62 result = await SpecialPowers.spawn(wnd, [], () => 63 this.content.document.body.innerHTML.trim() 64 ); 65 } catch (ex) { 66 result = ex; 67 } 68 is(result, body, message); 69 } 70 71 function isBlank(wnd, message) { 72 var result = null; 73 try { 74 result = wnd.document.body.innerHTML.trim(); 75 } catch (ex) { 76 result = ex; 77 } 78 is(result, "This is a blank document.", message); 79 } 80 81 function isAccessible(wnd, message) { 82 try { 83 wnd.document.body.innerHTML; 84 ok(true, message); 85 } catch (ex) { 86 ok(false, message); 87 } 88 } 89 90 function isInaccessible(wnd, message) { 91 try { 92 wnd.document.body.innerHTML; 93 ok(false, message); 94 } catch (ex) { 95 ok(true, message); 96 } 97 } 98 99 function delay(msec) { 100 return new Promise(resolve => setTimeout(resolve, msec)); 101 } 102 103 // ///////////////////////////////////////////////////////////////////////// 104 // Functions that uses SpecialPowers.spawn 105 // ///////////////////////////////////////////////////////////////////////// 106 107 async function waitForFinishedFrames(numFrames) { 108 SimpleTest.requestFlakyTimeout("Polling"); 109 110 var finishedWindows = new Set(); 111 112 async function searchForFinishedFrames(win) { 113 try { 114 let { href, bodyText, readyState } = await SpecialPowers.spawn( 115 win, 116 [], 117 () => { 118 return { 119 href: this.content.location.href, 120 bodyText: 121 this.content.document.body && 122 this.content.document.body.textContent.trim(), 123 readyState: this.content.document.readyState, 124 }; 125 } 126 ); 127 128 if ( 129 (href.endsWith(target_url) || href.endsWith(target_popup_url)) && 130 (bodyText == body || bodyText == popup_body) && 131 readyState == "complete" 132 ) { 133 finishedWindows.add(SpecialPowers.getBrowsingContextID(win)); 134 } 135 } catch (e) { 136 // This may throw if a frame is not fully initialized, in which 137 // case we'll handle it in a later iteration. 138 } 139 140 for (let i = 0; i < win.frames.length; i++) { 141 await searchForFinishedFrames(win.frames[i]); 142 } 143 } 144 145 while (finishedWindows.size < numFrames) { 146 await delay(500); 147 148 for (let win of SpecialPowers.getGroupTopLevelWindows(window)) { 149 win = SpecialPowers.unwrap(win); 150 await searchForFinishedFrames(win); 151 } 152 } 153 154 if (finishedWindows.size > numFrames) { 155 throw new Error("Too many frames loaded."); 156 } 157 } 158 159 async function getFramesByName(name) { 160 let results = []; 161 for (let win of SpecialPowers.getGroupTopLevelWindows(window)) { 162 win = SpecialPowers.unwrap(win); 163 if ( 164 (await SpecialPowers.spawn(win, [], () => this.content.name)) === name 165 ) { 166 results.push(win); 167 } 168 } 169 170 return results; 171 } 172 173 async function cleanupWindows() { 174 for (let win of SpecialPowers.getGroupTopLevelWindows(window)) { 175 win = SpecialPowers.unwrap(win); 176 if (win.closed) { 177 continue; 178 } 179 180 let href = ""; 181 try { 182 href = await SpecialPowers.spawn( 183 win, 184 [], 185 () => 186 this.content && this.content.location && this.content.location.href 187 ); 188 } catch (error) { 189 // SpecialPowers.spawn(win, ...) throws if win is closed. We did 190 // our best to not call it on a closed window, but races happen. 191 if (!win.closed) { 192 throw error; 193 } 194 } 195 196 if ( 197 href && 198 (href.endsWith(target_url) || href.endsWith(target_popup_url)) 199 ) { 200 win.close(); 201 } 202 } 203 }