browser_test_new_window_from_content.js (8576B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 /* 7 We have three ways for content to open new windows: 8 1) window.open (with the default features) 9 2) window.open (with non-default features) 10 3) target="_blank" in <a> tags 11 12 We also have two prefs that modify our window opening behaviours: 13 14 1) browser.link.open_newwindow 15 16 This has a numeric value that allows us to set our window-opening behaviours from 17 content in three ways: 18 1) Open links that would normally open a new window in the current tab 19 2) Open links that would normally open a new window in a new window 20 3) Open links that would normally open a new window in a new tab (default) 21 22 2) browser.link.open_newwindow.restriction 23 24 This has a numeric value that allows us to fine tune the browser.link.open_newwindow 25 pref so that it can discriminate between different techniques for opening windows. 26 27 0) All things that open windows should behave according to browser.link.open_newwindow. 28 1) No things that open windows should behave according to browser.link.open_newwindow 29 (essentially rendering browser.link.open_newwindow inert). 30 2) Most things that open windows should behave according to browser.link.open_newwindow, 31 _except_ for window.open calls with the "feature" parameter. This will open in a new 32 window regardless of what browser.link.open_newwindow is set at. (default) 33 34 This file attempts to test each window opening technique against all possible settings for 35 each preference. 36 */ 37 38 const kContentDoc = 39 "https://www.example.com/browser/dom/tests/browser/test_new_window_from_content_child.html"; 40 const kNewWindowPrefKey = "browser.link.open_newwindow"; 41 const kNewWindowRestrictionPrefKey = "browser.link.open_newwindow.restriction"; 42 const kSameTab = "same tab"; 43 const kNewWin = "new window"; 44 const kNewTab = "new tab"; 45 46 SpecialPowers.pushPrefEnv({ 47 set: [["dom.require_user_interaction_for_beforeunload", false]], 48 }); 49 50 requestLongerTimeout(3); 51 52 // The following "matrices" represent the result of content attempting to 53 // open a window with window.open with the default feature set. The key of 54 // the kWinOpenDefault object represents the value of browser.link.open_newwindow. 55 // The value for each key is an array that represents the result (either opening 56 // the link in the same tab, a new window, or a new tab), where the index of each 57 // result maps to the browser.link.open_newwindow.restriction pref. I've tried 58 // to illustrate this more clearly in the kWinOpenDefault object. 59 const kWinOpenDefault = { 60 // open_newwindow.restriction 61 // 0 1 2 62 // open_newwindow 63 1: [kSameTab, kNewWin, kSameTab], 64 2: [kNewWin, kNewWin, kNewWin], 65 3: [kNewTab, kNewWin, kNewTab], 66 }; 67 68 const kWinOpenNonDefault = { 69 1: [kSameTab, kNewWin, kNewWin], 70 2: [kNewWin, kNewWin, kNewWin], 71 3: [kNewTab, kNewWin, kNewWin], 72 }; 73 74 const kTargetBlank = { 75 1: [kSameTab, kSameTab, kSameTab], 76 2: [kNewWin, kNewWin, kNewWin], 77 3: [kNewTab, kNewTab, kNewTab], 78 }; 79 80 // We'll be changing these preferences a lot, so we'll stash their original 81 // values and make sure we restore them at the end of the test. 82 var originalNewWindowPref = Services.prefs.getIntPref(kNewWindowPrefKey); 83 var originalNewWindowRestrictionPref = Services.prefs.getIntPref( 84 kNewWindowRestrictionPrefKey 85 ); 86 87 registerCleanupFunction(function () { 88 Services.prefs.setIntPref(kNewWindowPrefKey, originalNewWindowPref); 89 Services.prefs.setIntPref( 90 kNewWindowRestrictionPrefKey, 91 originalNewWindowRestrictionPref 92 ); 93 }); 94 95 /** 96 * For some expectation when a link is clicked, creates and 97 * returns a Promise that resolves when that expectation is 98 * fulfilled. For example, aExpectation might be kSameTab, which 99 * will cause this function to return a Promise that resolves when 100 * the current tab attempts to browse to about:blank. 101 * 102 * This function also takes care of cleaning up once the result has 103 * occurred - for example, if a new window was opened, this function 104 * closes it before resolving. 105 * 106 * @param aBrowser the <xul:browser> with the test document 107 * @param aExpectation one of kSameTab, kNewWin, or kNewTab. 108 * @return a Promise that resolves when the expectation is fulfilled, 109 * and cleaned up after. 110 */ 111 function prepareForResult(aBrowser, aExpectation) { 112 let expectedSpec = kContentDoc.replace(/[^\/]*$/, "dummy.html"); 113 switch (aExpectation) { 114 case kSameTab: 115 return (async function () { 116 await BrowserTestUtils.browserLoaded(aBrowser); 117 is(aBrowser.currentURI.spec, expectedSpec, "Should be at dummy.html"); 118 // Now put the browser back where it came from 119 BrowserTestUtils.startLoadingURIString(aBrowser, kContentDoc); 120 await BrowserTestUtils.browserLoaded(aBrowser); 121 })(); 122 case kNewWin: 123 return (async function () { 124 let newWin = await BrowserTestUtils.waitForNewWindow({ 125 url: expectedSpec, 126 }); 127 let newBrowser = newWin.gBrowser.selectedBrowser; 128 is(newBrowser.currentURI.spec, expectedSpec, "Should be at dummy.html"); 129 await BrowserTestUtils.closeWindow(newWin); 130 })(); 131 case kNewTab: 132 return (async function () { 133 let newTab = await BrowserTestUtils.waitForNewTab(gBrowser); 134 is( 135 newTab.linkedBrowser.currentURI.spec, 136 expectedSpec, 137 "Should be at dummy.html" 138 ); 139 BrowserTestUtils.removeTab(newTab); 140 })(); 141 default: 142 ok( 143 false, 144 "prepareForResult can't handle an expectation of " + aExpectation 145 ); 146 return Promise.resolve(); 147 } 148 } 149 150 /** 151 * Ensure that clicks on a link with ID aLinkID cause us to 152 * perform as specified in the supplied aMatrix (kWinOpenDefault, 153 * for example). 154 * 155 * @param aLinkSelector a selector for the link within the testing page to click. 156 * @param aMatrix a testing matrix for the 157 * browser.link.open_newwindow and browser.link.open_newwindow.restriction 158 * prefs to test against. See kWinOpenDefault for an example. 159 */ 160 function testLinkWithMatrix(aLinkSelector, aMatrix) { 161 return BrowserTestUtils.withNewTab( 162 { 163 gBrowser, 164 url: kContentDoc, 165 }, 166 async function (browser) { 167 // This nested for-loop is unravelling the matrix const 168 // we set up, and gives us three things through each tick 169 // of the inner loop: 170 // 1) newWindowPref: a browser.link.open_newwindow pref to try 171 // 2) newWindowRestPref: a browser.link.open_newwindow.restriction pref to try 172 // 3) expectation: what we expect the click outcome on this link to be, 173 // which will either be kSameTab, kNewWin or kNewTab. 174 for (let newWindowPref in aMatrix) { 175 let expectations = aMatrix[newWindowPref]; 176 for (let i = 0; i < expectations.length; ++i) { 177 let newWindowRestPref = i; 178 let expectation = expectations[i]; 179 180 Services.prefs.setIntPref( 181 "browser.link.open_newwindow", 182 newWindowPref 183 ); 184 Services.prefs.setIntPref( 185 "browser.link.open_newwindow.restriction", 186 newWindowRestPref 187 ); 188 info("Clicking on " + aLinkSelector); 189 info( 190 "Testing with browser.link.open_newwindow = " + 191 newWindowPref + 192 " and " + 193 "browser.link.open_newwindow.restriction = " + 194 newWindowRestPref 195 ); 196 info("Expecting: " + expectation); 197 let resultPromise = prepareForResult(browser, expectation); 198 BrowserTestUtils.synthesizeMouseAtCenter(aLinkSelector, {}, browser); 199 await resultPromise; 200 info("Got expectation: " + expectation); 201 } 202 } 203 } 204 ); 205 } 206 207 add_setup(async function () { 208 await SpecialPowers.pushPrefEnv({ 209 set: [["test.wait300msAfterTabSwitch", true]], 210 }); 211 }); 212 213 add_task(async function test_window_open_with_defaults() { 214 await testLinkWithMatrix("#winOpenDefault", kWinOpenDefault); 215 }); 216 217 add_task(async function test_window_open_with_non_defaults() { 218 await testLinkWithMatrix("#winOpenNonDefault", kWinOpenNonDefault); 219 }); 220 221 add_task(async function test_window_open_dialog() { 222 await testLinkWithMatrix("#winOpenDialog", kWinOpenNonDefault); 223 }); 224 225 add_task(async function test_target__blank() { 226 await testLinkWithMatrix("#targetBlank", kTargetBlank); 227 });