Remove browser tests - Part 1: The Tests (except for experiments)

This commit is contained in:
NTD 2018-02-03 06:00:38 -05:00 • committed by Roy Tam
commit 261374f310
1697 changed files with 0 additions and 144364 deletions

View file

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"../../../../testing/mochitest/browser.eslintrc.js"
]
};

View file

@ -1,242 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# browser_506482.js is disabled because of frequent failures (bug 538672)
# browser_526613.js is disabled because of frequent failures (bug 534489)
# browser_589246.js is disabled for leaking browser windows (bug 752467)
# browser_580512.js is disabled for leaking browser windows (bug 752467)
[DEFAULT]
support-files =
head.js
content.js
content-forms.js
browser_cookies.sjs
browser_formdata_sample.html
browser_formdata_xpath_sample.html
browser_frametree_sample.html
browser_frametree_sample_frameset.html
browser_frame_history_index.html
browser_frame_history_index2.html
browser_frame_history_index_blank.html
browser_frame_history_a.html
browser_frame_history_b.html
browser_frame_history_c.html
browser_frame_history_c1.html
browser_frame_history_c2.html
browser_form_restore_events_sample.html
browser_formdata_format_sample.html
browser_pageStyle_sample.html
browser_pageStyle_sample_nested.html
browser_sessionHistory_slow.sjs
browser_scrollPositions_sample.html
browser_scrollPositions_sample_frameset.html
browser_scrollPositions_readerModeArticle.html
browser_sessionStorage.html
browser_248970_b_sample.html
browser_339445_sample.html
browser_423132_sample.html
browser_447951_sample.html
browser_454908_sample.html
browser_456342_sample.xhtml
browser_463205_sample.html
browser_463206_sample.html
browser_466937_sample.html
browser_485482_sample.html
browser_637020_slow.sjs
browser_662743_sample.html
browser_739531_sample.html
browser_911547_sample.html
browser_911547_sample.html^headers^
restore_redirect_http.html
restore_redirect_http.html^headers^
restore_redirect_js.html
restore_redirect_target.html
browser_1234021_page.html
#NB: the following are disabled
# browser_464620_a.html
# browser_464620_b.html
# browser_464620_xd.html
#disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html
#disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html
#disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html
[browser_aboutPrivateBrowsing.js]
[browser_aboutSessionRestore.js]
[browser_async_duplicate_tab.js]
[browser_async_flushes.js]
run-if = e10s && crashreporter
skip-if = debug # bug 1167933
[browser_async_remove_tab.js]
run-if = e10s
skip-if = debug # bug 1211084
[browser_attributes.js]
[browser_backup_recovery.js]
[browser_broadcast.js]
[browser_capabilities.js]
[browser_cleaner.js]
[browser_cookies.js]
[browser_crashedTabs.js]
skip-if = !e10s || !crashreporter
[browser_unrestored_crashedTabs.js]
skip-if = !e10s || !crashreporter
[browser_revive_crashed_bg_tabs.js]
skip-if = !e10s || !crashreporter
[browser_dying_cache.js]
[browser_dynamic_frames.js]
[browser_form_restore_events.js]
[browser_formdata.js]
[browser_formdata_cc.js]
[browser_formdata_format.js]
[browser_formdata_xpath.js]
[browser_frametree.js]
[browser_frame_history.js]
[browser_global_store.js]
[browser_history_persist.js]
[browser_label_and_icon.js]
[browser_merge_closed_tabs.js]
[browser_page_title.js]
[browser_pageStyle.js]
[browser_pending_tabs.js]
[browser_privatetabs.js]
[browser_purge_shistory.js]
skip-if = e10s # Bug 1271024
[browser_replace_load.js]
[browser_restore_redirect.js]
[browser_restore_cookies_noOriginAttributes.js]
[browser_scrollPositions.js]
[browser_scrollPositionsReaderMode.js]
[browser_sessionHistory.js]
[browser_sessionStorage.js]
[browser_sessionStorage_size.js]
[browser_swapDocShells.js]
[browser_switch_remoteness.js]
run-if = e10s
[browser_upgrade_backup.js]
[browser_windowRestore_perwindowpb.js]
[browser_248970_b_perwindowpb.js]
# Disabled because of leaks.
# Re-enabling and rewriting this test is tracked in bug 936919.
skip-if = true
[browser_339445.js]
[browser_345898.js]
[browser_350525.js]
[browser_354894_perwindowpb.js]
[browser_367052.js]
[browser_393716.js]
[browser_394759_basic.js]
# Disabled for intermittent failures, bug 944372.
skip-if = true
[browser_394759_behavior.js]
[browser_394759_perwindowpb.js]
[browser_394759_purge.js]
[browser_423132.js]
[browser_447951.js]
[browser_454908.js]
[browser_456342.js]
[browser_461634.js]
[browser_463205.js]
[browser_463206.js]
[browser_464199.js]
[browser_465215.js]
[browser_465223.js]
[browser_466937.js]
[browser_467409-backslashplosion.js]
[browser_477657.js]
[browser_480893.js]
[browser_485482.js]
[browser_485563.js]
[browser_490040.js]
[browser_491168.js]
[browser_491577.js]
[browser_495495.js]
[browser_500328.js]
[browser_514751.js]
[browser_522375.js]
[browser_522545.js]
[browser_524745.js]
[browser_528776.js]
[browser_579868.js]
[browser_579879.js]
skip-if = (os == 'linux' && e10s && (debug||asan)) # Bug 1234404
[browser_581937.js]
[browser_586147.js]
[browser_586068-apptabs.js]
[browser_586068-apptabs_ondemand.js]
[browser_586068-browser_state_interrupted.js]
[browser_586068-cascade.js]
[browser_586068-multi_window.js]
[browser_586068-reload.js]
[browser_586068-select.js]
[browser_586068-window_state.js]
[browser_586068-window_state_override.js]
[browser_588426.js]
[browser_590268.js]
[browser_590563.js]
[browser_595601-restore_hidden.js]
[browser_597071.js]
skip-if = true # Needs to be rewritten as Marionette test, bug 995916
[browser_599909.js]
[browser_600545.js]
[browser_601955.js]
[browser_607016.js]
[browser_615394-SSWindowState_events.js]
[browser_618151.js]
[browser_623779.js]
[browser_624727.js]
[browser_628270.js]
[browser_635418.js]
[browser_636279.js]
[browser_637020.js]
[browser_644409-scratchpads.js]
[browser_645428.js]
[browser_659591.js]
[browser_662743.js]
[browser_662812.js]
[browser_665702-state_session.js]
[browser_682507.js]
[browser_687710.js]
[browser_687710_2.js]
[browser_694378.js]
[browser_701377.js]
[browser_705597.js]
[browser_707862.js]
[browser_739531.js]
[browser_739805.js]
[browser_819510_perwindowpb.js]
skip-if = (os == 'win' && bits == 64) # Bug 1284312
# Disabled for frequent intermittent failures
[browser_464620_a.js]
skip-if = true
[browser_464620_b.js]
skip-if = true
# Disabled on OS X:
[browser_625016.js]
skip-if = os == "mac"
[browser_911547.js]
[browser_send_async_message_oom.js]
[browser_multiple_navigateAndRestore.js]
run-if = e10s
[browser_async_window_flushing.js]
[browser_forget_async_closings.js]
[browser_newtab_userTypedValue.js]
[browser_parentProcessRestoreHash.js]
run-if = e10s
[browser_sessionStoreContainer.js]
[browser_windowStateContainer.js]
[browser_1234021.js]
[browser_remoteness_flip_on_restore.js]
run-if = e10s
[browser_background_tab_crash.js]
run-if = e10s && crashreporter
# Disabled on debug for frequent intermittent failures:
[browser_undoCloseById.js]
skip-if = debug

View file

@ -1,18 +0,0 @@
"use strict";
const PREF = 'network.cookie.cookieBehavior';
const PAGE_URL = 'http://mochi.test:8888/browser/' +
'browser/components/sessionstore/test/browser_1234021_page.html';
const BEHAVIOR_REJECT = 2;
add_task(function* test() {
yield pushPrefs([PREF, BEHAVIOR_REJECT]);
yield BrowserTestUtils.withNewTab({
gBrowser: gBrowser,
url: PAGE_URL
}, function* handler(aBrowser) {
yield TabStateFlusher.flush(aBrowser);
ok(true, "Flush didn't time out");
});
});

View file

@ -1,6 +0,0 @@
<!doctype html>
<html>
<script>
sessionStorage
</script>
</html>

View file

@ -1,166 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test (B) for Bug 248970 **/
waitForExplicitFinish();
let windowsToClose = [];
let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
let filePath = file.path;
let fieldList = {
"//input[@name='input']": Date.now().toString(),
"//input[@name='spaced 1']": Math.random().toString(),
"//input[3]": "three",
"//input[@type='checkbox']": true,
"//input[@name='uncheck']": false,
"//input[@type='radio'][1]": false,
"//input[@type='radio'][2]": true,
"//input[@type='radio'][3]": false,
"//select": 2,
"//select[@multiple]": [1, 3],
"//textarea[1]": "",
"//textarea[2]": "Some text... " + Math.random(),
"//textarea[3]": "Some more text\n" + new Date(),
"//input[@type='file']": filePath
};
registerCleanupFunction(function* () {
for (let win of windowsToClose) {
yield BrowserTestUtils.closeWindow(win);
}
});
function test(aLambda) {
try {
return aLambda() || true;
} catch(ex) { }
return false;
}
function getElementByXPath(aTab, aQuery) {
let doc = aTab.linkedBrowser.contentDocument;
let xptype = Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE;
return doc.evaluate(aQuery, doc, null, xptype, null).singleNodeValue;
}
function setFormValue(aTab, aQuery, aValue) {
let node = getElementByXPath(aTab, aQuery);
if (typeof aValue == "string")
node.value = aValue;
else if (typeof aValue == "boolean")
node.checked = aValue;
else if (typeof aValue == "number")
node.selectedIndex = aValue;
else
Array.forEach(node.options, (aOpt, aIx) =>
(aOpt.selected = aValue.indexOf(aIx) > -1));
}
function compareFormValue(aTab, aQuery, aValue) {
let node = getElementByXPath(aTab, aQuery);
if (!node)
return false;
if (node instanceof Ci.nsIDOMHTMLInputElement)
return aValue == (node.type == "checkbox" || node.type == "radio" ?
node.checked : node.value);
if (node instanceof Ci.nsIDOMHTMLTextAreaElement)
return aValue == node.value;
if (!node.multiple)
return aValue == node.selectedIndex;
return Array.every(node.options, (aOpt, aIx) =>
(aValue.indexOf(aIx) > -1) == aOpt.selected);
}
//////////////////////////////////////////////////////////////////
// Test (B) : Session data restoration between windows //
//////////////////////////////////////////////////////////////////
let rootDir = getRootDirectory(gTestPath);
const testURL = rootDir + "browser_248970_b_sample.html";
const testURL2 = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_248970_b_sample.html";
whenNewWindowLoaded({ private: false }, function(aWin) {
windowsToClose.push(aWin);
// get closed tab count
let count = ss.getClosedTabCount(aWin);
let max_tabs_undo =
Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
ok(0 <= count && count <= max_tabs_undo,
"getClosedTabCount should return zero or at most max_tabs_undo");
// setup a state for tab (A) so we can check later that is restored
let key = "key";
let value = "Value " + Math.random();
let state = { entries: [{ url: testURL }], extData: { key: value } };
// public session, add new tab: (A)
let tab_A = aWin.gBrowser.addTab(testURL);
ss.setTabState(tab_A, JSON.stringify(state));
promiseBrowserLoaded(tab_A.linkedBrowser).then(() => {
// make sure that the next closed tab will increase getClosedTabCount
Services.prefs.setIntPref(
"browser.sessionstore.max_tabs_undo", max_tabs_undo + 1)
// populate tab_A with form data
for (let i in fieldList)
setFormValue(tab_A, i, fieldList[i]);
// public session, close tab: (A)
aWin.gBrowser.removeTab(tab_A);
// verify that closedTabCount increased
ok(ss.getClosedTabCount(aWin) > count,
"getClosedTabCount has increased after closing a tab");
// verify tab: (A), in undo list
let tab_A_restored = test(() => ss.undoCloseTab(aWin, 0));
ok(tab_A_restored, "a tab is in undo list");
promiseTabRestored(tab_A_restored).then(() => {
is(testURL, tab_A_restored.linkedBrowser.currentURI.spec,
"it's the same tab that we expect");
aWin.gBrowser.removeTab(tab_A_restored);
whenNewWindowLoaded({ private: true }, function(aWin) {
windowsToClose.push(aWin);
// setup a state for tab (B) so we can check that its duplicated
// properly
let key1 = "key1";
let value1 = "Value " + Math.random();
let state1 = {
entries: [{ url: testURL2 }], extData: { key1: value1 }
};
let tab_B = aWin.gBrowser.addTab(testURL2);
promiseTabState(tab_B, state1).then(() => {
// populate tab: (B) with different form data
for (let item in fieldList)
setFormValue(tab_B, item, fieldList[item]);
// duplicate tab: (B)
let tab_C = aWin.gBrowser.duplicateTab(tab_B);
promiseTabRestored(tab_C).then(() => {
// verify the correctness of the duplicated tab
is(ss.getTabValue(tab_C, key1), value1,
"tab successfully duplicated - correct state");
for (let item in fieldList)
ok(compareFormValue(tab_C, item, fieldList[item]),
"The value for \"" + item + "\" was correctly duplicated");
// private browsing session, close tab: (C) and (B)
aWin.gBrowser.removeTab(tab_C);
aWin.gBrowser.removeTab(tab_B);
finish();
});
});
});
});
});
});
}

View file

@ -1,37 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<meta charset="utf-8">
<title>Test for bug 248970</title>
<h3>Text Fields</h3>
<input type="text" name="input">
<input type="text" name="spaced 1">
<input>
<h3>Checkboxes and Radio buttons</h3>
<input type="checkbox" name="check"> Check 1
<input type="checkbox" name="uncheck" checked> Check 2
<p>
<input type="radio" name="group" value="1"> Radio 1
<input type="radio" name="group" value="some"> Radio 2
<input type="radio" name="group" checked> Radio 3
<h3>Selects</h3>
<select name="any">
<option value="1"> Select 1
<option value="some"> Select 2
<option>Select 3
</select>
<select multiple="multiple">
<option value=1> Multi-select 1
<option value=2> Multi-select 2
<option value=3> Multi-select 3
<option value=4> Multi-select 4
</select>
<h3>Text Areas</h3>
<textarea name="testarea"></textarea>
<textarea name="sized one" rows="5" cols="25"></textarea>
<textarea></textarea>
<h3>File Selector</h3>
<input type="file">

View file

@ -1,32 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
add_task(function* test() {
/** Test for Bug 339445 **/
let testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_339445_sample.html";
let tab = gBrowser.addTab(testURL);
yield promiseBrowserLoaded(tab.linkedBrowser);
yield ContentTask.spawn(tab.linkedBrowser, null, function() {
let doc = content.document;
is(doc.getElementById("storageTestItem").textContent, "PENDING",
"sessionStorage value has been set");
});
let tab2 = gBrowser.duplicateTab(tab);
yield promiseTabRestored(tab2);
yield ContentTask.spawn(tab2.linkedBrowser, null, function() {
let doc2 = content.document;
is(doc2.getElementById("storageTestItem").textContent, "SUCCESS",
"sessionStorage value has been duplicated");
});
// clean up
yield Promise.all([ BrowserTestUtils.removeTab(tab2),
BrowserTestUtils.removeTab(tab) ]);
});

View file

@ -1,18 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<meta charset="utf-8">
<title>Test for bug 339445</title>
storageTestItem = <span id="storageTestItem">FAIL</span>
<!--
storageTestItem's textContent will be one of the following:
* FAIL : sessionStorage wasn't available
* PENDING : the test value has been initialized on first load
* SUCCESS : the test value was correctly retrieved
-->
<script type="application/javascript">
document.getElementById("storageTestItem").textContent =
sessionStorage["storageTestItem"] || "PENDING";
sessionStorage["storageTestItem"] = "SUCCESS";
</script>

View file

@ -1,44 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 345898 **/
function test(aLambda) {
try {
aLambda();
return false;
}
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE" ||
ex.name == "NS_ERROR_FAILURE";
}
}
// all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
ok(test(() => ss.getWindowState({})),
"Invalid window for getWindowState throws");
ok(test(() => ss.setWindowState({}, "", false)),
"Invalid window for setWindowState throws");
ok(test(() => ss.getTabState({})),
"Invalid tab for getTabState throws");
ok(test(() => ss.setTabState({}, "{}")),
"Invalid tab state for setTabState throws");
ok(test(() => ss.setTabState({}, JSON.stringify({ entries: [] }))),
"Invalid tab for setTabState throws");
ok(test(() => ss.duplicateTab({}, {})),
"Invalid tab for duplicateTab throws");
ok(test(() => ss.duplicateTab({}, gBrowser.selectedTab)),
"Invalid window for duplicateTab throws");
ok(test(() => ss.getClosedTabData({})),
"Invalid window for getClosedTabData throws");
ok(test(() => ss.undoCloseTab({}, 0)),
"Invalid window for undoCloseTab throws");
ok(test(() => ss.undoCloseTab(window, -1)),
"Invalid index for undoCloseTab throws");
ok(test(() => ss.getWindowValue({}, "")),
"Invalid window for getWindowValue throws");
ok(test(() => ss.setWindowValue({}, "", "")),
"Invalid window for setWindowValue throws");
}

View file

@ -1,102 +0,0 @@
"use strict";
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["dom.ipc.processCount", 1]]
});
})
add_task(function* () {
/** Test for Bug 350525 **/
function test(aLambda) {
try {
return aLambda() || true;
}
catch (ex) { }
return false;
}
////////////////////////////
// setWindowValue, et al. //
////////////////////////////
let key = "Unique name: " + Date.now();
let value = "Unique value: " + Math.random();
// test adding
ok(test(() => ss.setWindowValue(window, key, value)), "set a window value");
// test retrieving
is(ss.getWindowValue(window, key), value, "stored window value matches original");
// test deleting
ok(test(() => ss.deleteWindowValue(window, key)), "delete the window value");
// value should not exist post-delete
is(ss.getWindowValue(window, key), "", "window value was deleted");
// test deleting a non-existent value
ok(test(() => ss.deleteWindowValue(window, key)), "delete non-existent window value");
/////////////////////////
// setTabValue, et al. //
/////////////////////////
key = "Unique name: " + Math.random();
value = "Unique value: " + Date.now();
let tab = gBrowser.addTab();
tab.linkedBrowser.stop();
// test adding
ok(test(() => ss.setTabValue(tab, key, value)), "store a tab value");
// test retrieving
is(ss.getTabValue(tab, key), value, "stored tab value match original");
// test deleting
ok(test(() => ss.deleteTabValue(tab, key)), "delete the tab value");
// value should not exist post-delete
is(ss.getTabValue(tab, key), "", "tab value was deleted");
// test deleting a non-existent value
ok(test(() => ss.deleteTabValue(tab, key)), "delete non-existent tab value");
// clean up
yield promiseRemoveTab(tab);
/////////////////////////////////////
// getClosedTabCount, undoCloseTab //
/////////////////////////////////////
// get closed tab count
let count = ss.getClosedTabCount(window);
let max_tabs_undo = gPrefService.getIntPref("browser.sessionstore.max_tabs_undo");
ok(0 <= count && count <= max_tabs_undo,
"getClosedTabCount returns zero or at most max_tabs_undo");
// create a new tab
let testURL = "about:";
tab = gBrowser.addTab(testURL);
yield promiseBrowserLoaded(tab.linkedBrowser);
// make sure that the next closed tab will increase getClosedTabCount
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
registerCleanupFunction(() => gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo"));
// remove tab
yield promiseRemoveTab(tab);
// getClosedTabCount
let newcount = ss.getClosedTabCount(window);
ok(newcount > count, "after closing a tab, getClosedTabCount has been incremented");
// undoCloseTab
tab = test(() => ss.undoCloseTab(window, 0));
ok(tab, "undoCloseTab doesn't throw")
yield promiseTabRestored(tab);
is(tab.linkedBrowser.currentURI.spec, testURL, "correct tab was reopened");
// clean up
gBrowser.removeTab(tab);
});

View file

@ -1,474 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Checks that restoring the last browser window in session is actually
* working.
*
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=354894
* @note It is implicitly tested that restoring the last window works when
* non-browser windows are around. The "Run Tests" window as well as the main
* browser window (wherein the test code gets executed) won't be considered
* browser windows. To achiveve this said main browser window has it's windowtype
* attribute modified so that it's not considered a browser window any longer.
* This is crucial, because otherwise there would be two browser windows around,
* said main test window and the one opened by the tests, and hence the new
* logic wouldn't be executed at all.
* @note Mac only tests the new notifications, as restoring the last window is
* not enabled on that platform (platform shim; the application is kept running
* although there are no windows left)
* @note There is a difference when closing a browser window with
* BrowserTryToCloseWindow() as opposed to close(). The former will make
* nsSessionStore restore a window next time it gets a chance and will post
* notifications. The latter won't.
*/
// Some urls that might be opened in tabs and/or popups
// Do not use about:blank:
// That one is reserved for special purposes in the tests
const TEST_URLS = ["about:mozilla", "about:buildconfig"];
// Number of -request notifications to except
// remember to adjust when adding new tests
const NOTIFICATIONS_EXPECTED = 6;
// Window features of popup windows
const POPUP_FEATURES = "toolbar=no,resizable=no,status=no";
// Window features of browser windows
const CHROME_FEATURES = "chrome,all,dialog=no";
const IS_MAC = navigator.platform.match(/Mac/);
/**
* Returns an Object with two properties:
* open (int):
* A count of how many non-closed navigator:browser windows there are.
* winstates (int):
* A count of how many windows there are in the SessionStore state.
*/
function getBrowserWindowsCount() {
let open = 0;
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
if (!e.getNext().closed)
++open;
}
let winstates = JSON.parse(ss.getBrowserState()).windows.length;
return { open, winstates };
}
add_task(function* setup() {
// Make sure we've only got one browser window to start with
let { open, winstates } = getBrowserWindowsCount();
is(open, 1, "Should only be one open window");
is(winstates, 1, "Should only be one window state in SessionStore");
// This test takes some time to run, and it could timeout randomly.
// So we require a longer timeout. See bug 528219.
requestLongerTimeout(3);
// Make the main test window not count as a browser window any longer
let oldWinType = document.documentElement.getAttribute("windowtype");
document.documentElement.setAttribute("windowtype", "navigator:testrunner");
registerCleanupFunction(() => {
document.documentElement.setAttribute("windowtype", "navigator:browser");
});
});
/**
* Sets up one of our tests by setting the right preferences, and
* then opening up a browser window preloaded with some tabs.
*
* @param options (Object)
* An object that can contain the following properties:
*
* private:
* Whether or not the opened window should be private.
*
* denyFirst:
* Whether or not the first window that attempts to close
* via closeWindowForRestoration should be denied.
*
* @param testFunction (Function*)
* A generator function that yields Promises to be run
* once the test has been set up.
*
* @returns Promise
* Resolves once the test has been cleaned up.
*/
let setupTest = Task.async(function*(options, testFunction) {
yield pushPrefs(["browser.startup.page", 3],
["browser.tabs.warnOnClose", false]);
// Observe these, and also use to count the number of hits
let observing = {
"browser-lastwindow-close-requested": 0,
"browser-lastwindow-close-granted": 0
};
/**
* Helper: Will observe and handle the notifications for us
*/
let hitCount = 0;
function observer(aCancel, aTopic, aData) {
// count so that we later may compare
observing[aTopic]++;
// handle some tests
if (options.denyFirst && ++hitCount == 1) {
aCancel.QueryInterface(Ci.nsISupportsPRBool).data = true;
}
}
for (let o in observing) {
Services.obs.addObserver(observer, o, false);
}
let private = options.private || false;
let newWin = yield promiseNewWindowLoaded({ private });
injectTestTabs(newWin);
yield testFunction(newWin, observing);
let count = getBrowserWindowsCount();
is(count.open, 0, "Got right number of open windows");
is(count.winstates, 1, "Got right number of stored window states");
for (let o in observing) {
Services.obs.removeObserver(observer, o);
}
yield popPrefs();
});
/**
* Loads a TEST_URLS into a browser window.
*
* @param win (Window)
* The browser window to load the tabs in
*/
function injectTestTabs(win) {
TEST_URLS.forEach(function (url) {
win.gBrowser.addTab(url);
});
}
/**
* Attempts to close a window via BrowserTryToCloseWindow so that
* we get the browser-lastwindow-close-requested and
* browser-lastwindow-close-granted observer notifications.
*
* @param win (Window)
* The window to try to close
* @returns Promise
* Resolves to true if the window closed, or false if the window
* was denied the ability to close.
*/
function closeWindowForRestoration(win) {
return new Promise((resolve) => {
let closePromise = BrowserTestUtils.windowClosed(win);
win.BrowserTryToCloseWindow();
if (!win.closed) {
resolve(false);
return;
}
closePromise.then(() => {
resolve(true);
});
});
}
/**
* Normal in-session restore
*
* @note: Non-Mac only
*
* Should do the following:
* 1. Open a new browser window
* 2. Add some tabs
* 3. Close that window
* 4. Opening another window
* 5. Checks that state is restored
*/
add_task(function* test_open_close_normal() {
if (IS_MAC) {
return;
}
yield setupTest({ denyFirst: true }, function*(newWin, obs) {
let closed = yield closeWindowForRestoration(newWin);
ok(!closed, "First close request should have been denied");
closed = yield closeWindowForRestoration(newWin);
ok(closed, "Second close request should be accepted");
newWin = yield promiseNewWindowLoaded();
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 2,
"Restored window in-session with otherpopup windows around");
// Note that this will not result in the the browser-lastwindow-close
// notifications firing for this other newWin.
yield BrowserTestUtils.closeWindow(newWin);
// setupTest gave us a window which was denied for closing once, and then
// closed.
is(obs["browser-lastwindow-close-requested"], 2,
"Got expected browser-lastwindow-close-requested notifications");
is(obs["browser-lastwindow-close-granted"], 1,
"Got expected browser-lastwindow-close-granted notifications");
});
});
/**
* PrivateBrowsing in-session restore
*
* @note: Non-Mac only
*
* Should do the following:
* 1. Open a new browser window A
* 2. Add some tabs
* 3. Close the window A as the last window
* 4. Open a private browsing window B
* 5. Make sure that B didn't restore the tabs from A
* 6. Close private browsing window B
* 7. Open a new window C
* 8. Make sure that new window C has restored tabs from A
*/
add_task(function* test_open_close_private_browsing() {
if (IS_MAC) {
return;
}
yield setupTest({}, function*(newWin, obs) {
let closed = yield closeWindowForRestoration(newWin);
ok(closed, "Should be able to close the window");
newWin = yield promiseNewWindowLoaded({private: true});
is(newWin.gBrowser.browsers.length, 1,
"Did not restore in private browing mode");
closed = yield closeWindowForRestoration(newWin);
ok(closed, "Should be able to close the window");
newWin = yield promiseNewWindowLoaded();
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 2,
"Restored tabs in a new non-private window");
// Note that this will not result in the the browser-lastwindow-close
// notifications firing for this other newWin.
yield BrowserTestUtils.closeWindow(newWin);
// We closed two windows with closeWindowForRestoration, and both
// should have been successful.
is(obs["browser-lastwindow-close-requested"], 2,
"Got expected browser-lastwindow-close-requested notifications");
is(obs["browser-lastwindow-close-granted"], 2,
"Got expected browser-lastwindow-close-granted notifications");
});
});
/**
* Open some popup windows to check those aren't restored, but the browser
* window is.
*
* @note: Non-Mac only
*
* Should do the following:
* 1. Open a new browser window
* 2. Add some tabs
* 3. Open some popups
* 4. Add another tab to one popup (so that it gets stored) and close it again
* 5. Close the browser window
* 6. Open another browser window
* 7. Make sure that the tabs of the closed browser window, but not the popup,
* are restored
*/
add_task(function* test_open_close_window_and_popup() {
if (IS_MAC) {
return;
}
yield setupTest({}, function*(newWin, obs) {
let popupPromise = BrowserTestUtils.waitForNewWindow();
openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[0]);
let popup = yield popupPromise;
let popup2Promise = BrowserTestUtils.waitForNewWindow();
openDialog(location, "popup2", POPUP_FEATURES, TEST_URLS[1]);
let popup2 = yield popup2Promise;
popup2.gBrowser.addTab(TEST_URLS[0]);
let closed = yield closeWindowForRestoration(newWin);
ok(closed, "Should be able to close the window");
yield BrowserTestUtils.closeWindow(popup2);
newWin = yield promiseNewWindowLoaded();
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 2,
"Restored window and associated tabs in session");
yield BrowserTestUtils.closeWindow(popup);
yield BrowserTestUtils.closeWindow(newWin);
// We closed one window with closeWindowForRestoration, and it should
// have been successful.
is(obs["browser-lastwindow-close-requested"], 1,
"Got expected browser-lastwindow-close-requested notifications");
is(obs["browser-lastwindow-close-granted"], 1,
"Got expected browser-lastwindow-close-granted notifications");
});
});
/**
* Open some popup window to check it isn't restored. Instead nothing at all
* should be restored
*
* @note: Non-Mac only
*
* Should do the following:
* 1. Open a popup
* 2. Add another tab to the popup (so that it gets stored) and close it again
* 3. Open a window
* 4. Check that nothing at all is restored
* 5. Open two browser windows and close them again
* 6. undoCloseWindow() one
* 7. Open another browser window
* 8. Check that nothing at all is restored
*/
add_task(function* test_open_close_only_popup() {
if (IS_MAC) {
return;
}
yield setupTest({}, function*(newWin, obs) {
// We actually don't care about the initial window in this test.
yield BrowserTestUtils.closeWindow(newWin);
// This will cause nsSessionStore to restore a window the next time it
// gets a chance.
let popupPromise = BrowserTestUtils.waitForNewWindow();
openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]);
let popup = yield popupPromise;
is(popup.gBrowser.browsers.length, 1,
"Did not restore the popup window (1)");
let closed = yield closeWindowForRestoration(popup);
ok(closed, "Should be able to close the window");
popupPromise = BrowserTestUtils.waitForNewWindow();
openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]);
popup = yield popupPromise;
popup.gBrowser.addTab(TEST_URLS[0]);
is(popup.gBrowser.browsers.length, 2,
"Did not restore to the popup window (2)");
yield BrowserTestUtils.closeWindow(popup);
newWin = yield promiseNewWindowLoaded();
isnot(newWin.gBrowser.browsers.length, 2,
"Did not restore the popup window");
is(TEST_URLS.indexOf(newWin.gBrowser.browsers[0].currentURI.spec), -1,
"Did not restore the popup window (2)");
yield BrowserTestUtils.closeWindow(newWin);
// We closed one popup window with closeWindowForRestoration, and popup
// windows should never fire the browser-lastwindow notifications.
is(obs["browser-lastwindow-close-requested"], 0,
"Got expected browser-lastwindow-close-requested notifications");
is(obs["browser-lastwindow-close-granted"], 0,
"Got expected browser-lastwindow-close-granted notifications");
});
});
/**
* Open some windows and do undoCloseWindow. This should prevent any
* restoring later in the test
*
* @note: Non-Mac only
*
* Should do the following:
* 1. Open two browser windows and close them again
* 2. undoCloseWindow() one
* 3. Open another browser window
* 4. Make sure nothing at all is restored
*/
add_task(function* test_open_close_restore_from_popup() {
if (IS_MAC) {
return;
}
yield setupTest({}, function*(newWin, obs) {
let newWin2 = yield promiseNewWindowLoaded();
yield injectTestTabs(newWin2);
let closed = yield closeWindowForRestoration(newWin);
ok(closed, "Should be able to close the window");
closed = yield closeWindowForRestoration(newWin2);
ok(closed, "Should be able to close the window");
let counts = getBrowserWindowsCount();
is(counts.open, 0, "Got right number of open windows");
is(counts.winstates, 1, "Got right number of window states");
newWin = undoCloseWindow(0);
yield BrowserTestUtils.waitForEvent(newWin, "load");
// Make sure we wait until this window is restored.
yield BrowserTestUtils.waitForEvent(newWin.gBrowser.tabContainer,
"SSTabRestored");
newWin2 = yield promiseNewWindowLoaded();
is(newWin2.gBrowser.browsers.length, 1,
"Did not restore, as undoCloseWindow() was last called");
is(TEST_URLS.indexOf(newWin2.gBrowser.browsers[0].currentURI.spec), -1,
"Did not restore, as undoCloseWindow() was last called (2)");
counts = getBrowserWindowsCount();
is(counts.open, 2, "Got right number of open windows");
is(counts.winstates, 3, "Got right number of window states");
yield BrowserTestUtils.closeWindow(newWin);
yield BrowserTestUtils.closeWindow(newWin2);
counts = getBrowserWindowsCount();
is(counts.open, 0, "Got right number of open windows");
is(counts.winstates, 1, "Got right number of window states");
});
});
/**
* Test if closing can be denied on Mac.
* @note: Mac only
*/
add_task(function* test_mac_notifications() {
if (!IS_MAC) {
return;
}
yield setupTest({ denyFirst: true }, function*(newWin, obs) {
let closed = yield closeWindowForRestoration(newWin);
ok(!closed, "First close attempt should be denied");
closed = yield closeWindowForRestoration(newWin);
ok(closed, "Second close attempt should be granted");
// We tried closing once, and got denied. Then we tried again and
// succeeded. That means 2 close requests, and 1 close granted.
is(obs["browser-lastwindow-close-requested"], 2,
"Got expected browser-lastwindow-close-requested notifications");
is(obs["browser-lastwindow-close-granted"], 1,
"Got expected browser-lastwindow-close-granted notifications");
});
});

View file

@ -1,41 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function* () {
// make sure that the next closed tab will increase getClosedTabCount
let max_tabs_undo = gPrefService.getIntPref("browser.sessionstore.max_tabs_undo");
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
registerCleanupFunction(() => gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo"));
// Empty the list of closed tabs.
while (ss.getClosedTabCount(window)) {
ss.forgetClosedTab(window, 0);
}
// restore a blank tab
let tab = gBrowser.addTab("about:");
yield promiseBrowserLoaded(tab.linkedBrowser);
let count = yield promiseSHistoryCount(tab.linkedBrowser);
ok(count >= 1, "the new tab does have at least one history entry");
yield promiseTabState(tab, {entries: []});
// We may have a different sessionHistory object if the tab
// switched from non-remote to remote.
count = yield promiseSHistoryCount(tab.linkedBrowser);
is(count, 0, "the tab was restored without any history whatsoever");
yield promiseRemoveTab(tab);
is(ss.getClosedTabCount(window), 0,
"The closed blank tab wasn't added to Recently Closed Tabs");
});
function promiseSHistoryCount(browser) {
return ContentTask.spawn(browser, null, function* () {
return docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory.count;
});
}

View file

@ -1,71 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = "about:config";
/**
* Bug 393716 - Basic tests for getTabState(), setTabState(), and duplicateTab().
*/
add_task(function test_set_tabstate() {
let key = "Unique key: " + Date.now();
let value = "Unique value: " + Math.random();
// create a new tab
let tab = gBrowser.addTab(URL);
ss.setTabValue(tab, key, value);
yield promiseBrowserLoaded(tab.linkedBrowser);
// get the tab's state
yield TabStateFlusher.flush(tab.linkedBrowser);
let state = ss.getTabState(tab);
ok(state, "get the tab's state");
// verify the tab state's integrity
state = JSON.parse(state);
ok(state instanceof Object && state.entries instanceof Array && state.entries.length > 0,
"state object seems valid");
ok(state.entries.length == 1 && state.entries[0].url == URL,
"Got the expected state object (test URL)");
ok(state.extData && state.extData[key] == value,
"Got the expected state object (test manually set tab value)");
// clean up
gBrowser.removeTab(tab);
});
add_task(function test_set_tabstate_and_duplicate() {
let key2 = "key2";
let value2 = "Value " + Math.random();
let value3 = "Another value: " + Date.now();
let state = { entries: [{ url: URL }], extData: { key2: value2 } };
// create a new tab
let tab = gBrowser.addTab();
// set the tab's state
ss.setTabState(tab, JSON.stringify(state));
yield promiseBrowserLoaded(tab.linkedBrowser);
// verify the correctness of the restored tab
ok(ss.getTabValue(tab, key2) == value2 && tab.linkedBrowser.currentURI.spec == URL,
"the tab's state was correctly restored");
// add text data
yield setInputValue(tab.linkedBrowser, {id: "textbox", value: value3});
// duplicate the tab
let tab2 = ss.duplicateTab(window, tab);
yield promiseTabRestored(tab2);
// verify the correctness of the duplicated tab
ok(ss.getTabValue(tab2, key2) == value2 &&
tab2.linkedBrowser.currentURI.spec == URL,
"correctly duplicated the tab's state");
let textbox = yield getInputValue(tab2.linkedBrowser, {id: "textbox"});
is(textbox, value3, "also duplicated text data");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
});

View file

@ -1,92 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const TEST_URL = "data:text/html;charset=utf-8,<input%20id=txt>" +
"<input%20type=checkbox%20id=chk>";
Cu.import("resource:///modules/sessionstore/SessionStore.jsm");
/**
* This test ensures that closing a window is a reversible action. We will
* close the the window, restore it and check that all data has been restored.
* This includes window-specific data as well as form data for tabs.
*/
function test() {
waitForExplicitFinish();
let uniqueKey = "bug 394759";
let uniqueValue = "unik" + Date.now();
let uniqueText = "pi != " + Math.random();
// Clear the list of closed windows.
forgetClosedWindows();
provideWindow(function onTestURLLoaded(newWin) {
newWin.gBrowser.addTab().linkedBrowser.stop();
// Mark the window with some unique data to be restored later on.
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
let [txt, chk] = newWin.content.document.querySelectorAll("#txt, #chk");
txt.value = uniqueText;
let browser = newWin.gBrowser.selectedBrowser;
setInputChecked(browser, {id: "chk", checked: true}).then(() => {
BrowserTestUtils.closeWindow(newWin).then(() => {
is(ss.getClosedWindowCount(), 1,
"The closed window was added to Recently Closed Windows");
let data = SessionStore.getClosedWindowData(false);
// Verify that non JSON serialized data is the same as JSON serialized data.
is(JSON.stringify(data), ss.getClosedWindowData(),
"Non-serialized data is the same as serialized data")
ok(data[0].title == TEST_URL && JSON.stringify(data[0]).indexOf(uniqueText) > -1,
"The closed window data was stored correctly");
// Reopen the closed window and ensure its integrity.
let newWin2 = ss.undoCloseWindow(0);
ok(newWin2 instanceof ChromeWindow,
"undoCloseWindow actually returned a window");
is(ss.getClosedWindowCount(), 0,
"The reopened window was removed from Recently Closed Windows");
// SSTabRestored will fire more than once, so we need to make sure we count them.
let restoredTabs = 0;
let expectedTabs = data[0].tabs.length;
newWin2.addEventListener("SSTabRestored", function sstabrestoredListener(aEvent) {
++restoredTabs;
info("Restored tab " + restoredTabs + "/" + expectedTabs);
if (restoredTabs < expectedTabs) {
return;
}
is(restoredTabs, expectedTabs, "Correct number of tabs restored");
newWin2.removeEventListener("SSTabRestored", sstabrestoredListener, true);
is(newWin2.gBrowser.tabs.length, 2,
"The window correctly restored 2 tabs");
is(newWin2.gBrowser.currentURI.spec, TEST_URL,
"The window correctly restored the URL");
let [txt, chk] = newWin2.content.document.querySelectorAll("#txt, #chk");
ok(txt.value == uniqueText && chk.checked,
"The window correctly restored the form");
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
"The window correctly restored the data associated with it");
// Clean up.
BrowserTestUtils.closeWindow(newWin2).then(finish);
}, true);
});
});
}, TEST_URL);
}
function setInputChecked(browser, data) {
return sendMessage(browser, "ss-test:setInputChecked", data);
}

View file

@ -1,76 +0,0 @@
/**
* Test helper function that opens a series of windows, closes them
* and then checks the closed window data from SessionStore against
* expected results.
*
* @param windowsToOpen (Array)
* An array of Objects, where each object must define a single
* property "isPopup" for whether or not the opened window should
* be a popup.
* @param expectedResults (Array)
* An Object with two properies: mac and other, where each points
* at yet another Object, with the following properties:
*
* popup (int):
* The number of popup windows we expect to be in the closed window
* data.
* normal (int):
* The number of normal windows we expect to be in the closed window
* data.
* @returns Promise
*/
function testWindows(windowsToOpen, expectedResults) {
return Task.spawn(function*() {
for (let winData of windowsToOpen) {
let features = "chrome,dialog=no," +
(winData.isPopup ? "all=no" : "all");
let url = "http://example.com/?window=" + windowsToOpen.length;
let openWindowPromise = BrowserTestUtils.waitForNewWindow(true, url);
openDialog(getBrowserURL(), "", features, url);
let win = yield openWindowPromise;
yield BrowserTestUtils.closeWindow(win);
}
let closedWindowData = JSON.parse(ss.getClosedWindowData());
let numPopups = closedWindowData.filter(function(el, i, arr) {
return el.isPopup;
}).length;
let numNormal = ss.getClosedWindowCount() - numPopups;
// #ifdef doesn't work in browser-chrome tests, so do a simple regex on platform
let oResults = navigator.platform.match(/Mac/) ? expectedResults.mac
: expectedResults.other;
is(numPopups, oResults.popup,
"There were " + oResults.popup + " popup windows to reopen");
is(numNormal, oResults.normal,
"There were " + oResults.normal + " normal windows to repoen");
});
}
add_task(function* test_closed_window_states() {
// This test takes quite some time, and timeouts frequently, so we require
// more time to run.
// See Bug 518970.
requestLongerTimeout(2);
let windowsToOpen = [{isPopup: false},
{isPopup: false},
{isPopup: true},
{isPopup: true},
{isPopup: true}];
let expectedResults = {mac: {popup: 3, normal: 0},
other: {popup: 3, normal: 1}};
yield testWindows(windowsToOpen, expectedResults);
let windowsToOpen2 = [{isPopup: false},
{isPopup: false},
{isPopup: false},
{isPopup: false},
{isPopup: false}];
let expectedResults2 = {mac: {popup: 0, normal: 3},
other: {popup: 0, normal: 3}};
yield testWindows(windowsToOpen2, expectedResults2);
});

View file

@ -1,55 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const TESTS = [
{ url: "about:config",
key: "bug 394759 Non-PB",
value: "uniq" + r() },
{ url: "about:mozilla",
key: "bug 394759 PB",
value: "uniq" + r() },
];
function promiseTestOpenCloseWindow(aIsPrivate, aTest) {
return Task.spawn(function*() {
let win = yield BrowserTestUtils.openNewBrowserWindow({ "private": aIsPrivate });
win.gBrowser.selectedBrowser.loadURI(aTest.url);
yield promiseBrowserLoaded(win.gBrowser.selectedBrowser);
yield Promise.resolve();
// Mark the window with some unique data to be restored later on.
ss.setWindowValue(win, aTest.key, aTest.value);
yield TabStateFlusher.flushWindow(win);
// Close.
yield BrowserTestUtils.closeWindow(win);
});
}
function promiseTestOnWindow(aIsPrivate, aValue) {
return Task.spawn(function*() {
let win = yield BrowserTestUtils.openNewBrowserWindow({ "private": aIsPrivate });
yield TabStateFlusher.flushWindow(win);
let data = JSON.parse(ss.getClosedWindowData())[0];
is(ss.getClosedWindowCount(), 1, "Check that the closed window count hasn't changed");
ok(JSON.stringify(data).indexOf(aValue) > -1,
"Check the closed window data was stored correctly");
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
});
}
add_task(function* init() {
forgetClosedWindows();
while (ss.getClosedTabCount(window) > 0) {
ss.forgetClosedTab(window, 0);
}
});
add_task(function* main() {
yield promiseTestOpenCloseWindow(false, TESTS[0]);
yield promiseTestOpenCloseWindow(true, TESTS[1]);
yield promiseTestOnWindow(false, TESTS[0].value);
yield promiseTestOnWindow(true, TESTS[0].value);
});

View file

@ -1,130 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
function waitForClearHistory(aCallback) {
let observer = {
observe: function(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, "browser:purge-domain-data");
setTimeout(aCallback, 0);
}
};
Services.obs.addObserver(observer, "browser:purge-domain-data", false);
}
function test() {
waitForExplicitFinish();
// utility functions
function countClosedTabsByTitle(aClosedTabList, aTitle) {
return aClosedTabList.filter(aData => aData.title == aTitle).length;
}
function countOpenTabsByTitle(aOpenTabList, aTitle) {
return aOpenTabList.filter(aData => aData.entries.some(aEntry => aEntry.title == aTitle)).length;
}
// backup old state
let oldState = ss.getBrowserState();
let oldState_wins = JSON.parse(oldState).windows.length;
if (oldState_wins != 1)
ok(false, "oldState in test_purge has " + oldState_wins + " windows instead of 1");
// create a new state for testing
const REMEMBER = Date.now(), FORGET = Math.random();
let testState = {
windows: [ { tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 } ],
_closedWindows : [
// _closedWindows[0]
{
tabs: [
{ entries: [{ url: "http://example.com/", title: REMEMBER }] },
{ entries: [{ url: "http://mozilla.org/", title: FORGET }] }
],
selected: 2,
title: "mozilla.org",
_closedTabs: []
},
// _closedWindows[1]
{
tabs: [
{ entries: [{ url: "http://mozilla.org/", title: FORGET }] },
{ entries: [{ url: "http://example.com/", title: REMEMBER }] },
{ entries: [{ url: "http://example.com/", title: REMEMBER }] },
{ entries: [{ url: "http://mozilla.org/", title: FORGET }] },
{ entries: [{ url: "http://example.com/", title: REMEMBER }] }
],
selected: 5,
_closedTabs: []
},
// _closedWindows[2]
{
tabs: [
{ entries: [{ url: "http://example.com/", title: REMEMBER }] }
],
selected: 1,
_closedTabs: [
{
state: {
entries: [
{ url: "http://mozilla.org/", title: FORGET },
{ url: "http://mozilla.org/again", title: "doesn't matter" }
]
},
pos: 1,
title: FORGET
},
{
state: {
entries: [
{ url: "http://example.com", title: REMEMBER }
]
},
title: REMEMBER
}
]
}
]
};
// set browser to test state
ss.setBrowserState(JSON.stringify(testState));
// purge domain & check that we purged correctly for closed windows
ForgetAboutSite.removeDataFromDomain("mozilla.org");
waitForClearHistory(function() {
let closedWindowData = JSON.parse(ss.getClosedWindowData());
// First set of tests for _closedWindows[0] - tests basics
let win = closedWindowData[0];
is(win.tabs.length, 1, "1 tab was removed");
is(countOpenTabsByTitle(win.tabs, FORGET), 0,
"The correct tab was removed");
is(countOpenTabsByTitle(win.tabs, REMEMBER), 1,
"The correct tab was remembered");
is(win.selected, 1, "Selected tab has changed");
is(win.title, REMEMBER, "The window title was correctly updated");
// Test more complicated case
win = closedWindowData[1];
is(win.tabs.length, 3, "2 tabs were removed");
is(countOpenTabsByTitle(win.tabs, FORGET), 0,
"The correct tabs were removed");
is(countOpenTabsByTitle(win.tabs, REMEMBER), 3,
"The correct tabs were remembered");
is(win.selected, 3, "Selected tab has changed");
is(win.title, REMEMBER, "The window title was correctly updated");
// Tests handling of _closedTabs
win = closedWindowData[2];
is(countClosedTabsByTitle(win._closedTabs, REMEMBER), 1,
"The correct number of tabs were removed, and the correct ones");
is(countClosedTabsByTitle(win._closedTabs, FORGET), 0,
"All tabs to be forgotten were indeed removed");
// restore pre-test state
ss.setBrowserState(oldState);
finish();
});
}

View file

@ -1,59 +0,0 @@
"use strict";
/**
* Tests that cookies are stored and restored correctly
* by sessionstore (bug 423132).
*/
add_task(function*() {
const testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_423132_sample.html";
Services.cookies.removeAll();
// make sure that sessionstore.js can be forced to be created by setting
// the interval pref to 0
yield SpecialPowers.pushPrefEnv({
set: [["browser.sessionstore.interval", 0]]
});
let win = yield BrowserTestUtils.openNewBrowserWindow();
let browser = win.gBrowser.selectedBrowser;
browser.loadURI(testURL);
yield BrowserTestUtils.browserLoaded(browser);
yield TabStateFlusher.flush(browser);
// get the sessionstore state for the window
let state = ss.getWindowState(win);
// verify our cookie got set during pageload
let enumerator = Services.cookies.enumerator;
let cookie;
let i = 0;
while (enumerator.hasMoreElements()) {
cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
i++;
}
Assert.equal(i, 1, "expected one cookie");
// remove the cookie
Services.cookies.removeAll();
// restore the window state
ss.setWindowState(win, state, true);
// at this point, the cookie should be restored...
enumerator = Services.cookies.enumerator;
let cookie2;
while (enumerator.hasMoreElements()) {
cookie2 = enumerator.getNext().QueryInterface(Ci.nsICookie);
if (cookie.name == cookie2.name)
break;
}
is(cookie.name, cookie2.name, "cookie name successfully restored");
is(cookie.value, cookie2.value, "cookie value successfully restored");
is(cookie.path, cookie2.path, "cookie path successfully restored");
// clean up
Services.cookies.removeAll();
yield BrowserTestUtils.closeWindow(win);
});

View file

@ -1,14 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
// generate an enormous random number...
var r = Math.floor(Math.random() * Math.pow(2, 62)).toString();
// ... and use it to set a randomly named cookie
document.cookie = r + "=value; path=/ohai";
</script>
<body>
</body>
</html>

View file

@ -1,65 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 447951 **/
waitForExplicitFinish();
const baseURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_447951_sample.html#";
// Make sure the functionality added in bug 943339 doesn't affect the results
gPrefService.setIntPref("browser.sessionstore.max_serialize_back", -1);
gPrefService.setIntPref("browser.sessionstore.max_serialize_forward", -1);
registerCleanupFunction(function () {
gPrefService.clearUserPref("browser.sessionstore.max_serialize_back");
gPrefService.clearUserPref("browser.sessionstore.max_serialize_forward");
});
let tab = gBrowser.addTab();
promiseBrowserLoaded(tab.linkedBrowser).then(() => {
let tabState = { entries: [] };
let max_entries = gPrefService.getIntPref("browser.sessionhistory.max_entries");
for (let i = 0; i < max_entries; i++)
tabState.entries.push({ url: baseURL + i });
promiseTabState(tab, tabState).then(() => {
return TabStateFlusher.flush(tab.linkedBrowser);
}).then(() => {
tabState = JSON.parse(ss.getTabState(tab));
is(tabState.entries.length, max_entries, "session history filled to the limit");
is(tabState.entries[0].url, baseURL + 0, "... but not more");
// visit yet another anchor (appending it to session history)
ContentTask.spawn(tab.linkedBrowser, null, function() {
content.window.document.querySelector("a").click();
}).then(flushAndCheck);
function flushAndCheck() {
TabStateFlusher.flush(tab.linkedBrowser).then(check);
}
function check() {
tabState = JSON.parse(ss.getTabState(tab));
if (tab.linkedBrowser.currentURI.spec != baseURL + "end") {
// It may take a few passes through the event loop before we
// get the right URL.
executeSoon(flushAndCheck);
return;
}
is(tab.linkedBrowser.currentURI.spec, baseURL + "end",
"the new anchor was loaded");
is(tabState.entries[tabState.entries.length - 1].url, baseURL + "end",
"... and ignored");
is(tabState.entries[0].url, baseURL + 1,
"... and the first item was removed");
// clean up
gBrowser.removeTab(tab);
finish();
}
});
});
}

View file

@ -1,5 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Testcase for bug 447951</title>
<a href="#end">click me</a>

View file

@ -1,47 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = ROOT + "browser_454908_sample.html";
const PASS = "pwd-" + Math.random();
/**
* Bug 454908 - Don't save/restore values of password fields.
*/
add_task(function* test_dont_save_passwords() {
// Make sure we do save form data.
Services.prefs.clearUserPref("browser.sessionstore.privacy_level");
// Add a tab with a password field.
let tab = gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Fill in some values.
let usernameValue = "User " + Math.random();
yield setInputValue(browser, {id: "username", value: usernameValue});
yield setInputValue(browser, {id: "passwd", value: PASS});
// Close and restore the tab.
yield promiseRemoveTab(tab);
tab = ss.undoCloseTab(window, 0);
browser = tab.linkedBrowser;
yield promiseTabRestored(tab);
// Check that password fields aren't saved/restored.
let username = yield getInputValue(browser, {id: "username"});
is(username, usernameValue, "username was saved/restored");
let passwd = yield getInputValue(browser, {id: "passwd"});
is(passwd, "", "password wasn't saved/restored");
// Write to disk and read our file.
yield forceSaveState();
yield promiseForEachSessionRestoreFile((state, key) =>
// Ensure that we have not saved our password.
ok(!state.includes(PASS), "password has not been written to file " + key)
);
// Cleanup.
gBrowser.removeTab(tab);
});

View file

@ -1,8 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Test for bug 454908</title>
<h3>Dummy Login</h3>
<form>
<p>Username: <input type="text" id="username">
<p>Password: <input type="password" id="passwd">
</form>

View file

@ -1,49 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = ROOT + "browser_456342_sample.xhtml";
/**
* Bug 456342 - Restore values from non-standard input field types.
*/
add_task(function test_restore_nonstandard_input_values() {
// Add tab with various non-standard input field types.
let tab = gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Fill in form values.
let expectedValue = Math.random();
yield setFormElementValues(browser, {value: expectedValue});
// Remove tab and check collected form data.
yield promiseRemoveTab(tab);
let undoItems = JSON.parse(ss.getClosedTabData(window));
let savedFormData = undoItems[0].state.formdata;
let countGood = 0, countBad = 0;
for (let id of Object.keys(savedFormData.id)) {
if (savedFormData.id[id] == expectedValue) {
countGood++;
} else {
countBad++;
}
}
for (let exp of Object.keys(savedFormData.xpath)) {
if (savedFormData.xpath[exp] == expectedValue) {
countGood++;
} else {
countBad++;
}
}
is(countGood, 4, "Saved text for non-standard input fields");
is(countBad, 0, "Didn't save text for ignored field types");
});
function setFormElementValues(browser, data) {
return sendMessage(browser, "ss-test:setFormElementValues", data);
}

View file

@ -1,36 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Test for bug 456342</title></head>
<body>
<form>
<h3>Non-standard &lt;input&gt;s</h3>
<p>Search <input type="search" id="searchTerm"/></p>
<p>Image Search: <input type="image search" /></p>
<p>Autocomplete: <input type="autocomplete" name="fill-in"/></p>
<p>Mistyped: <input type="txet" name="mistyped"/></p>
<h3>Ignored types</h3>
<input type="hidden" name="hideme"/>
<input type="HIDDEN" name="hideme2"/>
<input type="submit" name="submit"/>
<input type="reset" name="reset"/>
<input type="image" name="image"/>
<input type="button" name="button"/>
<input type="password" name="password"/>
<input type="PassWord" name="password2"/>
<input type="PASSWORD" name="password3"/>
<input autocomplete="off" name="auto1"/>
<input type="text" autocomplete="OFF" name="auto2"/>
<textarea autocomplete="off" name="auto3"/>
<select autocomplete="off" name="auto4">
<option value="1" selected="true"/>
<option value="2"/>
<option value="3"/>
</select>
</form>
</body>
</html>

View file

@ -1,62 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 459906 **/
waitForExplicitFinish();
let testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_459906_sample.html";
let uniqueValue = "<b>Unique:</b> " + Date.now();
var frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 2)
return;
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let iframes = tab.linkedBrowser.contentWindow.frames;
iframes[1].document.body.innerHTML = uniqueValue;
frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load (and reload!) completely
if (frameCount++ < 2)
return;
tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
let iframes = tab2.linkedBrowser.contentWindow.frames;
if (iframes[1].document.body.innerHTML !== uniqueValue) {
// Poll again the value, since we can't ensure to run
// after SessionStore has injected innerHTML value.
// See bug 521802.
info("Polling for innerHTML value");
setTimeout(arguments.callee, 100);
return;
}
is(iframes[1].document.body.innerHTML, uniqueValue,
"rich textarea's content correctly duplicated");
let innerDomain = null;
try {
innerDomain = iframes[0].document.domain;
}
catch (ex) { /* throws for chrome: documents */ }
is(innerDomain, "mochi.test", "XSS exploit prevented!");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
finish();
});
}, true);
}, true);
}

View file

@ -1,3 +0,0 @@
<title>Cross Domain File for bug 459906</title>
cheers from localhost

View file

@ -1,41 +0,0 @@
<!-- Testcase originally by David Bloom <bloom@google.com> -->
<!DOCTYPE html>
<title>Test for bug 459906</title>
<body>
<iframe src="data:text/html;charset=utf-8,not_on_localhost"></iframe>
<iframe></iframe>
<script type="application/javascript">
var loadCount = 0;
frames[0].addEventListener("DOMContentLoaded", handleLoad, false);
frames[1].addEventListener("DOMContentLoaded", handleLoad, false);
function handleLoad() {
if (++loadCount < 2)
return;
frames[0].removeEventListener("DOMContentLoaded", handleLoad, false);
frames[1].removeEventListener("DOMContentLoaded", handleLoad, false);
frames[0].document.designMode = "on";
frames[0].document.__defineGetter__("designMode", function() {
// inject a cross domain file ...
var documentInjected = false;
document.getElementsByTagName("iframe")[0].onload =
function() { documentInjected = true; };
frames[0].location = "browser_459906_empty.html";
// ... and ensure that it has time to load
for (var c = 0; !documentInjected && c < 20; c++) {
var r = new XMLHttpRequest();
r.open("GET", location.href, false);
r.overrideMimeType("text/plain");
r.send(null);
}
return "on";
});
frames[1].document.designMode = "on";
};
</script>
</body>

View file

@ -1,85 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource:///modules/sessionstore/SessionStore.jsm");
function test() {
/** Test for Bug 461634 **/
waitForExplicitFinish();
const REMEMBER = Date.now(), FORGET = Math.random();
let test_state = { windows: [{ "tabs": [{ "entries": [] }], _closedTabs: [
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: REMEMBER },
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: REMEMBER },
] }] };
let remember_count = 2;
function countByTitle(aClosedTabList, aTitle) {
return aClosedTabList.filter(aData => aData.title == aTitle).length;
}
function testForError(aFunction) {
try {
aFunction();
return false;
}
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE";
}
}
// Open a window and add the above closed tab list.
let newWin = openDialog(location, "", "chrome,all,dialog=no");
promiseWindowLoaded(newWin).then(() => {
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
test_state.windows[0]._closedTabs.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true);
let closedTabs = SessionStore.getClosedTabData(newWin, false);
// Verify that non JSON serialized data is the same as JSON serialized data.
is(JSON.stringify(closedTabs), SessionStore.getClosedTabData(newWin),
"Non-serialized data is the same as serialized data")
is(closedTabs.length, test_state.windows[0]._closedTabs.length,
"Closed tab list has the expected length");
is(countByTitle(closedTabs, FORGET),
test_state.windows[0]._closedTabs.length - remember_count,
"The correct amout of tabs are to be forgotten");
is(countByTitle(closedTabs, REMEMBER), remember_count,
"Everything is set up");
// All of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE.
ok(testForError(() => ss.forgetClosedTab({}, 0)),
"Invalid window for forgetClosedTab throws");
ok(testForError(() => ss.forgetClosedTab(newWin, -1)),
"Invalid tab for forgetClosedTab throws");
ok(testForError(() => ss.forgetClosedTab(newWin, test_state.windows[0]._closedTabs.length + 1)),
"Invalid tab for forgetClosedTab throws");
// Remove third tab, then first tab.
ss.forgetClosedTab(newWin, 2);
ss.forgetClosedTab(newWin, null);
closedTabs = SessionStore.getClosedTabData(newWin, false);
// Verify that non JSON serialized data is the same as JSON serialized data.
is(JSON.stringify(closedTabs), SessionStore.getClosedTabData(newWin),
"Non-serialized data is the same as serialized data")
is(closedTabs.length, remember_count,
"The correct amout of tabs was removed");
is(countByTitle(closedTabs, FORGET), 0,
"All tabs specifically forgotten were indeed removed");
is(countByTitle(closedTabs, REMEMBER), remember_count,
"... and tabs not specifically forgetten weren't");
// Clean up.
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
BrowserTestUtils.closeWindow(newWin).then(finish);
});
}

View file

@ -1,39 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 461743 **/
waitForExplicitFinish();
let testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_461743_sample.html";
let frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// Wait for all frames to load completely.
if (frameCount++ < 2)
return;
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted");
executeSoon(function() {
let iframes = tab2.linkedBrowser.contentWindow.frames;
let innerHTML = iframes[1].document.body.innerHTML;
isnot(innerHTML, Components.utils.reportError.toString(),
"chrome access denied!");
// Clean up.
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
finish();
});
}, true, true);
}, true);
}

View file

@ -1,56 +0,0 @@
<!-- Testcase originally by <moz_bug_r_a4@yahoo.com> -->
<!DOCTYPE html>
<title>Test for bug 461743</title>
<body>
<iframe src="data:text/html;charset=utf-8,empty"></iframe>
<iframe></iframe>
<script type="application/javascript">
var chromeUrl = "chrome://global/content/mozilla.xhtml";
var exploitUrl = "javascript:try { document.body.innerHTML = Components.utils.reportError; } catch (ex) { }";
var loadCount = 0;
frames[0].addEventListener("DOMContentLoaded", handleLoad, false);
frames[1].addEventListener("DOMContentLoaded", handleLoad, false);
function handleLoad() {
if (++loadCount < 2)
return;
frames[0].removeEventListener("DOMContentLoaded", handleLoad, false);
frames[1].removeEventListener("DOMContentLoaded", handleLoad, false);
var flip = 0;
MutationEvent.prototype.toString = function() {
return flip++ == 0 ? chromeUrl : exploitUrl;
};
var href = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(frames[1].location), "href").get;
var loadChrome = { handleEvent: href };
var loadExploit = { handleEvent: href };
function delay() {
var xhr = new XMLHttpRequest();
xhr.open("GET", location.href, false);
xhr.send(null);
}
function done() {
var event = new MessageEvent('461743', { bubbles: true, cancelable: false,
data: "done", origin: location.href,
source: window });
document.dispatchEvent(event);
frames[0].document.removeEventListener("DOMNodeInserted", loadChrome, true);
frames[0].document.removeEventListener("DOMNodeInserted", delay, true);
frames[0].document.removeEventListener("DOMNodeInserted", loadExploit, true);
frames[0].document.removeEventListener("DOMNodeInserted", done, true);
}
frames[0].document.addEventListener("DOMNodeInserted", loadChrome, true);
frames[0].document.addEventListener("DOMNodeInserted", delay, true);
frames[0].document.addEventListener("DOMNodeInserted", loadExploit, true);
frames[0].document.addEventListener("DOMNodeInserted", done, true);
frames[0].document.designMode = "on";
};
</script>
</body>

View file

@ -1,40 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = ROOT + "browser_463205_sample.html";
/**
* Bug 463205 - Check URLs before restoring form data to make sure a malicious
* website can't modify frame URLs and make us inject form data into the wrong
* web pages.
*/
add_task(function test_check_urls_before_restoring() {
// Add a blank tab.
let tab = gBrowser.addTab("about:blank");
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Restore form data with a valid URL.
yield promiseTabState(tab, getState(URL));
let value = yield getInputValue(browser, {id: "text"});
is(value, "foobar", "value was restored");
// Restore form data with an invalid URL.
yield promiseTabState(tab, getState("http://example.com/"));
value = yield getInputValue(browser, {id: "text"});
is(value, "", "value was not restored");
// Cleanup.
gBrowser.removeTab(tab);
});
function getState(url) {
return JSON.stringify({
entries: [{url: URL}],
formdata: {url: url, id: {text: "foobar"}}
});
}

View file

@ -1,7 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>bug 463205</title>
<body>
<input type="text" id="text" />
</body>

View file

@ -1,53 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const TEST_URL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_463206_sample.html";
add_task(function* () {
// Add a new tab.
let tab = gBrowser.addTab(TEST_URL);
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
// "Type in" some random values.
yield ContentTask.spawn(tab.linkedBrowser, null, function* () {
function typeText(aTextField, aValue) {
aTextField.value = aValue;
let event = aTextField.ownerDocument.createEvent("UIEvents");
event.initUIEvent("input", true, true, aTextField.ownerGlobal, 0);
aTextField.dispatchEvent(event);
}
typeText(content.document.getElementById("out1"), Date.now());
typeText(content.document.getElementsByName("1|#out2")[0], Math.random());
typeText(content.frames[0].frames[1].document.getElementById("in1"), new Date());
});
// Duplicate the tab.
let tab2 = gBrowser.duplicateTab(tab);
yield promiseTabRestored(tab2);
// Query a few values from the top and its child frames.
yield ContentTask.spawn(tab2.linkedBrowser, null, function* () {
Assert.notEqual(content.document.getElementById("out1").value,
content.frames[1].document.getElementById("out1").value,
"text isn't reused for frames");
Assert.notEqual(content.document.getElementsByName("1|#out2")[0].value,
"", "text containing | and # is correctly restored");
Assert.equal(content.frames[1].document.getElementById("out2").value,
"", "id prefixes can't be faked");
// Disabled for now, Bug 588077
//Assert.equal(content.frames[0].frames[1].document.getElementById("in1").value,
// "", "id prefixes aren't mixed up");
Assert.equal(content.frames[1].frames[0].document.getElementById("in1").value,
"", "id prefixes aren't mixed up");
});
// Cleanup.
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
});

View file

@ -1,11 +0,0 @@
<!-- Testcase originally by <moz_bug_r_a4@yahoo.com> -->
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for bug 463206</title>
<iframe src="data:text/html;charset=utf-8,<iframe></iframe><iframe%20src='data:text/html;charset=utf-8,<input%2520id=%2522in1%2522>'></iframe>"></iframe>
<iframe src="data:text/html;charset=utf-8,<input%20id='out1'><input%20id='out2'><iframe%20src='data:text/html;charset=utf-8,<input%2520id=%2522in1%2522>'>"></iframe>
<input id="out1">
<input name="1|#out2">

View file

@ -1,85 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
function waitForClearHistory(aCallback) {
let observer = {
observe: function(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, "browser:purge-domain-data");
setTimeout(aCallback, 0);
}
};
Services.obs.addObserver(observer, "browser:purge-domain-data", false);
}
function test() {
/** Test for Bug 464199 **/
waitForExplicitFinish();
const REMEMBER = Date.now(), FORGET = Math.random();
let test_state = { windows: [{ "tabs": [{ "entries": [] }], _closedTabs: [
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
{ state: { entries: [{ url: "http://www.example.org/" }] }, title: REMEMBER },
{ state: { entries: [{ url: "http://www.example.net/" },
{ url: "http://www.example.org/" }] }, title: FORGET },
{ state: { entries: [{ url: "http://example.net/" }] }, title: FORGET },
{ state: { entries: [{ url: "http://sub.example.net/" }] }, title: FORGET },
{ state: { entries: [{ url: "http://www.example.net:8080/" }] }, title: FORGET },
{ state: { entries: [{ url: "about:license" }] }, title: REMEMBER },
{ state: { entries: [{ url: "http://www.example.org/frameset",
children: [
{ url: "http://www.example.org/frame" },
{ url: "http://www.example.org:8080/frame2" }
] }] }, title: REMEMBER },
{ state: { entries: [{ url: "http://www.example.org/frameset",
children: [
{ url: "http://www.example.org/frame" },
{ url: "http://www.example.net/frame" }
] }] }, title: FORGET },
{ state: { entries: [{ url: "http://www.example.org/form",
formdata: { id: { "url": "http://www.example.net/" } }
}] }, title: REMEMBER },
{ state: { entries: [{ url: "http://www.example.org/form" }],
extData: { "setTabValue": "http://example.net:80" } }, title: REMEMBER }
] }] };
let remember_count = 5;
function countByTitle(aClosedTabList, aTitle) {
return aClosedTabList.filter(aData => aData.title == aTitle).length;
}
// open a window and add the above closed tab list
let newWin = openDialog(location, "", "chrome,all,dialog=no");
promiseWindowLoaded(newWin).then(() => {
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
test_state.windows[0]._closedTabs.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true);
let closedTabs = JSON.parse(ss.getClosedTabData(newWin));
is(closedTabs.length, test_state.windows[0]._closedTabs.length,
"Closed tab list has the expected length");
is(countByTitle(closedTabs, FORGET),
test_state.windows[0]._closedTabs.length - remember_count,
"The correct amout of tabs are to be forgotten");
is(countByTitle(closedTabs, REMEMBER), remember_count,
"Everything is set up.");
ForgetAboutSite.removeDataFromDomain("example.net");
waitForClearHistory(function() {
closedTabs = JSON.parse(ss.getClosedTabData(newWin));
is(closedTabs.length, remember_count,
"The correct amout of tabs was removed");
is(countByTitle(closedTabs, FORGET), 0,
"All tabs to be forgotten were indeed removed");
is(countByTitle(closedTabs, REMEMBER), remember_count,
"... and tabs to be remembered weren't.");
// clean up
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
BrowserTestUtils.closeWindow(newWin).then(finish);
});
});
}

View file

@ -1,54 +0,0 @@
<!-- Testcase originally by <moz_bug_r_a4@yahoo.com> -->
<title>Test for bug 464620 (injection on input)</title>
<iframe></iframe>
<iframe onload="setup()"></iframe>
<script>
var targetUrl = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_464620_xd.html";
var firstPass;
function setup() {
if (firstPass !== undefined)
return;
firstPass = frames[1].location.href == "about:blank";
if (firstPass) {
frames[0].location = 'data:text/html;charset=utf-8,<body onload="if (parent.firstPass) parent.step();"><input id="x" oninput="parent.xss()">XXX</body>';
}
frames[1].location = targetUrl;
}
function step() {
var x = frames[0].document.getElementById("x");
if (x.value == "")
x.value = "ready";
x.style.display = "none";
frames[0].document.designMode = "on";
}
function xss() {
step();
var documentInjected = false;
document.getElementsByTagName("iframe")[0].onload =
function() { documentInjected = true; };
frames[0].location = targetUrl;
for (var c = 0; !documentInjected && c < 20; c++) {
var r = new XMLHttpRequest();
r.open("GET", location.href, false);
r.overrideMimeType("text/plain");
r.send(null);
}
document.getElementById("state").textContent = "done";
var event = new MessageEvent('464620_a', { bubbles: true, cancelable: false,
data: "done", origin: location.href,
source: window });
document.dispatchEvent(event);
}
</script>
<p id="state">pending</p>

View file

@ -1,48 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 464620 (injection on input) **/
waitForExplicitFinish();
let testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_464620_a.html";
var frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 4)
return;
this.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("464620_a", function(aEvent) {
tab2.linkedBrowser.removeEventListener("464620_a", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted");
// let form restoration complete and take into account the
// setTimeout(..., 0) in sss_restoreDocument_proxy
executeSoon(function() {
setTimeout(function() {
let win = tab2.linkedBrowser.contentWindow;
isnot(win.frames[0].document.location, testURL,
"cross domain document was loaded");
ok(!/XXX/.test(win.frames[0].document.body.innerHTML),
"no content was injected");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
finish();
}, 0);
});
}, true, true);
});
}, true);
}

View file

@ -1,58 +0,0 @@
<!-- Testcase originally by <moz_bug_r_a4@yahoo.com> -->
<title>Test for bug 464620 (injection on DOM node insertion)</title>
<iframe></iframe>
<iframe></iframe>
<iframe onload="setup()"></iframe>
<script>
var targetUrl = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_464620_xd.html";
var firstPass;
function setup() {
if (firstPass !== undefined)
return;
firstPass = frames[2].location.href == "about:blank";
if (firstPass) {
frames[0].location = 'data:text/html;charset=utf-8,<body onload="parent.step()">a</body>';
frames[1].location = 'data:text/html;charset=utf-8,<body onload="document.designMode=\'on\';">XXX</body>';
}
frames[2].location = targetUrl;
}
function step() {
frames[0].document.designMode = "on";
if (firstPass)
return;
var body = frames[0].document.body;
body.addEventListener("DOMNodeInserted", function() {
body.removeEventListener("DOMNodeInserted", arguments.callee, true);
xss();
}, true);
}
function xss() {
var documentInjected = false;
document.getElementsByTagName("iframe")[1].onload =
function() { documentInjected = true; };
frames[1].location = targetUrl;
for (var c = 0; !documentInjected && c < 20; c++) {
var r = new XMLHttpRequest();
r.open("GET", location.href, false);
r.overrideMimeType("text/plain");
r.send(null);
}
document.getElementById("state").textContent = "done";
var event = new MessageEvent('464620_b', { bubbles: true, cancelable: false,
data: "done", origin: location.href,
source: window });
document.dispatchEvent(event);
}
</script>
<p id="state">pending</p>

View file

@ -1,48 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 464620 (injection on DOM node insertion) **/
waitForExplicitFinish();
let testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser_464620_b.html";
var frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 6)
return;
this.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("464620_b", function(aEvent) {
tab2.linkedBrowser.removeEventListener("464620_b", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted");
// let form restoration complete and take into account the
// setTimeout(..., 0) in sss_restoreDocument_proxy
executeSoon(function() {
setTimeout(function() {
let win = tab2.linkedBrowser.contentWindow;
isnot(win.frames[1].document.location, testURL,
"cross domain document was loaded");
ok(!/XXX/.test(win.frames[1].document.body.innerHTML),
"no content was injected");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
finish();
}, 0);
});
}, true, true);
});
}, true);
}

View file

@ -1,5 +0,0 @@
<title>Cross Document File for bug 464620</title>
<body onload="document.designMode='on';" bgcolor="red">
This document is editable.
</body>

View file

@ -1,28 +0,0 @@
"use strict";
var uniqueName = "bug 465215";
var uniqueValue1 = "as good as unique: " + Date.now();
var uniqueValue2 = "as good as unique: " + Math.random();
add_task(function* () {
// set a unique value on a new, blank tab
let tab1 = gBrowser.addTab("about:blank");
yield promiseBrowserLoaded(tab1.linkedBrowser);
ss.setTabValue(tab1, uniqueName, uniqueValue1);
// duplicate the tab with that value
let tab2 = ss.duplicateTab(window, tab1);
yield promiseTabRestored(tab2);
is(ss.getTabValue(tab2, uniqueName), uniqueValue1, "tab value was duplicated");
ss.setTabValue(tab2, uniqueName, uniqueValue2);
isnot(ss.getTabValue(tab1, uniqueName), uniqueValue2, "tab values aren't sync'd");
// overwrite the tab with the value which should remove it
yield promiseTabState(tab1, {entries: []});
is(ss.getTabValue(tab1, uniqueName), "", "tab value was cleared");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab1);
});

View file

@ -1,45 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 465223 **/
// test setup
waitForExplicitFinish();
let uniqueKey1 = "bug 465223.1";
let uniqueKey2 = "bug 465223.2";
let uniqueValue1 = "unik" + Date.now();
let uniqueValue2 = "pi != " + Math.random();
// open a window and set a value on it
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
promiseWindowLoaded(newWin).then(() => {
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
newState.windows[0].extData[uniqueKey2] = uniqueValue2;
ss.setWindowState(newWin, JSON.stringify(newState), false);
is(newWin.gBrowser.tabs.length, 2,
"original tab wasn't overwritten");
is(ss.getWindowValue(newWin, uniqueKey1), uniqueValue1,
"window value wasn't overwritten when the tabs weren't");
is(ss.getWindowValue(newWin, uniqueKey2), uniqueValue2,
"new window value was correctly added");
newState.windows[0].extData[uniqueKey2] = uniqueValue1;
ss.setWindowState(newWin, JSON.stringify(newState), true);
is(newWin.gBrowser.tabs.length, 1,
"original tabs were overwritten");
is(ss.getWindowValue(newWin, uniqueKey1), "",
"window value was cleared");
is(ss.getWindowValue(newWin, uniqueKey2), uniqueValue1,
"window value was correctly overwritten");
// clean up
BrowserTestUtils.closeWindow(newWin).then(finish);
});
}

View file

@ -1,42 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = ROOT + "browser_466937_sample.html";
/**
* Bug 466937 - Prevent file stealing with sessionstore.
*/
add_task(function test_prevent_file_stealing() {
// Add a tab with some file input fields.
let tab = gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Generate a path to a 'secret' file.
let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
file.append("466937_test.file");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
let testPath = file.path;
// Fill in form values.
yield setInputValue(browser, {id: "reverse_thief", value: "/home/user/secret2"});
yield setInputValue(browser, {id: "bystander", value: testPath});
// Duplicate and check form values.
let tab2 = gBrowser.duplicateTab(tab);
let browser2 = tab2.linkedBrowser;
yield promiseTabRestored(tab2);
let thief = yield getInputValue(browser2, {id: "thief"});
is(thief, "", "file path wasn't set to text field value");
let reverse_thief = yield getInputValue(browser2, {id: "reverse_thief"});
is(reverse_thief, "", "text field value wasn't set to full file path");
let bystander = yield getInputValue(browser2, {id: "bystander"});
is(bystander, testPath, "normal case: file path was correctly preserved");
// Cleanup.
gBrowser.removeTab(tab);
gBrowser.removeTab(tab2);
});

View file

@ -1,22 +0,0 @@
<!-- Testcase originally by <moz_bug_r_a4@yahoo.com> -->
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for bug 466937</title>
<input id="thief" value="/home/user/secret">
<input type="file" id="reverse_thief">
<input type="file" id="bystander">
<script>
window.addEventListener("DOMContentLoaded", function() {
window.removeEventListener("DOMContentLoaded", arguments.callee, false);
if (!document.location.hash) {
document.location.hash = "#ready";
}
else {
document.getElementById("thief").type = "file";
document.getElementById("reverse_thief").type = "text";
}
}, false);
</script>

View file

@ -1,74 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test Summary:
// 1. Open about:sessionrestore where formdata is a JS object, not a string
// 1a. Check that #sessionData on the page is readable after JSON.parse (skipped, checking formdata is sufficient)
// 1b. Check that there are no backslashes in the formdata
// 1c. Check that formdata doesn't require JSON.parse
//
// 2. Use the current state (currently about:sessionrestore with data) and then open that in a new instance of about:sessionrestore
// 2a. Check that there are no backslashes in the formdata
// 2b. Check that formdata doesn't require JSON.parse
//
// 3. [backwards compat] Use a stringified state as formdata when opening about:sessionrestore
// 3a. Make sure there are nodes in the tree on about:sessionrestore (skipped, checking formdata is sufficient)
// 3b. Check that there are no backslashes in the formdata
// 3c. Check that formdata doesn't require JSON.parse
const CRASH_STATE = {windows: [{tabs: [{entries: [{url: "about:mozilla" }]}]}]};
const STATE = createEntries(CRASH_STATE);
const STATE2 = createEntries({windows: [{tabs: [STATE]}]});
const STATE3 = createEntries(JSON.stringify(CRASH_STATE));
function createEntries(sessionData) {
return {
entries: [{url: "about:sessionrestore"}],
formdata: {id: {sessionData: sessionData}, url: "about:sessionrestore"}
};
}
add_task(function test_nested_about_sessionrestore() {
// Prepare a blank tab.
let tab = gBrowser.addTab("about:blank");
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// test 1
yield promiseTabState(tab, STATE);
yield checkState("test1", tab);
// test 2
yield promiseTabState(tab, STATE2);
yield checkState("test2", tab);
// test 3
yield promiseTabState(tab, STATE3);
yield checkState("test3", tab);
// Cleanup.
gBrowser.removeTab(tab);
});
function* checkState(prefix, tab) {
// Flush and query tab state.
yield TabStateFlusher.flush(tab.linkedBrowser);
let {formdata} = JSON.parse(ss.getTabState(tab));
ok(formdata.id["sessionData"], prefix + ": we have form data for about:sessionrestore");
let sessionData_raw = JSON.stringify(formdata.id["sessionData"]);
ok(!/\\/.test(sessionData_raw), prefix + ": #sessionData contains no backslashes");
info(sessionData_raw);
let gotError = false;
try {
JSON.parse(formdata.id["sessionData"]);
} catch (e) {
info(prefix + ": got error: " + e);
gotError = true;
}
ok(gotError, prefix + ": attempting to JSON.parse form data threw error");
}

View file

@ -1,60 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 477657 **/
waitForExplicitFinish();
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
promiseWindowLoaded(newWin).then(() => {
let newState = { windows: [{
tabs: [{ entries: [] }],
_closedTabs: [{
state: { entries: [{ url: "about:" }]},
title: "About:"
}],
sizemode: "maximized"
}] };
let uniqueKey = "bug 477657";
let uniqueValue = "unik" + Date.now();
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
is(ss.getWindowValue(newWin, uniqueKey), uniqueValue,
"window value was set before the window was overwritten");
ss.setWindowState(newWin, JSON.stringify(newState), true);
// use newWin.setTimeout(..., 0) to mirror sss_restoreWindowFeatures
newWin.setTimeout(function() {
is(ss.getWindowValue(newWin, uniqueKey), "",
"window value was implicitly cleared");
is(newWin.windowState, newWin.STATE_MAXIMIZED,
"the window was maximized");
is(JSON.parse(ss.getClosedTabData(newWin)).length, 1,
"the closed tab was added before the window was overwritten");
delete newState.windows[0]._closedTabs;
delete newState.windows[0].sizemode;
ss.setWindowState(newWin, JSON.stringify(newState), true);
newWin.setTimeout(function() {
is(JSON.parse(ss.getClosedTabData(newWin)).length, 0,
"closed tabs were implicitly cleared");
is(newWin.windowState, newWin.STATE_MAXIMIZED,
"the window remains maximized");
newState.windows[0].sizemode = "normal";
ss.setWindowState(newWin, JSON.stringify(newState), true);
newWin.setTimeout(function() {
isnot(newWin.windowState, newWin.STATE_MAXIMIZED,
"the window was explicitly unmaximized");
BrowserTestUtils.closeWindow(newWin).then(finish);
}, 0);
}, 0);
}, 0);
});
}

View file

@ -1,47 +0,0 @@
"use strict";
/**
* Tests that we get sent to the right page when the user clicks
* the "Close" button in about:sessionrestore
*/
add_task(function*() {
yield SpecialPowers.pushPrefEnv({
"set": [
["browser.startup.page", 0],
]
});
let tab = gBrowser.addTab("about:sessionrestore");
gBrowser.selectedTab = tab;
let browser = tab.linkedBrowser;
yield BrowserTestUtils.browserLoaded(browser, false, "about:sessionrestore");
let doc = browser.contentDocument;
// Click on the "Close" button after about:sessionrestore is loaded.
doc.getElementById("errorCancel").click();
yield BrowserTestUtils.browserLoaded(browser, false, "about:blank");
// Test that starting a new session loads the homepage (set to http://mochi.test:8888)
// if Firefox is configured to display a homepage at startup (browser.startup.page = 1)
let homepage = "http://mochi.test:8888/";
yield SpecialPowers.pushPrefEnv({
"set": [
["browser.startup.homepage", homepage],
["browser.startup.page", 1],
]
});
browser.loadURI("about:sessionrestore");
yield BrowserTestUtils.browserLoaded(browser, false, "about:sessionrestore");
doc = browser.contentDocument;
// Click on the "Close" button after about:sessionrestore is loaded.
doc.getElementById("errorCancel").click();
yield BrowserTestUtils.browserLoaded(browser);
is(browser.currentURI.spec, homepage, "loaded page is the homepage");
yield BrowserTestUtils.removeTab(tab);
});

View file

@ -1,37 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = ROOT + "browser_485482_sample.html";
/**
* Bug 485482 - Make sure that we produce valid XPath expressions even for very
* weird HTML documents.
*/
add_task(function test_xpath_exp_for_strange_documents() {
// Load a page with weird tag names.
let tab = gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Fill in some values.
let uniqueValue = Math.random();
yield setInputValue(browser, {selector: "input[type=text]", value: uniqueValue});
yield setInputChecked(browser, {selector: "input[type=checkbox]", checked: true});
// Duplicate the tab.
let tab2 = gBrowser.duplicateTab(tab);
let browser2 = tab2.linkedBrowser;
yield promiseTabRestored(tab2);
// Check that we generated valid XPath expressions to restore form values.
let text = yield getInputValue(browser2, {selector: "input[type=text]"});
is(text, uniqueValue, "generated XPath expression was valid");
let checkbox = yield getInputChecked(browser2, {selector: "input[type=checkbox]"});
ok(checkbox, "generated XPath expression was valid");
// Cleanup.
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
});

View file

@ -1,12 +0,0 @@
<!DOCTYPE html>
<title>Test for bug 485482</title>
<bad=name>
<input type="text">
</bad=name>
<worse=name>
<l0c@l+na~e"'§>
<input type="checkbox" name="check"> Check
</l0c@l+na~e"'§>
</worse=name>

View file

@ -1,26 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 485563 **/
waitForExplicitFinish();
let uniqueValue = Math.random() + "\u2028Second line\u2029Second paragraph\u2027";
let tab = gBrowser.addTab();
promiseBrowserLoaded(tab.linkedBrowser).then(() => {
ss.setTabValue(tab, "bug485563", uniqueValue);
let tabState = JSON.parse(ss.getTabState(tab));
is(tabState.extData["bug485563"], uniqueValue,
"unicode line separator wasn't over-encoded");
ss.deleteTabValue(tab, "bug485563");
ss.setTabState(tab, JSON.stringify(tabState));
is(ss.getTabValue(tab, "bug485563"), uniqueValue,
"unicode line separator was correctly preserved");
gBrowser.removeTab(tab);
finish();
});
}

View file

@ -1,65 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Only windows with open tabs are restorable. Windows where a lone tab is
// detached may have _closedTabs, but is left with just an empty tab.
const STATES = [{
shouldBeAdded: true,
windowState: {
windows: [{
tabs: [{ entries: [{ url: "http://example.com", title: "example.com" }] }],
selected: 1,
_closedTabs: []
}]
}
}, {
shouldBeAdded: false,
windowState: {
windows: [{
tabs: [{ entries: [] }],
_closedTabs: []
}]
}
}, {
shouldBeAdded: false,
windowState: {
windows: [{
tabs: [{ entries: [] }],
_closedTabs: [{ state: { entries: [{ url: "http://example.com", index: 1 }] } }]
}]
}
}, {
shouldBeAdded: false,
windowState: {
windows: [{
tabs: [{ entries: [] }],
_closedTabs: [],
extData: { keyname: "pi != " + Math.random() }
}]
}
}];
add_task(function* test_bug_490040() {
for (let state of STATES) {
// Ensure we can store the window if needed.
let startingClosedWindowCount = ss.getClosedWindowCount();
yield pushPrefs(["browser.sessionstore.max_windows_undo",
startingClosedWindowCount + 1]);
let curClosedWindowCount = ss.getClosedWindowCount();
let win = yield BrowserTestUtils.openNewBrowserWindow();
ss.setWindowState(win, JSON.stringify(state.windowState), true);
if (state.windowState.windows[0].tabs.length) {
yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
}
yield BrowserTestUtils.closeWindow(win);
is(ss.getClosedWindowCount(),
curClosedWindowCount + (state.shouldBeAdded ? 1 : 0),
"That window should " + (state.shouldBeAdded ? "" : "not ") +
"be restorable");
}
});

View file

@ -1,42 +0,0 @@
"use strict";
const REFERRER1 = "http://example.org/?" + Date.now();
const REFERRER2 = "http://example.org/?" + Math.random();
add_task(function* () {
function* checkDocumentReferrer(referrer, msg) {
yield ContentTask.spawn(gBrowser.selectedBrowser, { referrer, msg }, function* (args) {
Assert.equal(content.document.referrer, args.referrer, args.msg);
});
}
// Add a new tab.
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Load a new URI with a specific referrer.
let referrerURI = Services.io.newURI(REFERRER1, null, null);
browser.loadURI("http://example.org", referrerURI, null);
yield promiseBrowserLoaded(browser);
yield TabStateFlusher.flush(browser);
let tabState = JSON.parse(ss.getTabState(tab));
is(tabState.entries[0].referrer, REFERRER1,
"Referrer retrieved via getTabState matches referrer set via loadURI.");
tabState.entries[0].referrer = REFERRER2;
yield promiseTabState(tab, tabState);
yield checkDocumentReferrer(REFERRER2,
"document.referrer matches referrer set via setTabState.");
gBrowser.removeCurrentTab();
// Restore the closed tab.
tab = ss.undoCloseTab(window, 0);
yield promiseTabRestored(tab);
yield checkDocumentReferrer(REFERRER2,
"document.referrer is still correct after closing and reopening the tab.");
gBrowser.removeCurrentTab();
});

View file

@ -1,120 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 491577 **/
// test setup
waitForExplicitFinish();
const REMEMBER = Date.now(), FORGET = Math.random();
let test_state = {
windows: [ { tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 } ],
_closedWindows : [
// _closedWindows[0]
{
tabs: [
{ entries: [{ url: "http://example.com/", title: "title" }] },
{ entries: [{ url: "http://mozilla.org/", title: "title" }] }
],
selected: 2,
title: FORGET,
_closedTabs: []
},
// _closedWindows[1]
{
tabs: [
{ entries: [{ url: "http://mozilla.org/", title: "title" }] },
{ entries: [{ url: "http://example.com/", title: "title" }] },
{ entries: [{ url: "http://mozilla.org/", title: "title" }] },
],
selected: 3,
title: REMEMBER,
_closedTabs: []
},
// _closedWindows[2]
{
tabs: [
{ entries: [{ url: "http://example.com/", title: "title" }] }
],
selected: 1,
title: FORGET,
_closedTabs: [
{
state: {
entries: [
{ url: "http://mozilla.org/", title: "title" },
{ url: "http://mozilla.org/again", title: "title" }
]
},
pos: 1,
title: "title"
},
{
state: {
entries: [
{ url: "http://example.com", title: "title" }
]
},
title: "title"
}
]
}
]
};
let remember_count = 1;
function countByTitle(aClosedWindowList, aTitle) {
return aClosedWindowList.filter(aData => aData.title == aTitle).length;
}
function testForError(aFunction) {
try {
aFunction();
return false;
}
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE";
}
}
// open a window and add the above closed window list
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
promiseWindowLoaded(newWin).then(() => {
gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
test_state._closedWindows.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true);
let closedWindows = JSON.parse(ss.getClosedWindowData());
is(closedWindows.length, test_state._closedWindows.length,
"Closed window list has the expected length");
is(countByTitle(closedWindows, FORGET),
test_state._closedWindows.length - remember_count,
"The correct amount of windows are to be forgotten");
is(countByTitle(closedWindows, REMEMBER), remember_count,
"Everything is set up.");
// all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
ok(testForError(() => ss.forgetClosedWindow(-1)),
"Invalid window for forgetClosedWindow throws");
ok(testForError(() => ss.forgetClosedWindow(test_state._closedWindows.length + 1)),
"Invalid window for forgetClosedWindow throws");
// Remove third window, then first window
ss.forgetClosedWindow(2);
ss.forgetClosedWindow(null);
closedWindows = JSON.parse(ss.getClosedWindowData());
is(closedWindows.length, remember_count,
"The correct amount of windows were removed");
is(countByTitle(closedWindows, FORGET), 0,
"All windows specifically forgotten were indeed removed");
is(countByTitle(closedWindows, REMEMBER), remember_count,
"... and windows not specifically forgetten weren't.");
// clean up
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
BrowserTestUtils.closeWindow(newWin).then(finish);
});
}

View file

@ -1,46 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 495495 **/
waitForExplicitFinish();
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no,toolbar=yes");
promiseWindowLoaded(newWin).then(() => {
let state1 = ss.getWindowState(newWin);
BrowserTestUtils.closeWindow(newWin).then(() => {
newWin = openDialog(location, "_blank",
"chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar=no,location,personal,directories,dialog=no");
promiseWindowLoaded(newWin).then(() => {
let state2 = ss.getWindowState(newWin);
function testState(state, expected, callback) {
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
promiseWindowLoaded(win).then(() => {
is(win.gURLBar.readOnly, false,
"URL bar should not be read-only before setting the state");
is(win.gURLBar.getAttribute("enablehistory"), "true",
"URL bar autocomplete should be enabled before setting the state");
ss.setWindowState(win, state, true);
is(win.gURLBar.readOnly, expected.readOnly,
"URL bar read-only state should be restored correctly");
is(win.gURLBar.getAttribute("enablehistory"), expected.enablehistory,
"URL bar autocomplete state should be restored correctly");
BrowserTestUtils.closeWindow(win).then(callback);
});
}
BrowserTestUtils.closeWindow(newWin).then(() => {
testState(state1, {readOnly: false, enablehistory: "true"}, function() {
testState(state2, {readOnly: true, enablehistory: "false"}, finish);
});
});
});
});
});
}

View file

@ -1,120 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let checkState = Task.async(function*(browser) {
// Go back and then forward, and make sure that the state objects received
// from the popState event are as we expect them to be.
//
// We also add a node to the document's body when after going back and make
// sure it's still there after we go forward -- this is to test that the two
// history entries correspond to the same document.
let deferred = {};
deferred.promise = new Promise(resolve => deferred.resolve = resolve);
let popStateCount = 0;
browser.addEventListener("popstate", function(aEvent) {
if (popStateCount == 0) {
popStateCount++;
ok(aEvent.state, "Event should have a state property.");
ContentTask.spawn(browser, null, function() {
is(content.testState, "foo",
"testState after going back");
is(JSON.stringify(content.history.state), JSON.stringify({obj1:1}),
"first popstate object.");
// Add a node with id "new-elem" to the document.
let doc = content.document;
ok(!doc.getElementById("new-elem"),
"doc shouldn't contain new-elem before we add it.");
let elem = doc.createElement("div");
elem.id = "new-elem";
doc.body.appendChild(elem);
}).then(() => {
browser.goForward();
});
} else if (popStateCount == 1) {
popStateCount++;
// When content fires a PopStateEvent and we observe it from a chrome event
// listener (as we do here, and, thankfully, nowhere else in the tree), the
// state object will be a cross-compartment wrapper to an object that was
// deserialized in the content scope. And in this case, since RegExps are
// not currently Xrayable (see bug 1014991), trying to pull |obj3| (a RegExp)
// off of an Xrayed Object won't work. So we need to waive.
ContentTask.spawn(browser, aEvent.state, function(state) {
Assert.equal(Cu.waiveXrays(state).obj3.toString(),
"/^a$/", "second popstate object.");
// Make sure that the new-elem node is present in the document. If it's
// not, then this history entry has a different doc identifier than the
// previous entry, which is bad.
let doc = content.document;
let newElem = doc.getElementById("new-elem");
ok(newElem, "doc should contain new-elem.");
newElem.parentNode.removeChild(newElem);
ok(!doc.getElementById("new-elem"), "new-elem should be removed.");
}).then(() => {
browser.removeEventListener("popstate", arguments.callee, true);
deferred.resolve();
});
}
});
// Set some state in the page's window. When we go back(), the page should
// be retrieved from bfcache, and this state should still be there.
yield ContentTask.spawn(browser, null, function() {
content.testState = "foo";
});
// Now go back. This should trigger the popstate event handler above.
browser.goBack();
yield deferred.promise;
});
add_task(function* test() {
// Tests session restore functionality of history.pushState and
// history.replaceState(). (Bug 500328)
// We open a new blank window, let it load, and then load in
// http://example.com. We need to load the blank window first, otherwise the
// docshell gets confused and doesn't have a current history entry.
let state;
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
BrowserTestUtils.loadURI(browser, "http://example.com");
yield BrowserTestUtils.browserLoaded(browser);
// After these push/replaceState calls, the window should have three
// history entries:
// testURL (state object: null) <-- oldest
// testURL (state object: {obj1:1})
// testURL?page2 (state object: {obj3:/^a$/}) <-- newest
function contentTest() {
let history = content.window.history;
history.pushState({obj1:1}, "title-obj1");
history.pushState({obj2:2}, "title-obj2", "?page2");
history.replaceState({obj3:/^a$/}, "title-obj3");
}
yield ContentTask.spawn(browser, null, contentTest);
yield TabStateFlusher.flush(browser);
state = ss.getTabState(gBrowser.getTabForBrowser(browser));
});
// Restore the state into a new tab. Things don't work well when we
// restore into the old tab, but that's not a real use case anyway.
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
let tab2 = gBrowser.getTabForBrowser(browser);
let tabRestoredPromise = promiseTabRestored(tab2);
ss.setTabState(tab2, state, true);
// Run checkState() once the tab finishes loading its restored state.
yield tabRestoredPromise;
yield checkState(browser);
});
});

View file

@ -1,73 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 506482 **/
// test setup
waitForExplicitFinish();
// read the sessionstore.js mtime (picked from browser_248970_a.js)
let profilePath = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
function getSessionstoreFile() {
let sessionStoreJS = profilePath.clone();
sessionStoreJS.append("sessionstore.js");
return sessionStoreJS;
}
function getSessionstorejsModificationTime() {
let file = getSessionstoreFile();
if (file.exists())
return file.lastModifiedTime;
else
return -1;
}
// delete existing sessionstore.js, to make sure we're not reading
// the mtime of an old one initially.
let sessionStoreJS = getSessionstoreFile();
if (sessionStoreJS.exists())
sessionStoreJS.remove(false);
// test content URL
const TEST_URL = "data:text/html;charset=utf-8,"
+ "<body style='width: 100000px; height: 100000px;'><p>top</p></body>"
// preferences that we use
const PREF_INTERVAL = "browser.sessionstore.interval";
// make sure sessionstore.js is saved ASAP on all events
gPrefService.setIntPref(PREF_INTERVAL, 0);
// get the initial sessionstore.js mtime (-1 if it doesn't exist yet)
let mtime0 = getSessionstorejsModificationTime();
// create and select a first tab
let tab = gBrowser.addTab(TEST_URL);
promiseBrowserLoaded(tab.linkedBrowser).then(() => {
// step1: the above has triggered some saveStateDelayed(), sleep until
// it's done, and get the initial sessionstore.js mtime
setTimeout(function step1(e) {
let mtime1 = getSessionstorejsModificationTime();
isnot(mtime1, mtime0, "initial sessionstore.js update");
// step2: test sessionstore.js is not updated on tab selection
// or content scrolling
gBrowser.selectedTab = tab;
tab.linkedBrowser.contentWindow.scrollTo(1100, 1200);
setTimeout(function step2(e) {
let mtime2 = getSessionstorejsModificationTime();
is(mtime2, mtime1,
"tab selection and scrolling: sessionstore.js not updated");
// ok, done, cleanup and finish
if (gPrefService.prefHasUserValue(PREF_INTERVAL))
gPrefService.clearUserPref(PREF_INTERVAL);
gBrowser.removeTab(tab);
finish();
}, 3500); // end of sleep after tab selection and scrolling
}, 3500); // end of sleep after initial saveStateDelayed()
});
}

View file

@ -1,38 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 514751 (Wallpaper) **/
waitForExplicitFinish();
let state = {
windows: [{
tabs: [{
entries: [
{ url: "about:mozilla", title: "Mozilla" },
{}
]
}]
}]
};
var theWin = openDialog(location, "", "chrome,all,dialog=no");
theWin.addEventListener("load", function () {
theWin.removeEventListener("load", arguments.callee, false);
executeSoon(function () {
var gotError = false;
try {
ss.setWindowState(theWin, JSON.stringify(state), true);
} catch (e) {
if (/NS_ERROR_MALFORMED_URI/.test(e))
gotError = true;
}
ok(!gotError, "Didn't get a malformed URI error.");
BrowserTestUtils.closeWindow(theWin).then(finish);
});
}, false);
}

View file

@ -1,21 +0,0 @@
function test() {
var startup_info = Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup).getStartupInfo();
// No .process info on mac
// Check if we encountered a telemetry error for the the process creation
// timestamp and turn the first test into a known failure.
var telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
var snapshot = telemetry.getHistogramById("STARTUP_MEASUREMENT_ERRORS")
.snapshot();
if (snapshot.counts[0] == 0)
ok(startup_info.process <= startup_info.main, "process created before main is run " + uneval(startup_info));
else
todo(false, "An error occurred while recording the process creation timestamp, skipping this test");
// on linux firstPaint can happen after everything is loaded (especially with remote X)
if (startup_info.firstPaint)
ok(startup_info.main <= startup_info.firstPaint, "main ran before first paint " + uneval(startup_info));
ok(startup_info.main < startup_info.sessionRestored, "Session restored after main " + uneval(startup_info));
}

View file

@ -1,269 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 522545 **/
waitForExplicitFinish();
requestLongerTimeout(4);
// This tests the following use case:
// User opens a new tab which gets focus. The user types something into the
// address bar, then crashes or quits.
function test_newTabFocused() {
let state = {
windows: [{
tabs: [
{ entries: [{ url: "about:mozilla" }] },
{ entries: [], userTypedValue: "example.com", userTypedClear: 0 }
],
selected: 2
}]
};
waitForBrowserState(state, function() {
let browser = gBrowser.selectedBrowser;
is(browser.currentURI.spec, "about:blank",
"No history entries still sets currentURI to about:blank");
is(browser.userTypedValue, "example.com",
"userTypedValue was correctly restored");
ok(!browser.didStartLoadSinceLastUserTyping(),
"We still know that no load is ongoing");
is(gURLBar.value, "example.com",
"Address bar's value correctly restored");
// Change tabs to make sure address bar value gets updated
gBrowser.selectedTab = gBrowser.tabContainer.getItemAtIndex(0);
is(gURLBar.value, "about:mozilla",
"Address bar's value correctly updated");
runNextTest();
});
}
// This tests the following use case:
// User opens a new tab which gets focus. The user types something into the
// address bar, switches back to the first tab, then crashes or quits.
function test_newTabNotFocused() {
let state = {
windows: [{
tabs: [
{ entries: [{ url: "about:mozilla" }] },
{ entries: [], userTypedValue: "example.org", userTypedClear: 0 }
],
selected: 1
}]
};
waitForBrowserState(state, function() {
let browser = gBrowser.getBrowserAtIndex(1);
is(browser.currentURI.spec, "about:blank",
"No history entries still sets currentURI to about:blank");
is(browser.userTypedValue, "example.org",
"userTypedValue was correctly restored");
ok(!browser.didStartLoadSinceLastUserTyping(),
"We still know that no load is ongoing");
is(gURLBar.value, "about:mozilla",
"Address bar's value correctly restored");
// Change tabs to make sure address bar value gets updated
gBrowser.selectedTab = gBrowser.tabContainer.getItemAtIndex(1);
is(gURLBar.value, "example.org",
"Address bar's value correctly updated");
runNextTest();
});
}
// This tests the following use case:
// User is in a tab with session history, then types something in the
// address bar, then crashes or quits.
function test_existingSHEnd_noClear() {
let state = {
windows: [{
tabs: [{
entries: [{ url: "about:mozilla" }, { url: "about:config" }],
index: 2,
userTypedValue: "example.com",
userTypedClear: 0
}]
}]
};
waitForBrowserState(state, function() {
let browser = gBrowser.selectedBrowser;
is(browser.currentURI.spec, "about:config",
"browser.currentURI set to current entry in SH");
is(browser.userTypedValue, "example.com",
"userTypedValue was correctly restored");
ok(!browser.didStartLoadSinceLastUserTyping(),
"We still know that no load is ongoing");
is(gURLBar.value, "example.com",
"Address bar's value correctly restored to userTypedValue");
runNextTest();
});
}
// This tests the following use case:
// User is in a tab with session history, presses back at some point, then
// types something in the address bar, then crashes or quits.
function test_existingSHMiddle_noClear() {
let state = {
windows: [{
tabs: [{
entries: [{ url: "about:mozilla" }, { url: "about:config" }],
index: 1,
userTypedValue: "example.org",
userTypedClear: 0
}]
}]
};
waitForBrowserState(state, function() {
let browser = gBrowser.selectedBrowser;
is(browser.currentURI.spec, "about:mozilla",
"browser.currentURI set to current entry in SH");
is(browser.userTypedValue, "example.org",
"userTypedValue was correctly restored");
ok(!browser.didStartLoadSinceLastUserTyping(),
"We still know that no load is ongoing");
is(gURLBar.value, "example.org",
"Address bar's value correctly restored to userTypedValue");
runNextTest();
});
}
// This test simulates lots of tabs opening at once and then quitting/crashing.
function test_getBrowserState_lotsOfTabsOpening() {
gBrowser.stop();
let uris = [];
for (let i = 0; i < 25; i++)
uris.push("http://example.com/" + i);
// We're waiting for the first location change, which should indicate
// one of the tabs has loaded and the others haven't. So one should
// be in a non-userTypedValue case, while others should still have
// userTypedValue and userTypedClear set.
gBrowser.addTabsProgressListener({
onLocationChange: function (aBrowser) {
if (uris.indexOf(aBrowser.currentURI.spec) > -1) {
gBrowser.removeTabsProgressListener(this);
firstLocationChange();
}
}
});
function firstLocationChange() {
let state = JSON.parse(ss.getBrowserState());
let hasUTV = state.windows[0].tabs.some(function(aTab) {
return aTab.userTypedValue && aTab.userTypedClear && !aTab.entries.length;
});
ok(hasUTV, "At least one tab has a userTypedValue with userTypedClear with no loaded URL");
BrowserTestUtils.waitForMessage(gBrowser.selectedBrowser.messageManager, "SessionStore:update").then(firstLoad);
}
function firstLoad() {
let state = JSON.parse(ss.getTabState(gBrowser.selectedTab));
let hasSH = !("userTypedValue" in state) && state.entries[0].url;
ok(hasSH, "The selected tab has its entry in SH");
runNextTest();
}
gBrowser.loadTabs(uris);
}
// This simulates setting a userTypedValue and ensures that just typing in the
// URL bar doesn't set userTypedClear as well.
function test_getBrowserState_userTypedValue() {
let state = {
windows: [{
tabs: [{ entries: [] }]
}]
};
waitForBrowserState(state, function() {
let browser = gBrowser.selectedBrowser;
// Make sure this tab isn't loading and state is clear before we test.
is(browser.userTypedValue, null, "userTypedValue is empty to start");
ok(!browser.didStartLoadSinceLastUserTyping(),
"Initially, no load should be ongoing");
let inputText = "example.org";
gURLBar.focus();
gURLBar.value = inputText.slice(0, -1);
EventUtils.synthesizeKey(inputText.slice(-1) , {});
executeSoon(function () {
is(browser.userTypedValue, "example.org",
"userTypedValue was set when changing URLBar value");
ok(!browser.didStartLoadSinceLastUserTyping(),
"No load started since changing URLBar value");
// Now make sure ss gets these values too
let newState = JSON.parse(ss.getBrowserState());
is(newState.windows[0].tabs[0].userTypedValue, "example.org",
"sessionstore got correct userTypedValue");
is(newState.windows[0].tabs[0].userTypedClear, 0,
"sessionstore got correct userTypedClear");
runNextTest();
});
});
}
// test_getBrowserState_lotsOfTabsOpening tested userTypedClear in a few cases,
// but not necessarily any that had legitimate URIs in the state of loading
// (eg, "http://example.com"), so this test will cover that case.
function test_userTypedClearLoadURI() {
let state = {
windows: [{
tabs: [
{ entries: [], userTypedValue: "http://example.com", userTypedClear: 2 }
]
}]
};
waitForBrowserState(state, function() {
let browser = gBrowser.selectedBrowser;
is(browser.currentURI.spec, "http://example.com/",
"userTypedClear=2 caused userTypedValue to be loaded");
is(browser.userTypedValue, null,
"userTypedValue was null after loading a URI");
ok(!browser.didStartLoadSinceLastUserTyping(),
"We should have reset the load state when the tab loaded");
is(gURLBar.textValue, gURLBar.trimValue("http://example.com/"),
"Address bar's value set after loading URI");
runNextTest();
});
}
let tests = [test_newTabFocused, test_newTabNotFocused,
test_existingSHEnd_noClear, test_existingSHMiddle_noClear,
test_getBrowserState_lotsOfTabsOpening,
test_getBrowserState_userTypedValue, test_userTypedClearLoadURI];
let originalState = JSON.parse(ss.getBrowserState());
let state = {
windows: [{
tabs: [{ entries: [{ url: "about:blank" }] }]
}]
};
function runNextTest() {
if (tests.length) {
waitForBrowserState(state, function() {
gBrowser.selectedBrowser.userTypedValue = null;
URLBarSetURI();
(tests.shift())();
});
} else {
waitForBrowserState(originalState, function() {
gBrowser.selectedBrowser.userTypedValue = null;
URLBarSetURI();
finish();
});
}
}
// Run the tests!
runNextTest();
}

View file

@ -1,42 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 524745 **/
let uniqKey = "bug524745";
let uniqVal = Date.now().toString();
waitForExplicitFinish();
whenNewWindowLoaded({ private: false }, function (window_B) {
waitForFocus(function() {
// Add identifying information to window_B
ss.setWindowValue(window_B, uniqKey, uniqVal);
let state = JSON.parse(ss.getBrowserState());
let selectedWindow = state.windows[state.selectedWindow - 1];
is(selectedWindow.extData && selectedWindow.extData[uniqKey], uniqVal,
"selectedWindow is window_B");
// Now minimize window_B. The selected window shouldn't have the secret data
window_B.minimize();
waitForFocus(function() {
state = JSON.parse(ss.getBrowserState());
selectedWindow = state.windows[state.selectedWindow - 1];
ok(!selectedWindow.extData || !selectedWindow.extData[uniqKey],
"selectedWindow is not window_B after minimizing it");
// Now minimize the last open window (assumes no other tests left windows open)
window.minimize();
state = JSON.parse(ss.getBrowserState());
is(state.selectedWindow, 0,
"selectedWindow should be 0 when all windows are minimized");
// Cleanup
window.restore();
BrowserTestUtils.closeWindow(window_B).then(finish);
});
}, window_B);
});
}

View file

@ -1,72 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
/** Test for Bug 526613 **/
// test setup
waitForExplicitFinish();
function browserWindowsCount(expected) {
let count = 0;
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
if (!e.getNext().closed)
++count;
}
is(count, expected,
"number of open browser windows according to nsIWindowMediator");
let state = ss.getBrowserState();
info(state);
is(JSON.parse(state).windows.length, expected,
"number of open browser windows according to getBrowserState");
}
browserWindowsCount(1);
// backup old state
let oldState = ss.getBrowserState();
// create a new state for testing
let testState = {
windows: [
{ tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 },
{ tabs: [{ entries: [{ url: "about:mozilla" }] }], selected: 1 },
],
// make sure the first window is focused, otherwise when restoring the
// old state, the first window is closed and the test harness gets unloaded
selectedWindow: 1
};
let pass = 1;
function observer(aSubject, aTopic, aData) {
is(aTopic, "sessionstore-browser-state-restored",
"The sessionstore-browser-state-restored notification was observed");
if (pass++ == 1) {
browserWindowsCount(2);
// let the first window be focused (see above)
function pollMostRecentWindow() {
if (Services.wm.getMostRecentWindow("navigator:browser") == window) {
ss.setBrowserState(oldState);
} else {
info("waiting for the current window to become active");
setTimeout(pollMostRecentWindow, 0);
window.focus(); //XXX Why is this needed?
}
}
pollMostRecentWindow();
}
else {
browserWindowsCount(1);
ok(!window.closed, "Restoring the old state should have left this window open");
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");
finish();
}
}
Services.obs.addObserver(observer, "sessionstore-browser-state-restored", false);
// set browser to test state
ss.setBrowserState(JSON.stringify(testState));
}

View file

@ -1,21 +0,0 @@
function browserWindowsCount(expected) {
var count = 0;
var e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
if (!e.getNext().closed)
++count;
}
is(count, expected,
"number of open browser windows according to nsIWindowMediator");
is(JSON.parse(ss.getBrowserState()).windows.length, expected,
"number of open browser windows according to getBrowserState");
}
add_task(function() {
browserWindowsCount(1);
let win = yield BrowserTestUtils.openNewBrowserWindow();
browserWindowsCount(2);
yield BrowserTestUtils.closeWindow(win);
browserWindowsCount(1);
});

View file

@ -1,30 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
waitForExplicitFinish();
let tab1 = gBrowser.addTab("about:rights");
let tab2 = gBrowser.addTab("about:mozilla");
promiseBrowserLoaded(tab1.linkedBrowser).then(() => {
// Tell the session storer that the tab is pinned
let newTabState = '{"entries":[{"url":"about:rights"}],"pinned":true,"userTypedValue":"Hello World!"}';
ss.setTabState(tab1, newTabState);
// Undo pinning
gBrowser.unpinTab(tab1);
// Close and restore tab
gBrowser.removeTab(tab1);
let savedState = JSON.parse(ss.getClosedTabData(window))[0].state;
isnot(savedState.pinned, true, "Pinned should not be true");
tab1 = ss.undoCloseTab(window, 0);
isnot(tab1.pinned, true, "Should not be pinned");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
finish();
});
}

View file

@ -1,20 +0,0 @@
"use strict";
add_task(function* () {
let tab1 = gBrowser.addTab("data:text/plain;charset=utf-8,foo");
gBrowser.pinTab(tab1);
yield promiseBrowserLoaded(tab1.linkedBrowser);
let tab2 = gBrowser.addTab();
gBrowser.pinTab(tab2);
is(Array.indexOf(gBrowser.tabs, tab1), 0, "pinned tab 1 is at the first position");
yield promiseRemoveTab(tab1);
tab1 = undoCloseTab();
ok(tab1.pinned, "pinned tab 1 has been restored as a pinned tab");
is(Array.indexOf(gBrowser.tabs, tab1), 0, "pinned tab 1 has been restored to the first position");
yield BrowserTestUtils.removeTab(tab1);
yield BrowserTestUtils.removeTab(tab2);
});

View file

@ -1,81 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const URIS_PINNED = ["about:license", "about:about"];
const URIS_NORMAL_A = ["about:mozilla"];
const URIS_NORMAL_B = ["about:buildconfig"];
function test() {
waitForExplicitFinish();
isnot(Services.prefs.getIntPref("browser.startup.page"), 3,
"pref to save session must not be set for this test");
ok(!Services.prefs.getBoolPref("browser.sessionstore.resume_session_once"),
"pref to save session once must not be set for this test");
document.documentElement.setAttribute("windowtype", "navigator:browsertestdummy");
openWinWithCb(closeFirstWin, URIS_PINNED.concat(URIS_NORMAL_A));
}
function closeFirstWin(win) {
win.gBrowser.pinTab(win.gBrowser.tabs[0]);
win.gBrowser.pinTab(win.gBrowser.tabs[1]);
let winClosed = BrowserTestUtils.windowClosed(win);
// We need to call BrowserTryToCloseWindow in order to trigger
// the machinery that chooses whether or not to save the session
// for the last window.
win.BrowserTryToCloseWindow();
ok(win.closed, "window closed");
winClosed.then(() => {
openWinWithCb(checkSecondWin, URIS_NORMAL_B, URIS_PINNED.concat(URIS_NORMAL_B));
});
}
function checkSecondWin(win) {
is(win.gBrowser.browsers[0].currentURI.spec, URIS_PINNED[0], "first pinned tab restored");
is(win.gBrowser.browsers[1].currentURI.spec, URIS_PINNED[1], "second pinned tab restored");
ok(win.gBrowser.tabs[0].pinned, "first pinned tab is still pinned");
ok(win.gBrowser.tabs[1].pinned, "second pinned tab is still pinned");
BrowserTestUtils.closeWindow(win).then(() => {
// cleanup
document.documentElement.setAttribute("windowtype", "navigator:browser");
finish();
});
}
function openWinWithCb(cb, argURIs, expectedURIs) {
if (!expectedURIs)
expectedURIs = argURIs;
var win = openDialog(getBrowserURL(), "_blank",
"chrome,all,dialog=no", argURIs.join("|"));
win.addEventListener("load", function () {
win.removeEventListener("load", arguments.callee, false);
info("the window loaded");
var expectedLoads = expectedURIs.length;
win.gBrowser.addTabsProgressListener({
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aRequest &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
expectedURIs.indexOf(aRequest.QueryInterface(Ci.nsIChannel).originalURI.spec) > -1 &&
--expectedLoads <= 0) {
win.gBrowser.removeTabsProgressListener(this);
info("all tabs loaded");
is(win.gBrowser.tabs.length, expectedURIs.length, "didn't load any unexpected tabs");
executeSoon(function () {
cb(win);
});
}
}
});
}, false);
}

View file

@ -1,19 +0,0 @@
// Tests that an about:blank tab with no history will not be saved into
// session store and thus, it will not show up in Recently Closed Tabs.
"use strict";
add_task(function* () {
let tab = gBrowser.addTab("about:blank");
yield promiseBrowserLoaded(tab.linkedBrowser);
is(tab.linkedBrowser.currentURI.spec, "about:blank",
"we will be removing an about:blank tab");
let r = `rand-${Math.random()}`;
ss.setTabValue(tab, "foobar", r);
yield promiseRemoveTab(tab);
let closedTabData = ss.getClosedTabData(window);
ok(!closedTabData.includes(r), "tab not stored in _closedTabs");
});

View file

@ -1,58 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
requestLongerTimeout(2);
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org/#1" }], extData: { "uniq": r() }, pinned: true },
{ entries: [{ url: "http://example.org/#2" }], extData: { "uniq": r() }, pinned: true },
{ entries: [{ url: "http://example.org/#3" }], extData: { "uniq": r() }, pinned: true },
{ entries: [{ url: "http://example.org/#4" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#5" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#6" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#7" }], extData: { "uniq": r() } },
], selected: 5 }] };
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++;
// We'll make sure that the loads we get come from pinned tabs or the
// the selected tab.
// get the tab
let tab;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser)
tab = window.gBrowser.tabs[i];
}
ok(tab.pinned || tab.selected,
"load came from pinned or selected tab");
// We should get 4 loads: 3 app tabs + 1 normal selected tab
if (loadCount < 4)
return;
gProgressListener.unsetCallback();
resolve();
});
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state));
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,53 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
const PREF_RESTORE_PINNED_TABS_ON_DEMAND = "browser.sessionstore.restore_pinned_tabs_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
Services.prefs.setBoolPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND, true);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
Services.prefs.clearUserPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND);
});
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org/#1" }], extData: { "uniq": r() }, pinned: true },
{ entries: [{ url: "http://example.org/#2" }], extData: { "uniq": r() }, pinned: true },
{ entries: [{ url: "http://example.org/#3" }], extData: { "uniq": r() }, pinned: true },
{ entries: [{ url: "http://example.org/#4" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#5" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#6" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#7" }], extData: { "uniq": r() } },
], selected: 5 }] };
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
// get the tab
let tab;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser)
tab = window.gBrowser.tabs[i];
}
// Check that the load only comes from the selected tab.
ok(tab.selected, "load came from selected tab");
is(aNeedRestore, 6, "six tabs left to restore");
is(aRestoring, 1, "one tab is restoring");
is(aRestored, 0, "no tabs have been restored, yet");
gProgressListener.unsetCallback();
resolve();
});
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state));
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,113 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
requestLongerTimeout(2);
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
// The first state will be loaded using setBrowserState, followed by the 2nd
// state also being loaded using setBrowserState, interrupting the first restore.
let state1 = { windows: [
{
tabs: [
{ entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#3" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#4" }], extData: { "uniq": r() } }
],
selected: 1
},
{
tabs: [
{ entries: [{ url: "http://example.com#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#2" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#3" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#4" }], extData: { "uniq": r() } },
],
selected: 3
}
] };
let state2 = { windows: [
{
tabs: [
{ entries: [{ url: "http://example.org#5" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#6" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#7" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#8" }], extData: { "uniq": r() } }
],
selected: 3
},
{
tabs: [
{ entries: [{ url: "http://example.com#5" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#6" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#7" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#8" }], extData: { "uniq": r() } },
],
selected: 1
}
] };
// interruptedAfter will be set after the selected tab from each window have loaded.
let interruptedAfter = 0;
let loadedWindow1 = false;
let loadedWindow2 = false;
let numTabs = state2.windows[0].tabs.length + state2.windows[1].tabs.length;
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++;
if (aBrowser.currentURI.spec == state1.windows[0].tabs[2].entries[0].url)
loadedWindow1 = true;
if (aBrowser.currentURI.spec == state1.windows[1].tabs[0].entries[0].url)
loadedWindow2 = true;
if (!interruptedAfter && loadedWindow1 && loadedWindow2) {
interruptedAfter = loadCount;
ss.setBrowserState(JSON.stringify(state2));
return;
}
if (loadCount < numTabs + interruptedAfter)
return;
// We don't actually care about load order in this test, just that they all
// do load.
is(loadCount, numTabs + interruptedAfter, "all tabs were restored");
is(aNeedRestore, 0, "there are no tabs left needing restore");
// Remove the progress listener.
gProgressListener.unsetCallback();
resolve();
});
});
// We also want to catch the extra windows (there should be 2), so we need to observe domwindowopened
Services.ww.registerNotification(function observer(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
Services.ww.unregisterNotification(observer);
win.gBrowser.addTabsProgressListener(gProgressListener);
});
}
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state1));
yield promiseRestoringTabs;
// Cleanup.
yield promiseAllButPrimaryWindowClosed();
yield promiseBrowserState(backupState);
});

View file

@ -1,54 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } }
] }] };
let expectedCounts = [
[3, 3, 0],
[2, 3, 1],
[1, 3, 2],
[0, 3, 3],
[0, 2, 4],
[0, 1, 5]
];
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++;
let expected = expectedCounts[loadCount - 1];
is(aNeedRestore, expected[0], "load " + loadCount + " - # tabs that need to be restored");
is(aRestoring, expected[1], "load " + loadCount + " - # tabs that are restoring");
is(aRestored, expected[2], "load " + loadCount + " - # tabs that has been restored");
if (loadCount == state.windows[0].tabs.length) {
gProgressListener.unsetCallback();
resolve();
}
});
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state));
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,70 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
// The first window will be put into the already open window and the second
// window will be opened with _openWindowWithState, which is the source of the problem.
let state = { windows: [
{
tabs: [
{ entries: [{ url: "http://example.org#0" }], extData: { "uniq": r() } }
],
selected: 1
},
{
tabs: [
{ entries: [{ url: "http://example.com#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#2" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#3" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#4" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#5" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#6" }], extData: { "uniq": r() } }
],
selected: 4
}
] };
let numTabs = state.windows[0].tabs.length + state.windows[1].tabs.length;
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
if (++loadCount == numTabs) {
// We don't actually care about load order in this test, just that they all
// do load.
is(loadCount, numTabs, "all tabs were restored");
is(aNeedRestore, 0, "there are no tabs left needing restore");
gProgressListener.unsetCallback();
resolve();
}
});
});
// We also want to catch the 2nd window, so we need to observe domwindowopened
Services.ww.registerNotification(function observer(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
Services.ww.unregisterNotification(observer);
win.gBrowser.addTabsProgressListener(gProgressListener);
});
}
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state));
yield promiseRestoringTabs;
// Cleanup.
yield promiseAllButPrimaryWindowClosed();
yield promiseBrowserState(backupState);
});

View file

@ -1,54 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org/#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#2" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#3" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#4" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#5" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#6" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#7" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#8" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org/#9" }], extData: { "uniq": r() } },
], selected: 1 }] };
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gBrowser.tabContainer.addEventListener("SSTabRestored", function onRestored(event) {
let tab = event.target;
let browser = tab.linkedBrowser;
let tabData = state.windows[0].tabs[loadCount++];
// double check that this tab was the right one
is(browser.currentURI.spec, tabData.entries[0].url,
"load " + loadCount + " - browser loaded correct url");
is(ss.getTabValue(tab, "uniq"), tabData.extData.uniq,
"load " + loadCount + " - correct tab was restored");
if (loadCount == state.windows[0].tabs.length) {
gBrowser.tabContainer.removeEventListener("SSTabRestored", onRestored);
resolve();
} else {
// reload the next tab
gBrowser.browsers[loadCount].reload();
}
});
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state));
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,69 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } }
], selected: 1 }] };
let expectedCounts = [
[5, 1, 0],
[4, 1, 1],
[3, 1, 2],
[2, 1, 3],
[1, 1, 4],
[0, 1, 5]
];
let tabOrder = [0, 5, 1, 4, 3, 2];
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++;
let expected = expectedCounts[loadCount - 1];
is(aNeedRestore, expected[0], "load " + loadCount + " - # tabs that need to be restored");
is(aRestoring, expected[1], "load " + loadCount + " - # tabs that are restoring");
is(aRestored, expected[2], "load " + loadCount + " - # tabs that has been restored");
if (loadCount < state.windows[0].tabs.length) {
// double check that this tab was the right one
let expectedData = state.windows[0].tabs[tabOrder[loadCount - 1]].extData.uniq;
let tab;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser)
tab = window.gBrowser.tabs[i];
}
is(ss.getTabValue(tab, "uniq"), expectedData,
"load " + loadCount + " - correct tab was restored");
// select the next tab
window.gBrowser.selectTabAtIndex(tabOrder[loadCount]);
} else {
gProgressListener.unsetCallback();
resolve();
}
});
});
let backupState = ss.getBrowserState();
ss.setBrowserState(JSON.stringify(state));
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,59 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
// We'll use 2 states so that we can make sure calling setWindowState doesn't
// wipe out currently restoring data.
let state1 = { windows: [{ tabs: [
{ entries: [{ url: "http://example.com#1" }] },
{ entries: [{ url: "http://example.com#2" }] },
{ entries: [{ url: "http://example.com#3" }] },
{ entries: [{ url: "http://example.com#4" }] },
{ entries: [{ url: "http://example.com#5" }] },
] }] };
let state2 = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org#1" }] },
{ entries: [{ url: "http://example.org#2" }] },
{ entries: [{ url: "http://example.org#3" }] },
{ entries: [{ url: "http://example.org#4" }] },
{ entries: [{ url: "http://example.org#5" }] }
] }] };
let numTabs = state1.windows[0].tabs.length + state2.windows[0].tabs.length;
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
// When loadCount == 2, we'll also restore state2 into the window
if (++loadCount == 2) {
ss.setWindowState(window, JSON.stringify(state2), false);
}
if (loadCount < numTabs) {
return;
}
// We don't actually care about load order in this test, just that they all
// do load.
is(loadCount, numTabs, "test_setWindowStateNoOverwrite: all tabs were restored");
is(aNeedRestore, 0, "there are no tabs left needing restore");
gProgressListener.unsetCallback();
resolve();
});
});
let backupState = ss.getBrowserState();
ss.setWindowState(window, JSON.stringify(state1), true);
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,59 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
// We'll use 2 states so that we can make sure calling setWindowState doesn't
// wipe out currently restoring data.
let state1 = { windows: [{ tabs: [
{ entries: [{ url: "http://example.com#1" }] },
{ entries: [{ url: "http://example.com#2" }] },
{ entries: [{ url: "http://example.com#3" }] },
{ entries: [{ url: "http://example.com#4" }] },
{ entries: [{ url: "http://example.com#5" }] },
] }] };
let state2 = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org#1" }] },
{ entries: [{ url: "http://example.org#2" }] },
{ entries: [{ url: "http://example.org#3" }] },
{ entries: [{ url: "http://example.org#4" }] },
{ entries: [{ url: "http://example.org#5" }] }
] }] };
let numTabs = 2 + state2.windows[0].tabs.length;
let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
// When loadCount == 2, we'll also restore state2 into the window
if (++loadCount == 2) {
executeSoon(() => ss.setWindowState(window, JSON.stringify(state2), true));
}
if (loadCount < numTabs) {
return;
}
// We don't actually care about load order in this test, just that they all
// do load.
is(loadCount, numTabs, "all tabs were restored");
is(aNeedRestore, 0, "there are no tabs left needing restore");
gProgressListener.unsetCallback();
resolve();
});
});
let backupState = ss.getBrowserState();
ss.setWindowState(window, JSON.stringify(state1), true);
yield promiseRestoringTabs;
// Cleanup.
yield promiseBrowserState(backupState);
});

View file

@ -1,52 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function observeOneRestore(callback) {
let topic = "sessionstore-browser-state-restored";
Services.obs.addObserver(function onRestore() {
Services.obs.removeObserver(onRestore, topic);
callback();
}, topic, false);
};
function test() {
waitForExplicitFinish();
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
let hiddenTab = gBrowser.addTab();
is(gBrowser.visibleTabs.length, 2, "should have 2 tabs before hiding");
gBrowser.showOnlyTheseTabs([origTab]);
is(gBrowser.visibleTabs.length, 1, "only 1 after hiding");
ok(hiddenTab.hidden, "sanity check that it's hidden");
let extraTab = gBrowser.addTab();
let state = ss.getBrowserState();
let stateObj = JSON.parse(state);
let tabs = stateObj.windows[0].tabs;
is(tabs.length, 3, "just checking that browser state is correct");
ok(!tabs[0].hidden, "first tab is visible");
ok(tabs[1].hidden, "second is hidden");
ok(!tabs[2].hidden, "third is visible");
// Make the third tab hidden and then restore the modified state object
tabs[2].hidden = true;
observeOneRestore(function() {
let testWindow = Services.wm.getEnumerator("navigator:browser").getNext();
is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab");
let tabs = testWindow.gBrowser.tabs;
ok(!tabs[0].hidden, "first is still visible");
ok(tabs[1].hidden, "second tab is still hidden");
ok(tabs[2].hidden, "third tab is now hidden");
// Restore the original state and clean up now that we're done
gBrowser.removeTab(hiddenTab);
gBrowser.removeTab(extraTab);
finish();
});
ss.setBrowserState(JSON.stringify(stateObj));
}

View file

@ -1,41 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let state = { windows: [{ tabs: [
{entries: [{url: "about:mozilla"}], hidden: true},
{entries: [{url: "about:rights"}], hidden: true}
] }] };
waitForExplicitFinish();
newWindowWithState(state, function (win) {
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
is(win.gBrowser.tabs.length, 2, "two tabs were restored");
is(win.gBrowser.visibleTabs.length, 1, "one tab is visible");
let tab = win.gBrowser.visibleTabs[0];
is(tab.linkedBrowser.currentURI.spec, "about:mozilla", "visible tab is about:mozilla");
finish();
});
}
function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(function () {
win.addEventListener("SSWindowStateReady", function onReady() {
win.removeEventListener("SSWindowStateReady", onReady, false);
promiseTabRestored(win.gBrowser.tabs[0]).then(() => callback(win));
}, false);
ss.setWindowState(win, JSON.stringify(state), true);
});
}, false);
}

View file

@ -1,242 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Mirrors WINDOW_ATTRIBUTES IN nsSessionStore.js
const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
var stateBackup = ss.getBrowserState();
var originalWarnOnClose = gPrefService.getBoolPref("browser.tabs.warnOnClose");
var originalStartupPage = gPrefService.getIntPref("browser.startup.page");
var originalWindowType = document.documentElement.getAttribute("windowtype");
var gotLastWindowClosedTopic = false;
var shouldPinTab = false;
var shouldOpenTabs = false;
var shouldCloseTab = false;
var testNum = 0;
var afterTestCallback;
// Set state so we know the closed windows content
var testState = {
windows: [
{ tabs: [{ entries: [{ url: "http://example.org" }] }] }
],
_closedWindows: []
};
// We'll push a set of conditions and callbacks into this array
// Ideally we would also test win/linux under a complete set of conditions, but
// the tests for osx mirror the other set of conditions possible on win/linux.
var tests = [];
// the third & fourth test share a condition check, keep it DRY
function checkOSX34Generator(num) {
return function(aPreviousState, aCurState) {
// In here, we should have restored the pinned tab, so only the unpinned tab
// should be in aCurState. So let's shape our expectations.
let expectedState = JSON.parse(aPreviousState);
expectedState[0].tabs.shift();
// size attributes are stripped out in _prepDataForDeferredRestore in nsSessionStore.
// This isn't the best approach, but neither is comparing JSON strings
WINDOW_ATTRIBUTES.forEach(attr => delete expectedState[0][attr]);
is(aCurState, JSON.stringify(expectedState),
"test #" + num + ": closedWindowState is as expected");
};
}
function checkNoWindowsGenerator(num) {
return function(aPreviousState, aCurState) {
is(aCurState, "[]", "test #" + num + ": there should be no closedWindowsLeft");
};
}
// The first test has 0 pinned tabs and 1 unpinned tab
tests.push({
pinned: false,
extra: false,
close: false,
checkWinLin: checkNoWindowsGenerator(1),
checkOSX: function(aPreviousState, aCurState) {
is(aCurState, aPreviousState, "test #1: closed window state is unchanged");
}
});
// The second test has 1 pinned tab and 0 unpinned tabs.
tests.push({
pinned: true,
extra: false,
close: false,
checkWinLin: checkNoWindowsGenerator(2),
checkOSX: checkNoWindowsGenerator(2)
});
// The third test has 1 pinned tab and 2 unpinned tabs.
tests.push({
pinned: true,
extra: true,
close: false,
checkWinLin: checkNoWindowsGenerator(3),
checkOSX: checkOSX34Generator(3)
});
// The fourth test has 1 pinned tab, 2 unpinned tabs, and closes one unpinned tab.
tests.push({
pinned: true,
extra: true,
close: "one",
checkWinLin: checkNoWindowsGenerator(4),
checkOSX: checkOSX34Generator(4)
});
// The fifth test has 1 pinned tab, 2 unpinned tabs, and closes both unpinned tabs.
tests.push({
pinned: true,
extra: true,
close: "both",
checkWinLin: checkNoWindowsGenerator(5),
checkOSX: checkNoWindowsGenerator(5)
});
function test() {
/** Test for Bug 589246 - Closed window state getting corrupted when closing
and reopening last browser window without exiting browser **/
waitForExplicitFinish();
// windows opening & closing, so extending the timeout
requestLongerTimeout(2);
// We don't want the quit dialog pref
gPrefService.setBoolPref("browser.tabs.warnOnClose", false);
// Ensure that we would restore the session (important for Windows)
gPrefService.setIntPref("browser.startup.page", 3);
runNextTestOrFinish();
}
function runNextTestOrFinish() {
if (tests.length) {
setupForTest(tests.shift())
}
else {
// some state is cleaned up at the end of each test, but not all
["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) {
if (gPrefService.prefHasUserValue(p))
gPrefService.clearUserPref(p);
});
ss.setBrowserState(stateBackup);
executeSoon(finish);
}
}
function setupForTest(aConditions) {
// reset some checks
gotLastWindowClosedTopic = false;
shouldPinTab = aConditions.pinned;
shouldOpenTabs = aConditions.extra;
shouldCloseTab = aConditions.close;
testNum++;
// set our test callback
afterTestCallback = /Mac/.test(navigator.platform) ? aConditions.checkOSX
: aConditions.checkWinLin;
// Add observers
Services.obs.addObserver(onLastWindowClosed, "browser-lastwindow-close-granted", false);
// Set the state
Services.obs.addObserver(onStateRestored, "sessionstore-browser-state-restored", false);
ss.setBrowserState(JSON.stringify(testState));
}
function onStateRestored(aSubject, aTopic, aData) {
info("test #" + testNum + ": onStateRestored");
Services.obs.removeObserver(onStateRestored, "sessionstore-browser-state-restored");
// change this window's windowtype so that closing a new window will trigger
// browser-lastwindow-close-granted.
document.documentElement.setAttribute("windowtype", "navigator:testrunner");
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "http://example.com");
newWin.addEventListener("load", function(aEvent) {
newWin.removeEventListener("load", arguments.callee, false);
promiseBrowserLoaded(newWin.gBrowser.selectedBrowser).then(() => {
// pin this tab
if (shouldPinTab)
newWin.gBrowser.pinTab(newWin.gBrowser.selectedTab);
newWin.addEventListener("unload", function () {
newWin.removeEventListener("unload", arguments.callee, false);
onWindowUnloaded();
}, false);
// Open a new tab as well. On Windows/Linux this will be restored when the
// new window is opened below (in onWindowUnloaded). On OS X we'll just
// restore the pinned tabs, leaving the unpinned tab in the closedWindowsData.
if (shouldOpenTabs) {
let newTab = newWin.gBrowser.addTab("about:config");
let newTab2 = newWin.gBrowser.addTab("about:buildconfig");
newTab.linkedBrowser.addEventListener("load", function() {
newTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
if (shouldCloseTab == "one") {
newWin.gBrowser.removeTab(newTab2);
}
else if (shouldCloseTab == "both") {
newWin.gBrowser.removeTab(newTab);
newWin.gBrowser.removeTab(newTab2);
}
newWin.BrowserTryToCloseWindow();
}, true);
}
else {
newWin.BrowserTryToCloseWindow();
}
});
}, false);
}
// This will be called before the window is actually closed
function onLastWindowClosed(aSubject, aTopic, aData) {
info("test #" + testNum + ": onLastWindowClosed");
Services.obs.removeObserver(onLastWindowClosed, "browser-lastwindow-close-granted");
gotLastWindowClosedTopic = true;
}
// This is the unload event listener on the new window (from onStateRestored).
// Unload is fired after the window is closed, so sessionstore has already
// updated _closedWindows (which is important). We'll open a new window here
// which should actually trigger the bug.
function onWindowUnloaded() {
info("test #" + testNum + ": onWindowClosed");
ok(gotLastWindowClosedTopic, "test #" + testNum + ": browser-lastwindow-close-granted was notified prior");
let previousClosedWindowData = ss.getClosedWindowData();
// Now we want to open a new window
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla");
newWin.addEventListener("load", function(aEvent) {
newWin.removeEventListener("load", arguments.callee, false);
newWin.gBrowser.selectedBrowser.addEventListener("load", function () {
newWin.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
// Good enough for checking the state
afterTestCallback(previousClosedWindowData, ss.getClosedWindowData());
afterTestCleanup(newWin);
}, true);
}, false);
}
function afterTestCleanup(aNewWin) {
executeSoon(function() {
BrowserTestUtils.closeWindow(aNewWin).then(() => {
document.documentElement.setAttribute("windowtype", originalWindowType);
runNextTestOrFinish();
});
});
}

View file

@ -1,137 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const NUM_TABS = 12;
var stateBackup = ss.getBrowserState();
function test() {
/** Test for Bug 590268 - Provide access to sessionstore tab data sooner **/
waitForExplicitFinish();
requestLongerTimeout(2);
let startedTest = false;
// wasLoaded will be used to keep track of tabs that have already had SSTabRestoring
// fired for them.
let wasLoaded = { };
let restoringTabsCount = 0;
let restoredTabsCount = 0;
let uniq2 = { };
let uniq2Count = 0;
let state = { windows: [{ tabs: [] }] };
// We're going to put a bunch of tabs into this state
for (let i = 0; i < NUM_TABS; i++) {
let uniq = r();
let tabData = {
entries: [{ url: "http://example.com/#" + i }],
extData: { "uniq": uniq, "baz": "qux" }
};
state.windows[0].tabs.push(tabData);
wasLoaded[uniq] = false;
}
function onSSTabRestoring(aEvent) {
restoringTabsCount++;
let uniq = ss.getTabValue(aEvent.originalTarget, "uniq");
wasLoaded[uniq] = true;
is(ss.getTabValue(aEvent.originalTarget, "foo"), "",
"There is no value for 'foo'");
// On the first SSTabRestoring we're going to run the the real test.
// We'll keep this listener around so we can keep marking tabs as restored.
if (restoringTabsCount == 1)
onFirstSSTabRestoring();
else if (restoringTabsCount == NUM_TABS)
onLastSSTabRestoring();
}
function onSSTabRestored(aEvent) {
if (++restoredTabsCount < NUM_TABS)
return;
cleanup();
}
function onTabOpen(aEvent) {
// To test bug 614708, we'll just set a value on the tab here. This value
// would previously cause us to not recognize the values in extData until
// much later. So testing "uniq" failed.
ss.setTabValue(aEvent.originalTarget, "foo", "bar");
}
// This does the actual testing. SSTabRestoring should be firing on tabs from
// left to right, so we're going to start with the rightmost tab.
function onFirstSSTabRestoring() {
info("onFirstSSTabRestoring...");
for (let i = gBrowser.tabs.length - 1; i >= 0; i--) {
let tab = gBrowser.tabs[i];
let actualUniq = ss.getTabValue(tab, "uniq");
let expectedUniq = state.windows[0].tabs[i].extData["uniq"];
if (wasLoaded[actualUniq]) {
info("tab " + i + ": already restored");
continue;
}
is(actualUniq, expectedUniq, "tab " + i + ": extData was correct");
// Now we're going to set a piece of data back on the tab so it can be read
// to test setting a value "early".
uniq2[actualUniq] = r();
ss.setTabValue(tab, "uniq2", uniq2[actualUniq]);
// Delete the value we have for "baz". This tests that deleteTabValue
// will delete "early access" values (c.f. bug 617175). If this doesn't throw
// then the test is successful.
try {
ss.deleteTabValue(tab, "baz");
}
catch (e) {
ok(false, "no error calling deleteTabValue - " + e);
}
// This will be used in the final comparison to make sure we checked the
// same number as we set.
uniq2Count++;
}
}
function onLastSSTabRestoring() {
let checked = 0;
for (let i = 0; i < gBrowser.tabs.length; i++) {
let tab = gBrowser.tabs[i];
let uniq = ss.getTabValue(tab, "uniq");
// Look to see if we set a uniq2 value for this uniq value
if (uniq in uniq2) {
is(ss.getTabValue(tab, "uniq2"), uniq2[uniq], "tab " + i + " has correct uniq2 value");
checked++;
}
}
ok(uniq2Count > 0, "at least 1 tab properly checked 'early access'");
is(checked, uniq2Count, "checked the same number of uniq2 as we set");
}
function cleanup() {
// remove the event listener and clean up before finishing
gBrowser.tabContainer.removeEventListener("SSTabRestoring", onSSTabRestoring, false);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, true);
gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, false);
// Put this in an executeSoon because we still haven't called restoreNextTab
// in sessionstore for the last tab (we'll call it after this). We end up
// trying to restore the tab (since we then add a closed tab to the array).
executeSoon(function() {
ss.setBrowserState(stateBackup);
executeSoon(finish);
});
}
// Add the event listeners
gBrowser.tabContainer.addEventListener("SSTabRestoring", onSSTabRestoring, false);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, true);
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, false);
// Restore state
ss.setBrowserState(JSON.stringify(state));
}

View file

@ -1,74 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let sessionData = {
windows: [{
tabs: [
{ entries: [{ url: "about:mozilla" }], hidden: true },
{ entries: [{ url: "about:blank" }], hidden: false }
]
}]
};
let url = "about:sessionrestore";
let formdata = {id: {sessionData}, url};
let state = { windows: [{ tabs: [{ entries: [{url}], formdata }] }] };
waitForExplicitFinish();
newWindowWithState(state, function (win) {
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
is(gBrowser.tabs.length, 1, "The total number of tabs should be 1");
is(gBrowser.visibleTabs.length, 1, "The total number of visible tabs should be 1");
executeSoon(function () {
waitForFocus(function () {
middleClickTest(win);
finish();
}, win);
});
});
}
function middleClickTest(win) {
let browser = win.gBrowser.selectedBrowser;
let tree = browser.contentDocument.getElementById("tabList");
is(tree.view.rowCount, 3, "There should be three items");
// click on the first tab item
var rect = tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[1], "text");
EventUtils.synthesizeMouse(tree.body, rect.x, rect.y, { button: 1 },
browser.contentWindow);
// click on the second tab item
rect = tree.treeBoxObject.getCoordsForCellItem(2, tree.columns[1], "text");
EventUtils.synthesizeMouse(tree.body, rect.x, rect.y, { button: 1 },
browser.contentWindow);
is(win.gBrowser.tabs.length, 3,
"The total number of tabs should be 3 after restoring 2 tabs by middle click.");
is(win.gBrowser.visibleTabs.length, 3,
"The total number of visible tabs should be 3 after restoring 2 tabs by middle click");
}
function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
let tab = win.gBrowser.selectedTab;
// The form data will be restored before SSTabRestored, so we want to listen
// for that on the currently selected tab (it will be reused)
tab.addEventListener("SSTabRestored", function onRestored() {
tab.removeEventListener("SSTabRestored", onRestored, true);
callback(win);
}, true);
executeSoon(function () {
ss.setWindowState(win, JSON.stringify(state), true);
});
}, false);
}

View file

@ -1,112 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var state = {windows:[{tabs:[
{entries:[{url:"http://example.com#1"}]},
{entries:[{url:"http://example.com#2"}]},
{entries:[{url:"http://example.com#3"}]},
{entries:[{url:"http://example.com#4"}]},
{entries:[{url:"http://example.com#5"}], hidden: true},
{entries:[{url:"http://example.com#6"}], hidden: true},
{entries:[{url:"http://example.com#7"}], hidden: true},
{entries:[{url:"http://example.com#8"}], hidden: true}
]}]};
function test() {
waitForExplicitFinish();
requestLongerTimeout(2);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
});
// First stage: restoreHiddenTabs = true
// Second stage: restoreHiddenTabs = false
test_loadTabs(true, function () {
test_loadTabs(false, finish);
});
}
function test_loadTabs(restoreHiddenTabs, callback) {
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", restoreHiddenTabs);
let expectedTabs = restoreHiddenTabs ? 8 : 4;
let firstProgress = true;
newWindowWithState(state, function (win, needsRestore, isRestoring) {
if (firstProgress) {
firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently");
} else {
ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
}
// We're explicity checking for (isRestoring == 1) here because the test
// progress listener is called before the session store one. So when we're
// called with one tab left to restore we know that the last tab has
// finished restoring and will soon be handled by the SS listener.
let tabsNeedingRestore = win.gBrowser.tabs.length - needsRestore;
if (isRestoring == 1 && tabsNeedingRestore == expectedTabs) {
is(win.gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
TabsProgressListener.uninit();
executeSoon(callback);
}
});
}
var TabsProgressListener = {
init: function (win) {
this.window = win;
Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false);
},
uninit: function () {
Services.obs.removeObserver(this, "sessionstore-debug-tab-restored");
delete this.window;
delete this.callback;
},
setCallback: function (callback) {
this.callback = callback;
},
observe: function (browser) {
TabsProgressListener.onRestored(browser);
},
onRestored: function (browser) {
if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING)
this.callback.apply(null, [this.window].concat(this.countTabs()));
},
countTabs: function () {
let needsRestore = 0, isRestoring = 0;
for (let i = 0; i < this.window.gBrowser.tabs.length; i++) {
let browser = this.window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
return [needsRestore, isRestoring];
}
}
// ----------
function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
whenWindowLoaded(win, function onWindowLoaded(aWin) {
TabsProgressListener.init(aWin);
TabsProgressListener.setCallback(callback);
ss.setWindowState(aWin, JSON.stringify(state), true);
});
}

View file

@ -1,36 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 597071 - Closed windows should only be resurrected when there is a single
* popup window
*/
add_task(function test_close_last_nonpopup_window() {
// Purge the list of closed windows.
forgetClosedWindows();
let oldState = ss.getWindowState(window);
let popupState = {windows: [
{tabs: [{entries: []}], isPopup: true, hidden: "toolbar"}
]};
// Set this window to be a popup.
ss.setWindowState(window, JSON.stringify(popupState), true);
// Open a new window with a tab.
let win = yield BrowserTestUtils.openNewBrowserWindow({private: false});
let tab = win.gBrowser.addTab("http://example.com/");
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
// Make sure sessionstore sees this window.
let state = JSON.parse(ss.getBrowserState());
is(state.windows.length, 2, "sessionstore knows about this window");
// Closed the window and check the closed window count.
yield BrowserTestUtils.closeWindow(win);
is(ss.getClosedWindowCount(), 1, "correct closed window count");
// Cleanup.
ss.setWindowState(window, oldState, true);
});

View file

@ -1,120 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var stateBackup = ss.getBrowserState();
function cleanup() {
// Reset the pref
try {
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
} catch (e) {}
ss.setBrowserState(stateBackup);
executeSoon(finish);
}
function test() {
/** Bug 599909 - to-be-reloaded tabs don't show up in switch-to-tab **/
waitForExplicitFinish();
// Set the pref to true so we know exactly how many tabs should be restoring at
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org/#1" }] },
{ entries: [{ url: "http://example.org/#2" }] },
{ entries: [{ url: "http://example.org/#3" }] },
{ entries: [{ url: "http://example.org/#4" }] }
], selected: 1 }] };
let tabsForEnsure = {};
state.windows[0].tabs.forEach(function(tab) {
tabsForEnsure[tab.entries[0].url] = 1;
});
let tabsRestoring = 0;
let tabsRestored = 0;
function handleEvent(aEvent) {
if (aEvent.type == "SSTabRestoring")
tabsRestoring++;
else
tabsRestored++;
if (tabsRestoring < state.windows[0].tabs.length ||
tabsRestored < 1)
return;
gBrowser.tabContainer.removeEventListener("SSTabRestoring", handleEvent, true);
gBrowser.tabContainer.removeEventListener("SSTabRestored", handleEvent, true);
executeSoon(function() {
checkAutocompleteResults(tabsForEnsure, cleanup);
});
}
// currentURI is set before SSTabRestoring is fired, so we can sucessfully check
// after that has fired for all tabs. Since 1 tab will be restored though, we
// also need to wait for 1 SSTabRestored since currentURI will be set, unset, then set.
gBrowser.tabContainer.addEventListener("SSTabRestoring", handleEvent, true);
gBrowser.tabContainer.addEventListener("SSTabRestored", handleEvent, true);
ss.setBrowserState(JSON.stringify(state));
}
// The following was taken from browser/base/content/test/general/browser_tabMatchesInAwesomebar.js
// so that we could do the same sort of checking.
var gController = Cc["@mozilla.org/autocomplete/controller;1"].
getService(Ci.nsIAutoCompleteController);
function checkAutocompleteResults(aExpected, aCallback) {
gController.input = {
timeout: 10,
textValue: "",
searches: ["unifiedcomplete"],
searchParam: "enable-actions",
popupOpen: false,
minResultsForPopup: 0,
invalidate: function() {},
disableAutoComplete: false,
completeDefaultIndex: false,
get popup() { return this; },
onSearchBegin: function() {},
onSearchComplete: function ()
{
info("Found " + gController.matchCount + " matches.");
// Check to see the expected uris and titles match up (in any order)
for (let i = 0; i < gController.matchCount; i++) {
if (gController.getStyleAt(i).includes("heuristic")) {
info("Skip heuristic match");
continue;
}
let action = gURLBar.popup.input._parseActionUrl(gController.getValueAt(i));
let uri = action.params.url;
info("Search for '" + uri + "' in open tabs.");
ok(uri in aExpected, "Registered open page found in autocomplete.");
// Remove the found entry from expected results.
delete aExpected[uri];
}
// Make sure there is no reported open page that is not open.
for (let entry in aExpected) {
ok(false, "'" + entry + "' not found in autocomplete.");
}
executeSoon(aCallback);
},
setSelectedIndex: function() {},
get searchCount() { return this.searches.length; },
getSearchAt: function(aIndex) {
return this.searches[aIndex];
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIAutoCompleteInput,
Ci.nsIAutoCompletePopup,
])
};
info("Searching open pages.");
gController.startSearch(Services.prefs.getCharPref("browser.urlbar.restrict.openpage"));
}

View file

@ -1,89 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
requestLongerTimeout(2);
var stateBackup = JSON.parse(ss.getBrowserState());
function test() {
/** Test for Bug 600545 **/
waitForExplicitFinish();
testBug600545();
}
function testBug600545() {
// Set the pref to false to cause non-app tabs to be stripped out on a save
Services.prefs.setBoolPref("browser.sessionstore.resume_from_crash", false);
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("browser.sessionstore.resume_from_crash");
Services.prefs.clearUserPref("browser.sessionstore.interval");
});
// This tests the following use case: When multiple windows are open
// and browser.sessionstore.resume_from_crash preference is false,
// tab session data for non-active window is stripped for non-pinned
// tabs. This occurs after "sessionstore-state-write-complete"
// fires which will only fire in this case if there is at least one
// pinned tab.
let state = { windows: [
{
tabs: [
{ entries: [{ url: "http://example.org#0" }], pinned:true },
{ entries: [{ url: "http://example.com#1" }] },
{ entries: [{ url: "http://example.com#2" }] },
],
selected: 2
},
{
tabs: [
{ entries: [{ url: "http://example.com#3" }] },
{ entries: [{ url: "http://example.com#4" }] },
{ entries: [{ url: "http://example.com#5" }] },
{ entries: [{ url: "http://example.com#6" }] }
],
selected: 3
}
] };
waitForBrowserState(state, function() {
// Need to wait for SessionStore's saveState function to be called
// so that non-pinned tabs will be stripped from non-active window
waitForSaveState(function () {
let expectedNumberOfTabs = getStateTabCount(state);
let retrievedState = JSON.parse(ss.getBrowserState());
let actualNumberOfTabs = getStateTabCount(retrievedState);
is(actualNumberOfTabs, expectedNumberOfTabs,
"Number of tabs in retreived session data, matches number of tabs set.");
done();
});
});
}
function done() {
// Enumerate windows and close everything but our primary window. We can't
// use waitForFocus() because apparently it's buggy. See bug 599253.
let windowsEnum = Services.wm.getEnumerator("navigator:browser");
let closeWinPromises = [];
while (windowsEnum.hasMoreElements()) {
let currentWindow = windowsEnum.getNext();
if (currentWindow != window)
closeWinPromises.push(BrowserTestUtils.closeWindow(currentWindow));
}
Promise.all(closeWinPromises).then(() => {
waitForBrowserState(stateBackup, finish);
});
}
// Count up the number of tabs in the state data
function getStateTabCount(aState) {
let tabCount = 0;
for (let i in aState.windows)
tabCount += aState.windows[i].tabs.length;
return tabCount;
}

View file

@ -1,54 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This tests that pinning/unpinning a tab, on its own, eventually triggers a
// session store.
function test() {
waitForExplicitFinish();
// We speed up the interval between session saves to ensure that the test
// runs quickly.
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
// Loading a tab causes a save state and this is meant to catch that event.
waitForSaveState(testBug601955_1);
// Assumption: Only one window is open and it has one tab open.
gBrowser.addTab("about:mozilla");
}
function testBug601955_1() {
// Because pinned tabs are at the front of |gBrowser.tabs|, pinning tabs
// re-arranges the |tabs| array.
ok(!gBrowser.tabs[0].pinned, "first tab should not be pinned yet");
ok(!gBrowser.tabs[1].pinned, "second tab should not be pinned yet");
waitForSaveState(testBug601955_2);
gBrowser.pinTab(gBrowser.tabs[0]);
}
function testBug601955_2() {
let state = JSON.parse(ss.getBrowserState());
ok(state.windows[0].tabs[0].pinned, "first tab should be pinned by now");
ok(!state.windows[0].tabs[1].pinned, "second tab should still not be pinned");
waitForSaveState(testBug601955_3);
gBrowser.unpinTab(window.gBrowser.tabs[0]);
}
function testBug601955_3() {
let state = JSON.parse(ss.getBrowserState());
ok(!state.windows[0].tabs[0].pinned, "first tab should not be pinned");
ok(!state.windows[0].tabs[1].pinned, "second tab should not be pinned");
done();
}
function done() {
gBrowser.removeTab(window.gBrowser.tabs[1]);
Services.prefs.clearUserPref("browser.sessionstore.interval");
executeSoon(finish);
}

View file

@ -1,98 +0,0 @@
"use strict";
var stateBackup = ss.getBrowserState();
add_task(function* () {
/** Bug 607016 - If a tab is never restored, attributes (eg. hidden) aren't updated correctly **/
ignoreAllUncaughtExceptions();
// Set the pref to true so we know exactly how many tabs should be restoring at
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } }, // overwriting
{ entries: [{ url: "http://example.org#3" }], extData: { "uniq": r() } }, // hiding
{ entries: [{ url: "http://example.org#4" }], extData: { "uniq": r() } }, // adding
{ entries: [{ url: "http://example.org#5" }], extData: { "uniq": r() } }, // deleting
{ entries: [{ url: "http://example.org#6" }] } // creating
], selected: 1 }] };
function* progressCallback() {
let curState = JSON.parse(ss.getBrowserState());
for (let i = 0; i < curState.windows[0].tabs.length; i++) {
let tabState = state.windows[0].tabs[i];
let tabCurState = curState.windows[0].tabs[i];
if (tabState.extData) {
is(tabCurState.extData["uniq"], tabState.extData["uniq"],
"sanity check that tab has correct extData");
}
else {
// We aren't expecting there to be any data on extData, but panorama
// may be setting something, so we need to make sure that if we do have
// data, we just don't have anything for "uniq".
ok(!("extData" in tabCurState) || !("uniq" in tabCurState.extData),
"sanity check that tab doesn't have extData or extData doesn't have 'uniq'");
}
}
// Now we'll set a new unique value on 1 of the tabs
let newUniq = r();
ss.setTabValue(gBrowser.tabs[1], "uniq", newUniq);
let tabState = JSON.parse(ss.getTabState(gBrowser.tabs[1]));
is(tabState.extData.uniq, newUniq,
"(overwriting) new data is stored in extData");
// hide the next tab before closing it
gBrowser.hideTab(gBrowser.tabs[2]);
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[2]));
ok(tabState.hidden, "(hiding) tab data has hidden == true");
// set data that's not in a conflicting key
let stillUniq = r();
ss.setTabValue(gBrowser.tabs[3], "stillUniq", stillUniq);
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[3]));
is(tabState.extData.stillUniq, stillUniq,
"(adding) new data is stored in extData");
// remove the uniq value and make sure it's not there in the closed data
ss.deleteTabValue(gBrowser.tabs[4], "uniq");
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[4]));
// Since Panorama might have put data in, first check if there is extData.
// If there is explicitly check that "uniq" isn't in it. Otherwise, we're ok
if ("extData" in tabState) {
ok(!("uniq" in tabState.extData),
"(deleting) uniq not in existing extData");
}
else {
ok(true, "(deleting) no data is stored in extData");
}
// set unique data on the tab that never had any set, make sure that's saved
let newUniq2 = r();
ss.setTabValue(gBrowser.tabs[5], "uniq", newUniq2);
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[5]));
is(tabState.extData.uniq, newUniq2,
"(creating) new data is stored in extData where there was none");
while (gBrowser.tabs.length > 1) {
yield promiseRemoveTab(gBrowser.tabs[1]);
}
}
// Set the test state.
ss.setBrowserState(JSON.stringify(state));
// Wait until the selected tab is restored and all others are pending.
yield Promise.all(Array.map(gBrowser.tabs, tab => {
return (tab == gBrowser.selectedTab) ?
promiseTabRestored(tab) : promiseTabRestoring(tab)
}));
// Kick off the actual tests.
yield progressCallback();
// Cleanup.
yield promiseBrowserState(stateBackup);
});

View file

@ -1,361 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const stateBackup = JSON.parse(ss.getBrowserState());
const testState = {
windows: [{
tabs: [
{ entries: [{ url: "about:blank" }] },
{ entries: [{ url: "about:rights" }] }
]
}]
};
const lameMultiWindowState = { windows: [
{
tabs: [
{ entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#3" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#4" }], extData: { "uniq": r() } }
],
selected: 1
},
{
tabs: [
{ entries: [{ url: "http://example.com#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#2" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#3" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com#4" }], extData: { "uniq": r() } },
],
selected: 3
}
] };
function getOuterWindowID(aWindow) {
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
}
function test() {
/** Test for Bug 615394 - Session Restore should notify when it is beginning and ending a restore **/
waitForExplicitFinish();
// Preemptively extend the timeout to prevent [orange]
requestLongerTimeout(4);
runNextTest();
}
var tests = [
test_setTabState,
test_duplicateTab,
test_undoCloseTab,
test_setWindowState,
test_setBrowserState,
test_undoCloseWindow
];
function runNextTest() {
// set an empty state & run the next test, or finish
if (tests.length) {
// Enumerate windows and close everything but our primary window. We can't
// use waitForFocus() because apparently it's buggy. See bug 599253.
var windowsEnum = Services.wm.getEnumerator("navigator:browser");
let closeWinPromises = [];
while (windowsEnum.hasMoreElements()) {
var currentWindow = windowsEnum.getNext();
if (currentWindow != window) {
closeWinPromises.push(BrowserTestUtils.closeWindow(currentWindow));
}
}
Promise.all(closeWinPromises).then(() => {
let currentTest = tests.shift();
info("prepping for " + currentTest.name);
waitForBrowserState(testState, currentTest);
});
}
else {
waitForBrowserState(stateBackup, finish);
}
}
/** ACTUAL TESTS **/
function test_setTabState() {
let tab = gBrowser.tabs[1];
let newTabState = JSON.stringify({ entries: [{ url: "http://example.org" }], extData: { foo: "bar" } });
let busyEventCount = 0;
let readyEventCount = 0;
function onSSWindowStateBusy(aEvent) {
busyEventCount++;
}
function onSSWindowStateReady(aEvent) {
readyEventCount++;
is(ss.getTabValue(tab, "foo"), "bar");
ss.setTabValue(tab, "baz", "qux");
}
function onSSTabRestored(aEvent) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(tab, "baz"), "qux");
is(tab.linkedBrowser.currentURI.spec, "http://example.org/");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
runNextTest();
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
ss.setTabState(tab, newTabState);
}
function test_duplicateTab() {
let tab = gBrowser.tabs[1];
let busyEventCount = 0;
let readyEventCount = 0;
let newTab;
// We'll look to make sure this value is on the duplicated tab
ss.setTabValue(tab, "foo", "bar");
function onSSWindowStateBusy(aEvent) {
busyEventCount++;
}
function onSSWindowStateReady(aEvent) {
newTab = gBrowser.tabs[2];
readyEventCount++;
is(ss.getTabValue(newTab, "foo"), "bar");
ss.setTabValue(newTab, "baz", "qux");
}
function onSSTabRestored(aEvent) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(newTab, "baz"), "qux");
is(newTab.linkedBrowser.currentURI.spec, "about:rights");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
runNextTest();
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
newTab = ss.duplicateTab(window, tab);
}
function test_undoCloseTab() {
let tab = gBrowser.tabs[1],
busyEventCount = 0,
readyEventCount = 0,
reopenedTab;
ss.setTabValue(tab, "foo", "bar");
function onSSWindowStateBusy(aEvent) {
busyEventCount++;
}
function onSSWindowStateReady(aEvent) {
reopenedTab = gBrowser.tabs[1];
readyEventCount++;
is(ss.getTabValue(reopenedTab, "foo"), "bar");
ss.setTabValue(reopenedTab, "baz", "qux");
}
function onSSTabRestored(aEvent) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(reopenedTab, "baz"), "qux");
is(reopenedTab.linkedBrowser.currentURI.spec, "about:rights");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
runNextTest();
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
gBrowser.removeTab(tab);
reopenedTab = ss.undoCloseTab(window, 0);
}
function test_setWindowState() {
let testState = {
windows: [{
tabs: [
{ entries: [{ url: "about:mozilla" }], extData: { "foo": "bar" } },
{ entries: [{ url: "http://example.org" }], extData: { "baz": "qux" } }
]
}]
};
let busyEventCount = 0,
readyEventCount = 0,
tabRestoredCount = 0;
function onSSWindowStateBusy(aEvent) {
busyEventCount++;
}
function onSSWindowStateReady(aEvent) {
readyEventCount++;
is(ss.getTabValue(gBrowser.tabs[0], "foo"), "bar");
is(ss.getTabValue(gBrowser.tabs[1], "baz"), "qux");
}
function onSSTabRestored(aEvent) {
if (++tabRestoredCount < 2)
return;
is(busyEventCount, 1);
is(readyEventCount, 1);
is(gBrowser.tabs[0].linkedBrowser.currentURI.spec, "about:mozilla");
is(gBrowser.tabs[1].linkedBrowser.currentURI.spec, "http://example.org/");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
runNextTest();
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
ss.setWindowState(window, JSON.stringify(testState), true);
}
function test_setBrowserState() {
// We'll track events per window so we are sure that they are each happening once
// pre window.
let windowEvents = {};
windowEvents[getOuterWindowID(window)] = { busyEventCount: 0, readyEventCount: 0 };
// waitForBrowserState does it's own observing for windows, but doesn't attach
// the listeners we want here, so do it ourselves.
let newWindow;
function windowObserver(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
newWindow.addEventListener("load", function() {
newWindow.removeEventListener("load", arguments.callee, false);
Services.ww.unregisterNotification(windowObserver);
windowEvents[getOuterWindowID(newWindow)] = { busyEventCount: 0, readyEventCount: 0 };
newWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
newWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
}, false);
}
}
function onSSWindowStateBusy(aEvent) {
windowEvents[getOuterWindowID(aEvent.originalTarget)].busyEventCount++;
}
function onSSWindowStateReady(aEvent) {
windowEvents[getOuterWindowID(aEvent.originalTarget)].readyEventCount++;
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
Services.ww.registerNotification(windowObserver);
waitForBrowserState(lameMultiWindowState, function() {
let checkedWindows = 0;
for (let id of Object.keys(windowEvents)) {
let winEvents = windowEvents[id];
is(winEvents.busyEventCount, 1,
"[test_setBrowserState] window" + id + " busy event count correct");
is(winEvents.readyEventCount, 1,
"[test_setBrowserState] window" + id + " ready event count correct");
checkedWindows++;
}
is(checkedWindows, 2,
"[test_setBrowserState] checked 2 windows");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
newWindow.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
newWindow.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
runNextTest();
});
}
function test_undoCloseWindow() {
let newWindow, reopenedWindow;
function firstWindowObserver(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
Services.ww.unregisterNotification(firstWindowObserver);
}
}
Services.ww.registerNotification(firstWindowObserver);
waitForBrowserState(lameMultiWindowState, function() {
// Close the window which isn't window
BrowserTestUtils.closeWindow(newWindow).then(() => {
// Now give it time to close
reopenedWindow = ss.undoCloseWindow(0);
reopenedWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
reopenedWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
reopenedWindow.addEventListener("load", function() {
reopenedWindow.removeEventListener("load", arguments.callee, false);
reopenedWindow.gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
}, false);
});
});
let busyEventCount = 0,
readyEventCount = 0,
tabRestoredCount = 0;
// These will listen to the reopened closed window...
function onSSWindowStateBusy(aEvent) {
busyEventCount++;
}
function onSSWindowStateReady(aEvent) {
readyEventCount++;
}
function onSSTabRestored(aEvent) {
if (++tabRestoredCount < 4)
return;
is(busyEventCount, 1);
is(readyEventCount, 1);
reopenedWindow.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
reopenedWindow.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
reopenedWindow.gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
BrowserTestUtils.closeWindow(reopenedWindow).then(runNextTest);
}
}

View file

@ -1,65 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const stateBackup = ss.getBrowserState();
const testState = {
windows: [{
tabs: [
{ entries: [{ url: "about:blank" }] },
{ entries: [{ url: "about:mozilla" }] }
]
}]
};
function test() {
/** Test for Bug 618151 - Overwriting state can lead to unrestored tabs **/
waitForExplicitFinish();
runNextTest();
}
// Just a subset of tests from bug 615394 that causes a timeout.
var tests = [test_setup, test_hang];
function runNextTest() {
// set an empty state & run the next test, or finish
if (tests.length) {
// Enumerate windows and close everything but our primary window. We can't
// use waitForFocus() because apparently it's buggy. See bug 599253.
var windowsEnum = Services.wm.getEnumerator("navigator:browser");
let closeWinPromises = [];
while (windowsEnum.hasMoreElements()) {
var currentWindow = windowsEnum.getNext();
if (currentWindow != window) {
closeWinPromises.push(BrowserTestUtils.closeWindow(currentWindow));
}
}
Promise.all(closeWinPromises).then(() => {
let currentTest = tests.shift();
info("running " + currentTest.name);
waitForBrowserState(testState, currentTest);
});
}
else {
ss.setBrowserState(stateBackup);
executeSoon(finish);
}
}
function test_setup() {
function onSSTabRestored(aEvent) {
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
runNextTest();
}
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
ss.setTabState(gBrowser.tabs[1], JSON.stringify({
entries: [{ url: "http://example.org" }],
extData: { foo: "bar" } }));
}
function test_hang() {
ok(true, "test didn't time out");
runNextTest();
}

View file

@ -1,13 +0,0 @@
"use strict";
add_task(function* () {
gBrowser.pinTab(gBrowser.selectedTab);
let newTab = gBrowser.duplicateTab(gBrowser.selectedTab);
yield promiseTabRestored(newTab);
ok(!newTab.pinned, "duplicating a pinned tab creates unpinned tab");
yield promiseRemoveTab(newTab);
gBrowser.unpinTab(gBrowser.selectedTab);
});

View file

@ -1,35 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var TEST_STATE = { windows: [{ tabs: [{ url: "about:blank" }] }] };
add_task(function* () {
function assertNumberOfTabs(num, msg) {
is(gBrowser.tabs.length, num, msg);
}
function assertNumberOfPinnedTabs(num, msg) {
is(gBrowser._numPinnedTabs, num, msg);
}
// check prerequisites
assertNumberOfTabs(1, "we start off with one tab");
assertNumberOfPinnedTabs(0, "no pinned tabs so far");
// setup
gBrowser.addTab("about:blank");
assertNumberOfTabs(2, "there are two tabs, now");
let [tab1, tab2] = gBrowser.tabs;
let linkedBrowser = tab1.linkedBrowser;
gBrowser.pinTab(tab1);
gBrowser.pinTab(tab2);
assertNumberOfPinnedTabs(2, "both tabs are now pinned");
// run the test
yield promiseBrowserState(TEST_STATE);
assertNumberOfTabs(1, "one tab left after setBrowserState()");
assertNumberOfPinnedTabs(0, "there are no pinned tabs");
is(gBrowser.tabs[0].linkedBrowser, linkedBrowser, "first tab's browser got re-used");
});

View file

@ -1,82 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function* setup() {
/** Test for Bug 625016 - Restore windows closed in succession to quit (non-OSX only) **/
// We'll test this by opening a new window, waiting for the save
// event, then closing that window. We'll observe the
// "sessionstore-state-write-complete" notification and check that
// the state contains no _closedWindows. We'll then add a new tab
// and make sure that the state following that was reset and the
// closed window is now in _closedWindows.
requestLongerTimeout(2);
yield forceSaveState();
// We'll clear all closed windows to make sure our state is clean
// forgetClosedWindow doesn't trigger a delayed save
forgetClosedWindows();
is(ss.getClosedWindowCount(), 0, "starting with no closed windows");
});
add_task(function* new_window() {
let newWin;
try {
newWin = yield promiseNewWindowLoaded();
let tab = newWin.gBrowser.addTab("http://example.com/browser_625016.js?" + Math.random());
yield promiseBrowserLoaded(tab.linkedBrowser);
// Double check that we have no closed windows
is(ss.getClosedWindowCount(), 0, "no closed windows on first save");
yield BrowserTestUtils.closeWindow(newWin);
newWin = null;
let state = JSON.parse((yield promiseRecoveryFileContents()));
is(state.windows.length, 2,
"observe1: 2 windows in data written to disk");
is(state._closedWindows.length, 0,
"observe1: no closed windows in data written to disk");
// The API still treats the closed window as closed, so ensure that window is there
is(ss.getClosedWindowCount(), 1,
"observe1: 1 closed window according to API");
} finally {
if (newWin) {
yield BrowserTestUtils.closeWindow(newWin);
}
yield forceSaveState();
}
});
// We'll open a tab, which should trigger another state save which would wipe
// the _shouldRestore attribute from the closed window
add_task(function* new_tab() {
let newTab;
try {
newTab = gBrowser.addTab("about:mozilla");
let state = JSON.parse((yield promiseRecoveryFileContents()));
is(state.windows.length, 1,
"observe2: 1 window in data being written to disk");
is(state._closedWindows.length, 1,
"observe2: 1 closed window in data being written to disk");
// The API still treats the closed window as closed, so ensure that window is there
is(ss.getClosedWindowCount(), 1,
"observe2: 1 closed window according to API");
} finally {
gBrowser.removeTab(newTab);
}
});
add_task(function* done() {
// The API still represents the closed window as closed, so we can clear it
// with the API, but just to make sure...
// is(ss.getClosedWindowCount(), 1, "1 closed window according to API");
forgetClosedWindows();
Services.prefs.clearUserPref("browser.sessionstore.interval");
});

View file

@ -1,52 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let assertNumberOfTabs = function (num, msg) {
is(gBrowser.tabs.length, num, msg);
}
let assertNumberOfVisibleTabs = function (num, msg) {
is(gBrowser.visibleTabs.length, num, msg);
}
let assertNumberOfPinnedTabs = function (num, msg) {
is(gBrowser._numPinnedTabs, num, msg);
}
waitForExplicitFinish();
// check prerequisites
assertNumberOfTabs(1, "we start off with one tab");
// setup
let tab = gBrowser.addTab("about:mozilla");
whenTabIsLoaded(tab, function () {
// hide the newly created tab
assertNumberOfVisibleTabs(2, "there are two visible tabs");
gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
assertNumberOfVisibleTabs(1, "there is one visible tab");
ok(tab.hidden, "newly created tab is now hidden");
// close and restore hidden tab
promiseRemoveTab(tab).then(() => {
tab = ss.undoCloseTab(window, 0);
// check that everything was restored correctly, clean up and finish
whenTabIsLoaded(tab, function () {
is(tab.linkedBrowser.currentURI.spec, "about:mozilla", "restored tab has correct url");
gBrowser.removeTab(tab);
finish();
});
});
});
}
function whenTabIsLoaded(tab, callback) {
tab.linkedBrowser.addEventListener("load", function onLoad() {
tab.linkedBrowser.removeEventListener("load", onLoad, true);
callback();
}, true);
}

View file

@ -1,55 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This tests that hiding/showing a tab, on its own, eventually triggers a
// session store.
function test() {
waitForExplicitFinish();
// We speed up the interval between session saves to ensure that the test
// runs quickly.
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
// Loading a tab causes a save state and this is meant to catch that event.
waitForSaveState(testBug635418_1);
// Assumption: Only one window is open and it has one tab open.
gBrowser.addTab("about:mozilla");
}
function testBug635418_1() {
ok(!gBrowser.tabs[0].hidden, "first tab should not be hidden");
ok(!gBrowser.tabs[1].hidden, "second tab should not be hidden");
waitForSaveState(testBug635418_2);
// We can't hide the selected tab, so hide the new one
gBrowser.hideTab(gBrowser.tabs[1]);
}
function testBug635418_2() {
let state = JSON.parse(ss.getBrowserState());
ok(!state.windows[0].tabs[0].hidden, "first tab should still not be hidden");
ok(state.windows[0].tabs[1].hidden, "second tab should be hidden by now");
waitForSaveState(testBug635418_3);
gBrowser.showTab(gBrowser.tabs[1]);
}
function testBug635418_3() {
let state = JSON.parse(ss.getBrowserState());
ok(!state.windows[0].tabs[0].hidden, "first tab should still still not be hidden");
ok(!state.windows[0].tabs[1].hidden, "second tab should not be hidden again");
done();
}
function done() {
gBrowser.removeTab(window.gBrowser.tabs[1]);
Services.prefs.clearUserPref("browser.sessionstore.interval");
executeSoon(finish);
}

View file

@ -1,101 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var stateBackup = ss.getBrowserState();
var statePinned = {windows:[{tabs:[
{entries:[{url:"http://example.com#1"}], pinned: true}
]}]};
var state = {windows:[{tabs:[
{entries:[{url:"http://example.com#1"}]},
{entries:[{url:"http://example.com#2"}]},
{entries:[{url:"http://example.com#3"}]},
{entries:[{url:"http://example.com#4"}]},
]}]};
function test() {
waitForExplicitFinish();
registerCleanupFunction(function () {
TabsProgressListener.uninit();
ss.setBrowserState(stateBackup);
});
TabsProgressListener.init();
window.addEventListener("SSWindowStateReady", function onReady() {
window.removeEventListener("SSWindowStateReady", onReady, false);
let firstProgress = true;
TabsProgressListener.setCallback(function (needsRestore, isRestoring) {
if (firstProgress) {
firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently");
} else {
ok(isRestoring <= 3, "restoring max. 2 tabs concurrently");
}
if (0 == needsRestore) {
TabsProgressListener.unsetCallback();
waitForFocus(finish);
}
});
ss.setBrowserState(JSON.stringify(state));
}, false);
ss.setBrowserState(JSON.stringify(statePinned));
}
function countTabs() {
let needsRestore = 0, isRestoring = 0;
let windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let window = windowsEnum.getNext();
if (window.closed)
continue;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
let browser = window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
}
return [needsRestore, isRestoring];
}
var TabsProgressListener = {
init: function () {
Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false);
},
uninit: function () {
Services.obs.removeObserver(this, "sessionstore-debug-tab-restored");
this.unsetCallback();
},
setCallback: function (callback) {
this.callback = callback;
},
unsetCallback: function () {
delete this.callback;
},
observe: function (browser, topic, data) {
TabsProgressListener.onRestored(browser);
},
onRestored: function (browser) {
if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING) {
this.callback.apply(null, countTabs());
}
}
}

View file

@ -1,66 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URL = "http://mochi.test:8888/browser/browser/components/" +
"sessionstore/test/browser_637020_slow.sjs";
const TEST_STATE = {
windows: [{
tabs: [
{ entries: [{ url: "about:mozilla" }] },
{ entries: [{ url: "about:robots" }] }
]
}, {
tabs: [
{ entries: [{ url: TEST_URL }] },
{ entries: [{ url: TEST_URL }] }
]
}]
};
/**
* This test ensures that windows that have just been restored will be marked
* as dirty, otherwise _getCurrentState() might ignore them when collecting
* state for the first time and we'd just save them as empty objects.
*
* The dirty state acts as a cache to not collect data from all windows all the
* time, so at the beginning, each window must be dirty so that we collect
* their state at least once.
*/
add_task(function* test() {
// Wait until the new window has been opened.
let promiseWindow = new Promise(resolve => {
Services.obs.addObserver(function onOpened(subject) {
Services.obs.removeObserver(onOpened, "domwindowopened");
resolve(subject);
}, "domwindowopened", false);
});
// Set the new browser state that will
// restore a window with two slowly loading tabs.
let backupState = SessionStore.getBrowserState();
SessionStore.setBrowserState(JSON.stringify(TEST_STATE));
let win = yield promiseWindow;
// The window has now been opened. Check the state that is returned,
// this should come from the cache while the window isn't restored, yet.
info("the window has been opened");
checkWindows();
// The history has now been restored and the tabs are loading. The data must
// now come from the window, if it's correctly been marked as dirty before.
yield new Promise(resolve => whenDelayedStartupFinished(win, resolve));
info("the delayed startup has finished");
checkWindows();
// Cleanup.
yield BrowserTestUtils.closeWindow(win);
yield promiseBrowserState(backupState);
});
function checkWindows() {
let state = JSON.parse(SessionStore.getBrowserState());
is(state.windows[0].tabs.length, 2, "first window has two tabs");
is(state.windows[1].tabs.length, 2, "second window has two tabs");
}

View file

@ -1,21 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const Cc = Components.classes;
const Ci = Components.interfaces;
const DELAY_MS = "2000";
let timer;
function handleRequest(req, resp) {
resp.processAsync();
resp.setHeader("Cache-Control", "no-cache", false);
resp.setHeader("Content-Type", "text/html;charset=utf-8", false);
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(() => {
resp.write("hi");
resp.finish();
}, DELAY_MS, Ci.nsITimer.TYPE_ONE_SHOT);
}

View file

@ -1,68 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const testState = {
windows: [{
tabs: [
{ entries: [{ url: "about:blank" }] },
]
}],
scratchpads: [
{ text: "text1", executionContext: 1 },
{ text: "", executionContext: 2, filename: "test.js" }
]
};
// only finish() when correct number of windows opened
var restored = [];
function addState(state) {
restored.push(state);
if (restored.length == testState.scratchpads.length) {
ok(statesMatch(restored, testState.scratchpads),
"Two scratchpad windows restored");
Services.ww.unregisterNotification(windowObserver);
finish();
}
}
function test() {
waitForExplicitFinish();
Services.ww.registerNotification(windowObserver);
ss.setBrowserState(JSON.stringify(testState));
}
function windowObserver(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
if (win.Scratchpad) {
win.Scratchpad.addObserver({
onReady: function() {
win.Scratchpad.removeObserver(this);
let state = win.Scratchpad.getState();
BrowserTestUtils.closeWindow(win).then(() => {
addState(state);
});
},
});
}
}, false);
}
}
function statesMatch(restored, states) {
return states.every(function(state) {
return restored.some(function(restoredState) {
return state.filename == restoredState.filename &&
state.text == restoredState.text &&
state.executionContext == restoredState.executionContext;
})
});
}

View file

@ -1,22 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const NOTIFICATION = "sessionstore-browser-state-restored";
function test() {
waitForExplicitFinish();
function observe(subject, topic, data) {
if (NOTIFICATION == topic) {
finish();
ok(true, "TOPIC received");
}
}
Services.obs.addObserver(observe, NOTIFICATION, false);
registerCleanupFunction(function () {
Services.obs.removeObserver(observe, NOTIFICATION);
});
ss.setBrowserState(JSON.stringify({ windows: [] }));
}

View file

@ -1,33 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
let eventReceived = false;
registerCleanupFunction(function () {
ok(eventReceived, "SSWindowClosing event received");
});
newWindow(function (win) {
win.addEventListener("SSWindowClosing", function onWindowClosing() {
win.removeEventListener("SSWindowClosing", onWindowClosing, false);
eventReceived = true;
}, false);
BrowserTestUtils.closeWindow(win).then(() => {
waitForFocus(finish);
});
});
}
function newWindow(callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(() => callback(win));
}, false);
}

Some files were not shown because too many files have changed in this diff Show more