browser_remoteness_flip_on_restore.js (9199B)
1 "use strict"; 2 3 /** 4 * This set of tests checks that the remoteness is properly 5 * set for each browser in a window when that window has 6 * session state loaded into it. 7 */ 8 9 /** 10 * Takes a SessionStore window state object for a single 11 * window, sets the selected tab for it, and then returns 12 * the object to be passed to SessionStore.setWindowState. 13 * 14 * @param state (object) 15 * The state to prepare to be sent to a window. This is 16 * state should just be for a single window. 17 * @param selected (int) 18 * The 1-based index of the selected tab. Note that 19 * If this is 0, then the selected tab will not change 20 * from what's already selected in the window that we're 21 * sending state to. 22 * @returns (object) 23 * The JSON encoded string to call 24 * SessionStore.setWindowState with. 25 */ 26 function prepareState(state, selected) { 27 // We'll create a copy so that we don't accidentally 28 // modify the caller's selected property. 29 let copy = {}; 30 Object.assign(copy, state); 31 copy.selected = selected; 32 33 return { 34 windows: [copy], 35 }; 36 } 37 38 const SIMPLE_STATE = { 39 tabs: [ 40 { 41 entries: [ 42 { 43 url: "http://example.com/", 44 triggeringPrincipal_base64, 45 title: "title", 46 }, 47 ], 48 }, 49 { 50 entries: [ 51 { 52 url: "http://example.com/", 53 triggeringPrincipal_base64, 54 title: "title", 55 }, 56 ], 57 }, 58 { 59 entries: [ 60 { 61 url: "http://example.com/", 62 triggeringPrincipal_base64, 63 title: "title", 64 }, 65 ], 66 }, 67 ], 68 title: "", 69 _closedTabs: [], 70 }; 71 72 const PINNED_STATE = { 73 tabs: [ 74 { 75 entries: [ 76 { 77 url: "http://example.com/", 78 triggeringPrincipal_base64, 79 title: "title", 80 }, 81 ], 82 pinned: true, 83 }, 84 { 85 entries: [ 86 { 87 url: "http://example.com/", 88 triggeringPrincipal_base64, 89 title: "title", 90 }, 91 ], 92 pinned: true, 93 }, 94 { 95 entries: [ 96 { 97 url: "http://example.com/", 98 triggeringPrincipal_base64, 99 title: "title", 100 }, 101 ], 102 }, 103 ], 104 title: "", 105 _closedTabs: [], 106 }; 107 108 /** 109 * This is where most of the action is happening. This function takes 110 * an Array of "test scenario" Objects and runs them. For each scenario, a 111 * window is opened, put into some state, and then a new state is 112 * loaded into that window. We then check to make sure that the 113 * right things have happened in that window wrt remoteness flips. 114 * 115 * The schema for a testing scenario Object is as follows: 116 * 117 * initialRemoteness: 118 * an Array that represents the starting window. Each bool 119 * in the Array represents the window tabs in order. A "true" 120 * indicates that that tab should be remote. "false" if the tab 121 * should be non-remote. 122 * 123 * initialSelectedTab: 124 * The 1-based index of the tab that we want to select for the 125 * restored window. This is 1-based to avoid confusion with the 126 * selectedTab property described down below, though you probably 127 * want to set this to be greater than 0, since the initial window 128 * needs to have a defined initial selected tab. Because of this, 129 * the test will throw if initialSelectedTab is 0. 130 * 131 * stateToRestore: 132 * A JS Object for the state to send down to the window. 133 * 134 * selectedTab: 135 * The 1-based index of the tab that we want to select for the 136 * restored window. Leave this at 0 if you don't want to change 137 * the selection from the initial window state. 138 * 139 * expectedRemoteness: 140 * an Array that represents the window that we end up with after 141 * restoring state. Each bool in the Array represents the window 142 * tabs in order. A "true" indicates that the tab be remote, and 143 * a "false" indicates that the tab should be "non-remote". We 144 * need this Array in order to test pinned tabs which will also 145 * be loaded by default, and therefore should end up remote. 146 * 147 */ 148 async function runScenarios(scenarios) { 149 for (let [scenarioIndex, scenario] of scenarios.entries()) { 150 info("Running scenario " + scenarioIndex); 151 Assert.greater( 152 scenario.initialSelectedTab, 153 0, 154 "You must define an initially selected tab" 155 ); 156 157 // First, we need to create the initial conditions, so we 158 // open a new window to put into our starting state... 159 let win = await BrowserTestUtils.openNewBrowserWindow(); 160 let tabbrowser = win.gBrowser; 161 Assert.ok( 162 tabbrowser.selectedBrowser.isRemoteBrowser, 163 "The initial browser should be remote." 164 ); 165 // Now put the window into the expected initial state. 166 for (let i = 0; i < scenario.initialRemoteness.length; ++i) { 167 let tab; 168 if (i > 0) { 169 // The window starts with one tab, so we need to create 170 // any of the additional ones required by this test. 171 info("Opening a new tab"); 172 tab = await BrowserTestUtils.openNewForegroundTab(tabbrowser); 173 } else { 174 info("Using the selected tab"); 175 tab = tabbrowser.selectedTab; 176 } 177 let browser = tab.linkedBrowser; 178 let remotenessState = scenario.initialRemoteness[i] 179 ? E10SUtils.DEFAULT_REMOTE_TYPE 180 : E10SUtils.NOT_REMOTE; 181 tabbrowser.updateBrowserRemoteness(browser, { 182 remoteType: remotenessState, 183 }); 184 } 185 186 // And select the requested tab. 187 let tabToSelect = tabbrowser.tabs[scenario.initialSelectedTab - 1]; 188 if (tabbrowser.selectedTab != tabToSelect) { 189 await BrowserTestUtils.switchTab(tabbrowser, tabToSelect); 190 } 191 192 // Okay, time to test! 193 let state = prepareState(scenario.stateToRestore, scenario.selectedTab); 194 195 await setWindowState(win, state, true); 196 197 for (let i = 0; i < scenario.expectedRemoteness.length; ++i) { 198 let expectedRemoteness = scenario.expectedRemoteness[i]; 199 let tab = tabbrowser.tabs[i]; 200 201 Assert.equal( 202 tab.linkedBrowser.isRemoteBrowser, 203 expectedRemoteness, 204 "Should have gotten the expected remoteness " + 205 `for the tab at index ${i}` 206 ); 207 } 208 209 await BrowserTestUtils.closeWindow(win); 210 } 211 } 212 213 /** 214 * Tests that if we restore state to browser windows with 215 * a variety of initial remoteness states. For this particular 216 * set of tests, we assume that tabs are restoring on demand. 217 */ 218 add_task(async function () { 219 // This test opens and closes windows, which might bog down 220 // a debug build long enough to time out the test, so we 221 // extend the tolerance on timeouts. 222 requestLongerTimeout(5); 223 224 await SpecialPowers.pushPrefEnv({ 225 set: [["browser.sessionstore.restore_on_demand", true]], 226 }); 227 228 const TEST_SCENARIOS = [ 229 // Only one tab in the new window, and it's remote. This 230 // is the common case, since this is how restoration occurs 231 // when the restored window is being opened. 232 { 233 initialRemoteness: [true], 234 initialSelectedTab: 1, 235 stateToRestore: SIMPLE_STATE, 236 selectedTab: 3, 237 // All tabs should now be remote. 238 expectedRemoteness: [true, true, true], 239 }, 240 241 // A single remote tab, and this is the one that's going 242 // to be selected once state is restored. 243 { 244 initialRemoteness: [true], 245 initialSelectedTab: 1, 246 stateToRestore: SIMPLE_STATE, 247 selectedTab: 1, 248 // All tabs should now be remote. 249 expectedRemoteness: [true, true, true], 250 }, 251 252 // A single remote tab which starts selected. We set the 253 // selectedTab to 0 which is equivalent to "don't change 254 // the tab selection in the window". 255 { 256 initialRemoteness: [true], 257 initialSelectedTab: 1, 258 stateToRestore: SIMPLE_STATE, 259 selectedTab: 0, 260 // All tabs should now be remote. 261 expectedRemoteness: [true, true, true], 262 }, 263 264 // An initially remote tab, but we're going to load 265 // some pinned tabs now, and the pinned tabs should load 266 // right away. 267 { 268 initialRemoteness: [true], 269 initialSelectedTab: 1, 270 stateToRestore: PINNED_STATE, 271 selectedTab: 3, 272 // Both pinned tabs and the selected tabs should all 273 // end up being remote. 274 expectedRemoteness: [true, true, true], 275 }, 276 277 // A single non-remote tab. 278 { 279 initialRemoteness: [false], 280 initialSelectedTab: 1, 281 stateToRestore: SIMPLE_STATE, 282 selectedTab: 2, 283 // All tabs should now be remote. 284 expectedRemoteness: [true, true, true], 285 }, 286 287 // A mixture of remote and non-remote tabs. 288 { 289 initialRemoteness: [true, false, true], 290 initialSelectedTab: 1, 291 stateToRestore: SIMPLE_STATE, 292 selectedTab: 3, 293 // All tabs should now be remote. 294 expectedRemoteness: [true, true, true], 295 }, 296 297 // An initially non-remote tab, but we're going to load 298 // some pinned tabs now, and the pinned tabs should load 299 // right away. 300 { 301 initialRemoteness: [false], 302 initialSelectedTab: 1, 303 stateToRestore: PINNED_STATE, 304 selectedTab: 3, 305 // All tabs should now be remote. 306 expectedRemoteness: [true, true, true], 307 }, 308 ]; 309 310 await runScenarios(TEST_SCENARIOS); 311 });