browser_248970_b_perwindowpb.js (6352B)
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 function test() { 6 /** Test (B) for Bug 248970 */ 7 waitForExplicitFinish(); 8 9 let windowsToClose = []; 10 let file = Services.dirsvc.get("TmpD", Ci.nsIFile); 11 let filePath = file.path; 12 let fieldList = { 13 "//input[@name='input']": Date.now().toString(16), 14 "//input[@name='spaced 1']": Math.random().toString(), 15 "//input[3]": "three", 16 "//input[@type='checkbox']": true, 17 "//input[@name='uncheck']": false, 18 "//input[@type='radio'][1]": false, 19 "//input[@type='radio'][2]": true, 20 "//input[@type='radio'][3]": false, 21 "//select": 2, 22 "//select[@multiple]": [1, 3], 23 "//textarea[1]": "", 24 "//textarea[2]": "Some text... " + Math.random(), 25 "//textarea[3]": "Some more text\n" + new Date(), 26 "//input[@type='file']": filePath, 27 }; 28 29 registerCleanupFunction(async function () { 30 for (let win of windowsToClose) { 31 await BrowserTestUtils.closeWindow(win); 32 } 33 }); 34 35 function checkNoThrow(aLambda) { 36 try { 37 return aLambda() || true; 38 } catch (ex) {} 39 return false; 40 } 41 42 function getElementByXPath(aTab, aQuery) { 43 let doc = aTab.linkedBrowser.contentDocument; 44 let xptype = doc.defaultView.XPathResult.FIRST_ORDERED_NODE_TYPE; 45 return doc.evaluate(aQuery, doc, null, xptype, null).singleNodeValue; 46 } 47 48 function setFormValue(aTab, aQuery, aValue) { 49 let node = getElementByXPath(aTab, aQuery); 50 if (typeof aValue == "string") { 51 node.value = aValue; 52 } else if (typeof aValue == "boolean") { 53 node.checked = aValue; 54 } else if (typeof aValue == "number") { 55 node.selectedIndex = aValue; 56 } else { 57 Array.prototype.forEach.call( 58 node.options, 59 (aOpt, aIx) => (aOpt.selected = aValue.indexOf(aIx) > -1) 60 ); 61 } 62 } 63 64 function compareFormValue(aTab, aQuery, aValue) { 65 let node = getElementByXPath(aTab, aQuery); 66 if (!node) { 67 return false; 68 } 69 if (ChromeUtils.getClassName(node) === "HTMLInputElement") { 70 return ( 71 aValue == 72 (node.type == "checkbox" || node.type == "radio" 73 ? node.checked 74 : node.value) 75 ); 76 } 77 if (ChromeUtils.getClassName(node) === "HTMLTextAreaElement") { 78 return aValue == node.value; 79 } 80 if (!node.multiple) { 81 return aValue == node.selectedIndex; 82 } 83 return Array.prototype.every.call( 84 node.options, 85 (aOpt, aIx) => aValue.indexOf(aIx) > -1 == aOpt.selected 86 ); 87 } 88 89 /** 90 * Test (B) : Session data restoration between windows 91 */ 92 93 let rootDir = getRootDirectory(gTestPath); 94 const testURL = rootDir + "browser_248970_b_sample.html"; 95 const testURL2 = 96 "http://mochi.test:8888/browser/" + 97 "browser/components/sessionstore/test/browser_248970_b_sample.html"; 98 99 whenNewWindowLoaded({ private: false }, function (aWin) { 100 windowsToClose.push(aWin); 101 102 // get closed tab count 103 let count = ss.getClosedTabCountForWindow(aWin); 104 let max_tabs_undo = Services.prefs.getIntPref( 105 "browser.sessionstore.max_tabs_undo" 106 ); 107 ok( 108 0 <= count && count <= max_tabs_undo, 109 "getClosedTabCountForWindow should return zero or at most max_tabs_undo" 110 ); 111 112 // setup a state for tab (A) so we can check later that is restored 113 let value = "Value " + Math.random(); 114 let state = { entries: [{ url: testURL }], extData: { key: value } }; 115 116 // public session, add new tab: (A) 117 let tab_A = BrowserTestUtils.addTab(aWin.gBrowser, testURL); 118 ss.setTabState(tab_A, JSON.stringify(state)); 119 promiseBrowserLoaded(tab_A.linkedBrowser).then(() => { 120 // make sure that the next closed tab will increase getClosedTabCountForWindow 121 Services.prefs.setIntPref( 122 "browser.sessionstore.max_tabs_undo", 123 max_tabs_undo + 1 124 ); 125 126 // populate tab_A with form data 127 for (let i in fieldList) { 128 setFormValue(tab_A, i, fieldList[i]); 129 } 130 131 // public session, close tab: (A) 132 aWin.gBrowser.removeTab(tab_A); 133 134 // verify that closedTabCount increased 135 Assert.greater( 136 ss.getClosedTabCountForWindow(aWin), 137 count, 138 "getClosedTabCountForWindow has increased after closing a tab" 139 ); 140 141 // verify tab: (A), in undo list 142 let tab_A_restored = checkNoThrow(() => ss.undoCloseTab(aWin, 0)); 143 ok(tab_A_restored, "a tab is in undo list"); 144 promiseTabRestored(tab_A_restored).then(() => { 145 is( 146 testURL, 147 tab_A_restored.linkedBrowser.currentURI.spec, 148 "it's the same tab that we expect" 149 ); 150 aWin.gBrowser.removeTab(tab_A_restored); 151 152 whenNewWindowLoaded({ private: true }, function (win) { 153 windowsToClose.push(win); 154 155 // setup a state for tab (B) so we can check that its duplicated 156 // properly 157 let key1 = "key1"; 158 let value1 = "Value " + Math.random(); 159 let state1 = { 160 entries: [{ url: testURL2 }], 161 extData: { key1: value1 }, 162 }; 163 164 let tab_B = BrowserTestUtils.addTab(win.gBrowser, testURL2); 165 promiseTabState(tab_B, state1).then(() => { 166 // populate tab: (B) with different form data 167 for (let item in fieldList) { 168 setFormValue(tab_B, item, fieldList[item]); 169 } 170 171 // duplicate tab: (B) 172 let tab_C = win.gBrowser.duplicateTab(tab_B); 173 promiseTabRestored(tab_C).then(() => { 174 // verify the correctness of the duplicated tab 175 is( 176 ss.getCustomTabValue(tab_C, key1), 177 value1, 178 "tab successfully duplicated - correct state" 179 ); 180 181 for (let item in fieldList) { 182 ok( 183 compareFormValue(tab_C, item, fieldList[item]), 184 'The value for "' + item + '" was correctly duplicated' 185 ); 186 } 187 188 // private browsing session, close tab: (C) and (B) 189 win.gBrowser.removeTab(tab_C); 190 win.gBrowser.removeTab(tab_B); 191 192 finish(); 193 }); 194 }); 195 }); 196 }); 197 }); 198 }); 199 }