56 const Cc = Components.classes;
57 const Ci = Components.interfaces;
58 const Cr = Components.results;
59 const Cu = Components.utils;
77 "domwindowopened",
"domwindowclosed",
78 "quit-application-requested",
"quit-application-granted",
79 "browser-lastwindow-close-granted",
80 "quit-application",
"browser:purge-session-history",
81 "private-browsing",
"browser:purge-domain-data",
82 "private-browsing-change-granted"
96 "menubar",
"toolbar",
"locationbar",
97 "personalbar",
"statusbar",
"scrollbars"
109 "Subframes",
"Plugins",
"Javascript",
"MetaRedirects",
"Images",
110 "DNSPrefetch",
"Auth"
114 #define BROKEN_WM_Z_ORDER
117 Cu.import(
"resource://gre/modules/XPCOMUtils.jsm");
120 aMsg = (
"SessionStore: " + aMsg).replace(/\S{80}/g,
"$&\n");
121 Cc[
"@mozilla.org/consoleservice;1"].getService(
Ci.nsIConsoleService)
122 .logStringMessage(aMsg);
127 Cu.import(
"resource://gre/modules/NetUtil.jsm");
138 contractID:
"@mozilla.org/browser/sessionstore;1",
139 classID: Components.ID(
"{5280606b-2510-4fe0-97ef-9b5a22eafe6b}"),
141 Ci.nsIDOMEventListener,
143 Ci.nsISupportsWeakReference]),
147 xulAttributes: [
"image"],
156 _resume_from_crash:
true,
163 _browserSetState:
false,
184 _inPrivateBrowsing:
false,
187 _clearingOnShutdown:
false,
194 _restoreLastWindow:
false,
202 init:
function sss_init(aWindow) {
206 if (aWindow && (!aWindow.__SSi || !
this._windows[aWindow.__SSi]))
215 this._observerService =
Cc[
"@mozilla.org/observer-service;1"].
219 this._observerService.addObserver(
this, aTopic,
true);
222 var pbs =
Cc[
"@mozilla.org/privatebrowsing;1"].
224 this._inPrivateBrowsing = pbs.privateBrowsingEnabled;
227 this._interval = this.
_prefBranch.getIntPref(
"sessionstore.interval");
228 this.
_prefBranch.addObserver(
"sessionstore.interval",
this,
true);
231 this._resume_from_crash = this.
_prefBranch.getBoolPref(
"sessionstore.resume_from_crash");
232 this.
_prefBranch.addObserver(
"sessionstore.resume_from_crash",
this,
true);
235 this.
_prefBranch.addObserver(
"sessionstore.max_tabs_undo",
this,
true);
236 this.
_prefBranch.addObserver(
"sessionstore.max_windows_undo",
this,
true);
239 this._sessionhistory_max_entries =
240 this.
_prefBranch.getIntPref(
"sessionhistory.max_entries");
243 var dirService =
Cc[
"@mozilla.org/file/directory_service;1"].
245 this._sessionFile = dirService.get(
"ProfD",
Ci.nsILocalFile);
246 this._sessionFileBackup = this._sessionFile.clone();
247 this._sessionFile.append(
"sessionstore.js");
248 this._sessionFileBackup.append(
"sessionstore.bak");
253 var ss =
Cc[
"@mozilla.org/browser/sessionstartup;1"].
256 iniString = ss.state;
258 catch(ex) { dump(ex +
"\n"); }
263 this._initialState = this._safeEval(
"(" + iniString +
")");
265 let lastSessionCrashed =
266 this._initialState.session && this._initialState.session.state &&
268 if (lastSessionCrashed) {
269 this._recentCrashes = (this._initialState.session &&
270 this._initialState.session.recentCrashes || 0) + 1;
272 if (this._needsRestorePage(this._initialState, this._recentCrashes)) {
275 url:
"about:sessionrestore",
276 formdata: {
"#sessionData": iniString }
278 this._initialState = {
windows: [{
tabs: [{ entries: [pageData] }] }] };
283 delete this._initialState.windows[0].hidden;
285 delete this._initialState.windows[0].isPopup;
287 catch (ex) {
debug(
"The session file is invalid: " + ex); }
291 if (!this._resume_from_crash)
295 if (this._sessionFileBackup.exists())
296 this._sessionFileBackup.remove(
false);
297 if (this._sessionFile.exists())
298 this._sessionFile.copyTo(
null,
this._sessionFileBackup.leafName);
300 catch (ex) {
Cu.reportError(ex); }
306 this.
_prefBranch.getBoolPref(
"sessionstore.resume_session_once"))
307 this.
_prefBranch.setBoolPref(
"sessionstore.resume_session_once",
false);
317 _uninit:
function sss_uninit() {
318 if (this._doResumeSession()) {
325 if (this._saveTimer) {
326 this._saveTimer.cancel();
327 this._saveTimer =
null;
334 observe:
function sss_observe(aSubject, aTopic,
aData) {
339 case "domwindowopened":
340 aSubject.addEventListener(
"load",
function(aEvent) {
341 aEvent.currentTarget.removeEventListener(
"load",
arguments.callee,
false);
342 _this.onLoad(aEvent.currentTarget);
345 case "domwindowclosed":
346 if (this._closingWindows.length > 0) {
347 let index = this._closingWindows.indexOf(aSubject);
349 this._closingWindows.splice(index, 1);
350 if (this._closingWindows.length == 0)
356 case "quit-application-requested":
358 this._forEachBrowserWindow(
function(aWindow) {
359 this._collectWindowData(aWindow);
363 case "quit-application-granted":
368 case "browser-lastwindow-close-granted":
373 this._restoreLastWindow =
true;
376 case "quit-application":
377 if (
aData ==
"restart") {
378 this.
_prefBranch.setBoolPref(
"sessionstore.resume_session_once",
true);
379 this._clearingOnShutdown =
false;
384 case "browser:purge-session-history":
385 let openWindows = {};
386 this._forEachBrowserWindow(
function(aWindow) {
387 Array.forEach(aWindow.gBrowser.browsers,
function(
aBrowser) {
390 openWindows[aWindow.__SSi] =
true;
394 if (
ix in openWindows)
395 this._windows[
ix]._closedTabs = [];
397 delete this._windows[
ix];
400 this._closedWindows = [];
403 var
win = this._getMostRecentBrowserWindow();
405 win.setTimeout(
function() { _this.saveState(
true); }, 0);
409 if (
"_stateBackup" in
this)
410 delete this._stateBackup;
412 this._clearingOnShutdown =
true;
414 case "browser:purge-domain-data":
416 function containsDomain(aEntry) {
418 if (this._getURIFromString(aEntry.url).host.hasRootDomain(
aData))
422 return aEntry.children && aEntry.children.some(containsDomain,
this);
425 for (let
ix in this._windows) {
426 let closedTabs = this._windows[
ix]._closedTabs;
427 for (let
i = closedTabs.length - 1;
i >= 0;
i--) {
428 if (closedTabs[
i].state.entries.some(containsDomain,
this))
429 closedTabs.splice(
i, 1);
434 for (let
ix = this._closedWindows.length - 1;
ix >= 0;
ix--) {
435 let closedTabs = this._closedWindows[
ix]._closedTabs;
436 let openTabs = this._closedWindows[
ix].tabs;
438 for (let
i = closedTabs.length - 1;
i >= 0;
i--)
439 if (closedTabs[
i].state.entries.some(containsDomain,
this))
440 closedTabs.splice(
i, 1);
441 for (let j = openTabs.length - 1; j >= 0; j--) {
442 if (openTabs[j].entries.some(containsDomain,
this)) {
443 openTabs.splice(j, 1);
444 if (this._closedWindows[
ix].selected > j)
445 this._closedWindows[
ix].selected--;
448 if (openTabs.length == 0) {
449 this._closedWindows.splice(
ix, 1);
451 else if (openTabs.length != openTabCount) {
453 let selectedTab = openTabs[this._closedWindows[
ix].selected - 1];
455 let
activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
456 if (activeIndex >= selectedTab.entries.length)
457 activeIndex = selectedTab.entries.length - 1;
458 this._closedWindows[
ix].title = selectedTab.entries[
activeIndex].title;
464 case "nsPref:changed":
468 case "sessionstore.max_tabs_undo":
469 for (let
ix in this._windows) {
470 this._windows[
ix]._closedTabs.splice(this.
_prefBranch.getIntPref(
"sessionstore.max_tabs_undo"));
473 case "sessionstore.max_windows_undo":
474 this._capClosedWindows();
476 case "sessionstore.interval":
477 this._interval = this.
_prefBranch.getIntPref(
"sessionstore.interval");
479 if (this._saveTimer) {
480 this._saveTimer.cancel();
481 this._saveTimer =
null;
483 this.saveStateDelayed(
null, -1);
485 case "sessionstore.resume_from_crash":
486 this._resume_from_crash = this.
_prefBranch.getBoolPref(
"sessionstore.resume_from_crash");
489 if (this._resume_from_crash)
496 case "timer-callback":
497 this._saveTimer =
null;
500 case "private-browsing":
503 this._inPrivateBrowsing =
true;
506 aSubject.QueryInterface(
Ci.nsISupportsPRBool);
507 let quitting = aSubject.data;
511 if (
"_stateBackup" in
this) {
512 var
oState = this._stateBackup;
518 this.
_prefBranch.setBoolPref(
"sessionstore.resume_session_once",
true);
521 this._inPrivateBrowsing =
false;
522 delete this._stateBackup;
526 case "private-browsing-change-granted":
527 if (
aData ==
"enter") {
529 this._stateBackup = this._safeEval(this._getCurrentState(
true).toSource());
540 handleEvent:
function sss_handleEvent(aEvent) {
541 var
win = aEvent.currentTarget.ownerDocument.defaultView;
542 switch (aEvent.type) {
545 this.onTabLoad(win, aEvent.currentTarget, aEvent);
549 case "DOMAutoComplete":
550 this.onTabInput(win, aEvent.currentTarget);
553 this.onTabScroll(win);
557 let
browser = aEvent.originalTarget.linkedBrowser;
558 if (aEvent.type ==
"TabOpen") {
559 this.onTabAdd(win, browser);
565 this.onTabRemove(win, browser);
569 this.onTabSelect(win);
583 onLoad:
function sss_onLoad(aWindow) {
585 if (aWindow && aWindow.__SSi &&
this._windows[aWindow.__SSi])
589 if (aWindow.document.documentElement.getAttribute(
"windowtype") !=
"navigator:browser" ||
594 aWindow.__SSi =
"window" + Date.now();
597 this.
_windows[aWindow.__SSi] = {
tabs: [], selected: 0, _closedTabs: [] };
598 if (!aWindow.toolbar.visible)
599 this.
_windows[aWindow.__SSi].isPopup =
true;
607 if (this._initialState) {
609 this._initialState._firstTabs =
true;
610 this._restoreCount = this._initialState.windows ? this._initialState.windows.length : 0;
611 this.restoreWindow(aWindow, this._initialState, this._isCmdLineEmpty(aWindow));
612 delete this._initialState;
627 else if (!this._isWindowLoaded(aWindow)) {
628 let followUp = this.
_statesToRestore[aWindow.__SS_restoreID].windows.length == 1;
629 this.restoreWindow(aWindow, this.
_statesToRestore[aWindow.__SS_restoreID],
true, followUp);
632 else if (this._restoreLastWindow && aWindow.toolbar.visible &&
633 this._closedWindows.length &&
this._doResumeSession() &&
634 !this._inPrivateBrowsing) {
639 this._closedWindows = this._closedWindows.filter(
function(aWinState) {
640 if (!state && !aWinState.isPopup) {
649 this._restoreCount = 1;
650 this.restoreWindow(aWindow, state, this._isCmdLineEmpty(aWindow));
653 this.
_prefBranch.setBoolPref(
"sessionstore.resume_session_once",
false);
655 if (this._restoreLastWindow && aWindow.toolbar.visible) {
659 this._restoreLastWindow =
false;
666 for (let
i = 0;
i < tabbrowser.browsers.length;
i++) {
667 this.onTabAdd(aWindow, tabbrowser.browsers[
i],
true);
670 tabbrowser.addEventListener(
"TabOpen",
this,
true);
671 tabbrowser.addEventListener(
"TabClose",
this,
true);
672 tabbrowser.addEventListener(
"TabSelect",
this,
true);
682 onClose:
function sss_onClose(aWindow) {
684 let isFullyLoaded = this._isWindowLoaded(aWindow);
685 if (!isFullyLoaded) {
687 aWindow.__SSi =
"window" + Date.now();
690 delete aWindow.__SS_restoreID;
694 if (!aWindow.__SSi || !
this._windows[aWindow.__SSi]) {
698 if (this.windowToFocus && this.windowToFocus == aWindow) {
699 delete this.windowToFocus;
702 var tabbrowser = aWindow.gBrowser;
704 tabbrowser.removeEventListener(
"TabOpen",
this,
true);
705 tabbrowser.removeEventListener(
"TabClose",
this,
true);
706 tabbrowser.removeEventListener(
"TabSelect",
this,
true);
711 this._collectWindowData(aWindow);
714 winData.title = aWindow.content.document.title || tabbrowser.selectedTab.label;
715 winData.title = this._replaceLoadingTitle(winData.title, tabbrowser,
716 tabbrowser.selectedTab);
721 if (winData.tabs.length > 1 ||
722 (winData.tabs.length == 1 && winData.tabs[0].entries.length > 0)) {
723 this._closedWindows.unshift(winData);
724 this._capClosedWindows();
728 delete this.
_windows[aWindow.__SSi];
731 this.saveStateDelayed();
734 for (let
i = 0;
i < tabbrowser.browsers.length;
i++) {
735 this.onTabRemove(aWindow, tabbrowser.browsers[
i],
true);
739 aWindow.__SS_dyingCache =
winData;
741 delete aWindow.__SSi;
753 onTabAdd:
function sss_onTabAdd(aWindow,
aBrowser, aNoNotification) {
754 aBrowser.addEventListener(
"load",
this,
true);
755 aBrowser.addEventListener(
"pageshow",
this,
true);
756 aBrowser.addEventListener(
"change",
this,
true);
757 aBrowser.addEventListener(
"input",
this,
true);
758 aBrowser.addEventListener(
"DOMAutoComplete",
this,
true);
759 aBrowser.addEventListener(
"scroll",
this,
true);
761 if (!aNoNotification) {
762 this.saveStateDelayed(aWindow);
765 this._updateCrashReportURL(aWindow);
777 onTabRemove:
function sss_onTabRemove(aWindow,
aBrowser, aNoNotification) {
778 aBrowser.removeEventListener(
"load",
this,
true);
779 aBrowser.removeEventListener(
"pageshow",
this,
true);
780 aBrowser.removeEventListener(
"change",
this,
true);
781 aBrowser.removeEventListener(
"input",
this,
true);
782 aBrowser.removeEventListener(
"DOMAutoComplete",
this,
true);
783 aBrowser.removeEventListener(
"scroll",
this,
true);
787 if (!aNoNotification) {
788 this.saveStateDelayed(aWindow);
802 var
event = aWindow.document.createEvent(
"Events");
803 event.initEvent(
"SSTabClosing",
true,
false);
806 var maxTabsUndo = this.
_prefBranch.getIntPref(
"sessionstore.max_tabs_undo");
808 if (maxTabsUndo == 0) {
813 var tabState = this._collectTabData(
aTab);
814 this._updateTextAndScrollDataForTab(aWindow,
aTab.linkedBrowser, tabState);
817 if (tabState.entries.length > 0) {
818 let tabTitle =
aTab.label;
819 let tabbrowser = aWindow.gBrowser;
820 tabTitle = this._replaceLoadingTitle(tabTitle, tabbrowser,
aTab);
822 this.
_windows[aWindow.__SSi]._closedTabs.unshift({
825 image:
aTab.getAttribute(
"image"),
828 var length = this.
_windows[aWindow.__SSi]._closedTabs.length;
829 if (length > maxTabsUndo)
830 this.
_windows[aWindow.__SSi]._closedTabs.splice(maxTabsUndo, length - maxTabsUndo);
843 onTabLoad:
function sss_onTabLoad(aWindow,
aBrowser, aEvent) {
846 if (aEvent.type !=
"load" && !aEvent.persisted) {
851 this.saveStateDelayed(aWindow);
854 this._updateCrashReportURL(aWindow);
864 onTabInput:
function sss_onTabInput(aWindow,
aBrowser) {
866 delete aBrowser.__SS_data._formDataSaved;
868 this.saveStateDelayed(aWindow, 3000);
876 onTabScroll:
function sss_onTabScroll(aWindow) {
877 this.saveStateDelayed(aWindow, 3000);
885 onTabSelect:
function sss_onTabSelect(aWindow) {
887 this.
_windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex;
888 this.saveStateDelayed(aWindow);
891 this._updateCrashReportURL(aWindow);
897 getBrowserState:
function sss_getBrowserState() {
898 return this._toJSONString(this._getCurrentState());
901 setBrowserState:
function sss_setBrowserState(
aState) {
903 var state = this._safeEval(
"(" +
aState +
")");
906 if (!state || !state.windows)
907 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
909 this._browserSetState =
true;
911 var
window = this._getMostRecentBrowserWindow();
913 this._restoreCount = 1;
914 this._openWindowWithState(state);
919 this._closedWindows = [];
922 this._restoreCount = state.windows ? state.windows.length : 0;
926 this._forEachBrowserWindow(
function(aWindow) {
927 if (aWindow != window) {
928 self._closingWindows.push(aWindow);
934 this.restoreWindow(window, state,
true);
937 getWindowState:
function sss_getWindowState(aWindow) {
938 if (!aWindow.__SSi && !aWindow.__SS_dyingCache)
939 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
942 return this._toJSONString({
windows: [aWindow.__SS_dyingCache] });
943 return this._toJSONString(this._getWindowState(aWindow));
946 setWindowState:
function sss_setWindowState(aWindow,
aState, aOverwrite) {
948 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
950 this.restoreWindow(aWindow,
"(" +
aState +
")", aOverwrite);
953 getTabState:
function sss_getTabState(
aTab) {
954 if (!
aTab.ownerDocument || !
aTab.ownerDocument.defaultView.__SSi)
955 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
957 var tabState = this._collectTabData(
aTab);
959 var window =
aTab.ownerDocument.defaultView;
960 this._updateTextAndScrollDataForTab(window,
aTab.linkedBrowser, tabState);
962 return this._toJSONString(tabState);
965 setTabState:
function sss_setTabState(
aTab,
aState) {
966 var tabState = this._safeEval(
"(" +
aState +
")");
967 if (!tabState.entries || !
aTab.ownerDocument || !
aTab.ownerDocument.defaultView.__SSi)
968 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
970 var window =
aTab.ownerDocument.defaultView;
974 duplicateTab:
function sss_duplicateTab(aWindow,
aTab) {
975 if (!
aTab.ownerDocument || !
aTab.ownerDocument.defaultView.__SSi ||
977 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
979 var tabState = this._collectTabData(
aTab,
true);
980 var sourceWindow =
aTab.ownerDocument.defaultView;
981 this._updateTextAndScrollDataForTab(sourceWindow,
aTab.linkedBrowser, tabState,
true);
983 var newTab = aWindow.getBrowser().addTab();
989 getClosedTabCount:
function sss_getClosedTabCount(aWindow) {
990 if (!aWindow.__SSi && aWindow.__SS_dyingCache)
991 return aWindow.__SS_dyingCache._closedTabs.length;
996 return this.
_windows[aWindow.__SSi]._closedTabs.length;
999 getClosedTabData:
function sss_getClosedTabDataAt(aWindow) {
1000 if (!aWindow.__SSi && !aWindow.__SS_dyingCache)
1001 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1004 return this._toJSONString(aWindow.__SS_dyingCache._closedTabs);
1005 return this._toJSONString(this.
_windows[aWindow.__SSi]._closedTabs);
1008 undoCloseTab:
function sss_undoCloseTab(aWindow, aIndex) {
1010 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1012 var closedTabs = this.
_windows[aWindow.__SSi]._closedTabs;
1015 aIndex = aIndex || 0;
1016 if (!(aIndex in closedTabs))
1017 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1020 let closedTab = closedTabs.splice(aIndex, 1).shift();
1021 let closedTabState = closedTab.state;
1024 let browser = aWindow.gBrowser;
1025 let
tab = browser.addTab();
1028 browser.moveTabTo(tab, closedTab.pos);
1034 let content = browser.getBrowserForTab(tab).contentWindow;
1035 aWindow.setTimeout(
function() { content.focus(); }, 0);
1040 forgetClosedTab:
function sss_forgetClosedTab(aWindow, aIndex) {
1042 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1044 var closedTabs = this.
_windows[aWindow.__SSi]._closedTabs;
1047 aIndex = aIndex || 0;
1048 if (!(aIndex in closedTabs))
1049 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1052 closedTabs.splice(aIndex, 1);
1055 getClosedWindowCount:
function sss_getClosedWindowCount() {
1056 return this._closedWindows.length;
1059 getClosedWindowData:
function sss_getClosedWindowData() {
1060 return this._toJSONString(this._closedWindows);
1064 if (!(aIndex in this._closedWindows))
1065 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1068 let state = {
windows: this._closedWindows.splice(aIndex, 1) };
1069 let window = this._openWindowWithState(state);
1070 this.windowToFocus =
window;
1074 forgetClosedWindow:
function sss_forgetClosedWindow(aIndex) {
1076 aIndex = aIndex || 0;
1077 if (!(aIndex in this._closedWindows))
1078 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1081 this._closedWindows.splice(aIndex, 1);
1084 getWindowValue:
function sss_getWindowValue(aWindow, aKey) {
1085 if (aWindow.__SSi) {
1087 return data[aKey] ||
"";
1089 if (aWindow.__SS_dyingCache) {
1090 data = aWindow.__SS_dyingCache.extData || {};
1091 return data[aKey] ||
"";
1093 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1096 setWindowValue:
function sss_setWindowValue(aWindow, aKey, aStringValue) {
1097 if (aWindow.__SSi) {
1098 if (!this.
_windows[aWindow.__SSi].extData) {
1099 this.
_windows[aWindow.__SSi].extData = {};
1101 this.
_windows[aWindow.__SSi].extData[aKey] = aStringValue;
1102 this.saveStateDelayed(aWindow);
1105 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1109 deleteWindowValue:
function sss_deleteWindowValue(aWindow, aKey) {
1110 if (aWindow.__SSi &&
this._windows[aWindow.__SSi].extData &&
1111 this._windows[aWindow.__SSi].extData[aKey])
1112 delete this.
_windows[aWindow.__SSi].extData[aKey];
1114 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1117 getTabValue:
function sss_getTabValue(
aTab, aKey) {
1118 var
data =
aTab.__SS_extdata || {};
1119 return data[aKey] ||
"";
1122 setTabValue:
function sss_setTabValue(
aTab, aKey, aStringValue) {
1123 if (!
aTab.__SS_extdata) {
1124 aTab.__SS_extdata = {};
1126 aTab.__SS_extdata[aKey] = aStringValue;
1127 this.saveStateDelayed(
aTab.ownerDocument.defaultView);
1130 deleteTabValue:
function sss_deleteTabValue(
aTab, aKey) {
1131 if (
aTab.__SS_extdata &&
aTab.__SS_extdata[aKey])
1132 delete aTab.__SS_extdata[aKey];
1134 throw (Components.returnCode =
Cr.NS_ERROR_INVALID_ARG);
1137 persistTabAttribute:
function sss_persistTabAttribute(
aName) {
1138 if (this.xulAttributes.indexOf(
aName) != -1)
1141 this.xulAttributes.push(
aName);
1142 this.saveStateDelayed();
1153 var tabbrowser = aWindow.getBrowser();
1154 var
tabs = tabbrowser.mTabs;
1155 var tabsData = this.
_windows[aWindow.__SSi].tabs = [];
1157 for (var
i = 0;
i < tabs.length;
i++)
1158 tabsData.push(
this._collectTabData(tabs[
i]));
1160 this.
_windows[aWindow.__SSi].selected = tabbrowser.mTabBox.selectedIndex + 1;
1171 _collectTabData:
function sss_collectTabData(
aTab,
aFullData) {
1172 var
tabData = { entries: [] };
1173 var browser =
aTab.linkedBrowser;
1175 if (!browser || !browser.currentURI)
1178 else if (browser.__SS_data && browser.__SS_data._tabStillLoading)
1180 return browser.__SS_data;
1184 history = browser.sessionHistory;
1190 if (history && browser.__SS_data &&
1191 browser.__SS_data.entries[history.index] &&
1192 history.index <
this._sessionhistory_max_entries - 1 && !
aFullData) {
1193 tabData = browser.__SS_data;
1194 tabData.index = history.index + 1;
1196 else if (history && history.count > 0) {
1197 for (var j = 0; j < history.count; j++)
1198 tabData.entries.push(
this._serializeHistoryEntry(history.getEntryAtIndex(j,
false),
1200 tabData.index = history.index + 1;
1206 else if (browser.currentURI.spec !=
"about:blank" ||
1207 browser.contentDocument.body.hasChildNodes()) {
1208 tabData.entries[0] = {
url: browser.currentURI.spec };
1216 if (browser.userTypedValue) {
1217 tabData.userTypedValue = browser.userTypedValue;
1218 tabData.userTypedClear = browser.userTypedClear;
1225 if (disallow.length > 0)
1226 tabData.disallow = disallow.join(
",");
1227 else if (tabData.disallow)
1228 delete tabData.disallow;
1230 if (this.xulAttributes.length > 0) {
1231 tabData.attributes = {};
1232 Array.forEach(
aTab.attributes,
function(aAttr) {
1233 if (this.xulAttributes.indexOf(aAttr.name) > -1)
1234 tabData.attributes[aAttr.name] = aAttr.value;
1238 if (
aTab.__SS_extdata)
1239 tabData.extData =
aTab.__SS_extdata;
1240 else if (tabData.extData)
1241 delete tabData.extData;
1243 if (history && browser.docShell instanceof
Ci.nsIDocShell)
1258 _serializeHistoryEntry:
function sss_serializeHistoryEntry(aEntry,
aFullData) {
1259 var
entry = {
url: aEntry.URI.spec };
1261 if (aEntry.title && aEntry.title != entry.url) {
1262 entry.title = aEntry.title;
1264 if (aEntry.isSubFrame) {
1265 entry.subframe =
true;
1267 if (!(aEntry instanceof
Ci.nsISHEntry)) {
1271 var cacheKey = aEntry.cacheKey;
1272 if (cacheKey && cacheKey instanceof
Ci.nsISupportsPRUint32 &&
1273 cacheKey.data != 0) {
1276 entry.cacheKey = cacheKey.data;
1278 entry.ID = aEntry.ID;
1280 if (aEntry.referrerURI)
1281 entry.referrer = aEntry.referrerURI.spec;
1283 if (aEntry.contentType)
1284 entry.contentType = aEntry.contentType;
1287 aEntry.getScrollPosition(x,
y);
1288 if (x.value != 0 ||
y.value != 0)
1289 entry.scroll = x.value +
"," +
y.value;
1292 var prefPostdata = this.
_prefBranch.getIntPref(
"sessionstore.postdata");
1294 prefPostdata &&
this._checkPrivacyLevel(aEntry.URI.schemeIs(
"https")))) {
1295 aEntry.postData.QueryInterface(
Ci.nsISeekableStream).
1296 seek(
Ci.nsISeekableStream.NS_SEEK_SET, 0);
1297 var stream =
Cc[
"@mozilla.org/binaryinputstream;1"].
1299 stream.setInputStream(aEntry.postData);
1300 var postBytes = stream.readByteArray(stream.available());
1303 postdata.replace(/^(Content-.*\r\n)+(\r\n)*/,
"").length <=
1308 entry.postdata_b64 = btoa(postdata);
1312 catch (ex) {
debug(ex); }
1318 var binaryStream =
Cc[
"@mozilla.org/binaryoutputstream;1"].
1320 var pipe =
Cc[
"@mozilla.org/pipe;1"].createInstance(
Ci.nsIPipe);
1321 pipe.init(
false,
false, 0, 0xffffffff,
null);
1322 binaryStream.setOutputStream(pipe.outputStream);
1323 binaryStream.writeCompoundObject(aEntry.owner,
Ci.nsISupports,
true);
1324 binaryStream.close();
1327 var scriptableStream =
Cc[
"@mozilla.org/binaryinputstream;1"].
1329 scriptableStream.setInputStream(pipe.inputStream);
1331 scriptableStream.readByteArray(scriptableStream.available());
1335 entry.owner_b64 = btoa(
String.fromCharCode.apply(
null, ownerBytes));
1337 catch (ex) {
debug(ex); }
1340 if (!(aEntry instanceof
Ci.nsISHContainer)) {
1344 if (aEntry.childCount > 0) {
1345 entry.children = [];
1346 for (var i = 0; i < aEntry.childCount; i++) {
1347 var child = aEntry.GetChildAt(i);
1349 entry.children.push(this._serializeHistoryEntry(child,
aFullData));
1352 entry.children.push({
url:
"about:blank" });
1356 delete entry.children;
1378 let storageData = {};
1384 let domain = uri.spec;
1387 domain = uri.prePath;
1390 if (storageData[domain] || !(
aFullData || this._checkPrivacyLevel(uri.schemeIs(
"https"))))
1393 let storage, storageItemCount = 0;
1395 var principal =
Cc[
"@mozilla.org/scriptsecuritymanager;1"].
1397 getCodebasePrincipal(uri);
1404 storage =
aDocShell.getSessionStorageForPrincipal(principal,
false);
1406 storageItemCount = storage.length;
1409 if (storageItemCount == 0)
1412 let
data = storageData[domain] = {};
1413 for (let j = 0; j < storageItemCount; j++) {
1415 let
key = storage.key(j);
1416 let item = storage.getItem(key);
1435 var browsers = aWindow.getBrowser().browsers;
1436 for (var i = 0; i < browsers.length; i++) {
1438 var tabData = this.
_windows[aWindow.__SSi].tabs[
i];
1439 if (browsers[i].__SS_data &&
1440 browsers[i].__SS_data._tabStillLoading)
1442 this._updateTextAndScrollDataForTab(aWindow, browsers[i], tabData);
1444 catch (ex) {
debug(ex); }
1460 _updateTextAndScrollDataForTab:
1468 this._getSelectedPageStyle(
aBrowser.contentWindow);
1469 if (selectedPageStyle)
1478 if (
aBrowser.currentURI.spec ==
"about:config")
1480 "#textbox":
aBrowser.contentDocument.getElementById(
"textbox").wrappedJSObject.value
1499 function sss_updateTextAndScrollDataForFrame(aWindow,
aContent,
aData,
1501 for (var i = 0; i <
aContent.frames.length; i++) {
1507 document.location.href).schemeIs(
"https");
1509 aContent.top.document.location.href ==
"about:sessionrestore") {
1511 let formData = this._collectFormDataForFrame(
aContent.document);
1513 aData.formdata = formData;
1514 else if (
aData.formdata)
1515 delete aData.formdata;
1519 if ((
aContent.document.designMode ||
"") ==
"on") {
1523 aContent.addEventListener(
"keypress",
function(aEvent) {
1524 _this.saveStateDelayed(aWindow, 3000);
1534 .getInterface(
Ci.nsIDOMWindowUtils);
1536 domWindowUtils.getScrollXY(
false, scrollX,
scrollY);
1546 _getSelectedPageStyle:
function sss_getSelectedPageStyle(
aContent) {
1547 const forScreen = /(?:^|,)\s*(?:all|screen)\s*(?:,|$)/i;
1548 for (let i = 0; i <
aContent.document.styleSheets.length; i++) {
1549 let ss =
aContent.document.styleSheets[
i];
1550 let media = ss.media.mediaText;
1551 if (!ss.disabled && ss.title && (!media || forScreen.test(media)))
1554 for (let i = 0; i <
aContent.frames.length; i++) {
1555 let selectedPageStyle = this._getSelectedPageStyle(
aContent.frames[i]);
1556 if (selectedPageStyle)
1567 _collectFormDataForFrame:
function sss_collectFormDataForFrame(
aDocument) {
1570 Ci.nsIDOMXPathResult.UNORDERED_NODE_ITERATOR_TYPE,
null);
1571 let
node = formNodes.iterateNext();
1585 if (node instanceof
Ci.nsIDOMHTMLInputElement) {
1586 if (node.type !=
"file")
1587 data[
id] = node.type ==
"checkbox" || node.type ==
"radio" ? node.checked : node.value;
1589 data[
id] = { type:
"file", fileList: node.mozGetFileNameArray({}) };
1591 else if (node instanceof
Ci.nsIDOMHTMLTextAreaElement)
1592 data[
id] = node.value;
1593 else if (!node.multiple)
1594 data[
id] = node.selectedIndex;
1597 data[
id] = options.filter(
function(
aIx)
aIx >= 0);
1599 }
while ((node = formNodes.iterateNext()));
1610 var hosts = this.
_windows[aWindow.__SSi]._hosts = {};
1614 if (/^https?:\/\/(?:[^@\/\s]+@)?([\w.-]+)/.test(aEntry.url)) {
1615 if (!hosts[RegExp.$1] &&
_this._checkPrivacyLevel(
_this._getURIFromString(aEntry.url).schemeIs(
"https"))) {
1616 hosts[RegExp.$1] =
true;
1619 else if (/^
file:\/\/([^\/]*)/.test(aEntry.url)) {
1620 hosts[RegExp.$1] =
true;
1622 if (aEntry.children) {
1647 var
cm =
Cc[
"@mozilla.org/cookiemanager;1"].getService(
Ci.nsICookieManager2);
1649 for (var i = 0; i < aWindows.length; i++)
1650 aWindows[i].cookies = [];
1656 aWindows.forEach(
function(aWindow) {
1657 for (var host in aWindow._hosts) {
1658 var list = cm.getCookiesFromHost(host);
1659 while (list.hasMoreElements()) {
1660 var cookie = list.getNext().QueryInterface(
Ci.nsICookie2);
1661 if (cookie.isSession && _this._checkPrivacyLevel(cookie.isSecure)) {
1664 if (!(cookie.host in jscookies &&
1665 cookie.path in jscookies[cookie.host] &&
1666 cookie.name in jscookies[cookie.host][cookie.path])) {
1667 var jscookie = {
"host": cookie.host,
"value": cookie.value };
1669 if (cookie.path) jscookie.path = cookie.path;
1670 if (cookie.name) jscookie.name = cookie.name;
1671 if (cookie.isSecure) jscookie.secure =
true;
1672 if (cookie.isHttpOnly) jscookie.httponly =
true;
1673 if (cookie.expiry < MAX_EXPIRY) jscookie.expiry = cookie.expiry;
1675 addCookieToHash(jscookies, cookie.host, cookie.path, cookie.name, jscookie);
1677 aWindow.cookies.push(jscookies[cookie.host][cookie.path][cookie.name]);
1684 for (i = 0; i < aWindows.length; i++)
1685 if (aWindows[i].cookies.length == 0)
1686 delete aWindows[
i].cookies;
1695 var winData = this.
_windows[aWindow.__SSi];
1698 winData[aAttr] = this._getWindowDimension(aWindow, aAttr);
1702 return aWindow[aItem] && !aWindow[aItem].visible;
1704 if (hidden.length != 0)
1705 winData.hidden = hidden.join(
",");
1706 else if (winData.hidden)
1707 delete winData.hidden;
1709 var
sidebar = aWindow.document.getElementById(
"sidebar-box").getAttribute(
"sidebarcommand");
1712 else if (winData.sidebar)
1713 delete winData.sidebar;
1722 _getCurrentState:
function sss_getCurrentState(aUpdateAll) {
1723 var activeWindow = this._getMostRecentBrowserWindow();
1727 this._forEachBrowserWindow(
function(aWindow) {
1728 if (!this._isWindowLoaded(aWindow))
1730 if (aUpdateAll || this.
_dirtyWindows[aWindow.__SSi] || aWindow == activeWindow) {
1731 this._collectWindowData(aWindow);
1745 total.push(this._windows[ix]);
1747 if (!this._windows[ix].isPopup)
1754 for each (let winData
in this._statesToRestore[ix].
windows) {
1755 total.push(winData);
1756 if (!winData.isPopup)
1766 if (nonPopupCount == 0 && lastClosedWindowsCopy.length > 0) {
1770 total.unshift(lastClosedWindowsCopy.shift())
1771 }
while (total[0].isPopup)
1776 this.activeWindowSSiCache = activeWindow.__SSi ||
"";
1778 ix = this.activeWindowSSiCache ? windows.indexOf(this.activeWindowSSiCache) : -1;
1780 return { windows:
total, selectedWindow: ix + 1, _closedWindows: lastClosedWindowsCopy };
1789 _getWindowState:
function sss_getWindowState(aWindow) {
1790 if (!this._isWindowLoaded(aWindow))
1791 return this._statesToRestore[aWindow.__SS_restoreID];
1794 this._collectWindowData(aWindow);
1797 var total = [this._windows[aWindow.__SSi]];
1800 return { windows: total };
1803 _collectWindowData:
function sss_collectWindowData(aWindow) {
1804 if (!this._isWindowLoaded(aWindow))
1831 this.windowToFocus = aWindow;
1834 if (aWindow && (!aWindow.__SSi || !
this._windows[aWindow.__SSi]))
1838 var root = typeof
aState ==
"string" ? this._safeEval(aState) :
aState;
1839 if (!root.windows[0]) {
1850 if (root._closedWindows)
1851 this._closedWindows = root._closedWindows;
1854 if (!aState.selectedWindow) {
1855 aState.selectedWindow = 0;
1859 for (var w = 1; w < root.windows.length; w++) {
1860 winData = root.windows[w];
1861 if (winData && winData.tabs && winData.tabs[0]) {
1862 var window = this._openWindowWithState({ windows: [
winData] });
1863 if (w == aState.selectedWindow - 1) {
1864 this.windowToFocus =
window;
1868 winData = root.windows[0];
1869 if (!winData.tabs) {
1875 (!winData.tabs[0].entries || winData.tabs[0].entries.length == 0)) {
1879 var tabbrowser = aWindow.gBrowser;
1887 tabstrip.smoothScroll =
false;
1891 if (
aOverwriteTabs && tabbrowser.selectedTab._tPos >= newTabCount)
1892 tabbrowser.moveTabTo(tabbrowser.selectedTab, newTabCount - 1);
1895 tabs.push(
t < openTabCount ? tabbrowser.mTabs[
t] : tabbrowser.addTab());
1898 tabbrowser.moveTabTo(tabs[
t], t);
1904 Array.slice(tabbrowser.mTabs, newTabCount, openTabCount)
1905 .forEach(tabbrowser.removeTab, tabbrowser);
1909 this.restoreWindowFeatures(aWindow, winData);
1910 delete this._windows[aWindow.__SSi].extData;
1912 if (winData.cookies) {
1913 this.restoreCookies(winData.cookies);
1915 if (winData.extData) {
1916 if (!this._windows[aWindow.__SSi].extData) {
1917 this._windows[aWindow.__SSi].extData = {};
1919 for (var
key in winData.extData) {
1920 this._windows[aWindow.__SSi].extData[
key] = winData.extData[
key];
1924 this._windows[aWindow.__SSi]._closedTabs = winData._closedTabs || [];
1953 var tabbrowser = aWindow.getBrowser();
1959 if (!tabbrowser.getBrowserForTab(
aTabs[
t]).webNavigation.sessionHistory) {
1965 var restoreHistoryFunc =
function(
self) {
1968 aWindow.setTimeout(restoreHistoryFunc, 100,
this);
1975 for (
t = 0;
t <
aTabs.length;
t++) {
1977 var browser = tabbrowser.getBrowserForTab(tab);
1983 browser.contentDocument.location =
"about:blank";
1989 tab.setAttribute(
"busy",
"true");
1990 tabbrowser.updateIcon(tab);
1991 tabbrowser.setTabTitleLoading(tab);
1997 browser.userTypedValue = activePageData ? activePageData.url ||
null :
null;
2006 let maxVisibleTabs = Math.ceil(tabbrowser.tabContainer.mTabstrip.scrollClientSize /
2007 aTabs[0].clientWidth);
2010 if (maxVisibleTabs < aTabs.length && aSelectTab > 1) {
2011 let firstVisibleTab = 0;
2017 firstVisibleTab =
aTabs.length - maxVisibleTabs;
2026 aTabs.unshift(
aTabs.splice(aSelectTab, 1)[0]);
2028 tabbrowser.selectedTab =
aTabs[0];
2032 if (!this._isWindowLoaded(aWindow)) {
2034 delete this._statesToRestore[aWindow.__SS_restoreID];
2035 delete aWindow.__SS_restoreID;
2067 var browser = aWindow.getBrowser().getBrowserForTab(tab);
2068 var history = browser.webNavigation.sessionHistory;
2070 if (history.count > 0) {
2071 history.PurgeHistory(history.count);
2073 history.QueryInterface(
Ci.nsISHistoryInternal);
2075 if (!tabData.entries) {
2076 tabData.entries = [];
2078 if (tabData.extData) {
2079 tab.__SS_extdata = {};
2080 for (let
key in tabData.extData)
2081 tab.__SS_extdata[
key] = tabData.extData[
key];
2084 delete tab.__SS_extdata;
2086 for (var i = 0; i < tabData.entries.length; i++) {
2088 if (!tabData.entries[i].url)
2090 history.addEntry(this._deserializeHistoryEntry(tabData.entries[i],
aIdMap),
true);
2094 var disallow = (tabData.disallow)?tabData.disallow.split(
","):[];
2096 browser.docShell[
"allow" + aCapability] = disallow.indexOf(aCapability) == -1;
2098 Array.filter(tab.attributes,
function(aAttr) {
2099 return (_this.xulAttributes.indexOf(aAttr.name) > -1);
2100 }).
forEach(tab.removeAttribute, tab);
2101 if (tabData.xultab) {
2103 tabData.xultab.split(
" ").forEach(
function(aAttr) {
2104 if (/^([^\s=]+)=(.*)/.
test(aAttr)) {
2105 tab.setAttribute(RegExp.$1, decodeURI(RegExp.$2));
2109 for (let
name in tabData.attributes)
2112 if (tabData.storage && browser.docShell instanceof
Ci.nsIDocShell)
2113 this._deserializeSessionStorage(tabData.storage, browser.docShell);
2116 var
event = aWindow.document.createEvent(
"Events");
2117 event.initEvent(
"SSTabRestoring",
true,
false);
2118 tab.dispatchEvent(
event);
2121 if (activeIndex >= tabData.entries.length)
2122 activeIndex = tabData.entries.length - 1;
2124 if (activeIndex >= 0)
2125 browser.webNavigation.gotoIndex(activeIndex);
2129 tab.removeAttribute(
"busy");
2132 if (tabData.entries.length > 0) {
2136 browser.__SS_restore_data = tabData.entries[
activeIndex] || {};
2137 browser.__SS_restore_text = tabData.text ||
"";
2138 browser.__SS_restore_pageStyle = tabData.pageStyle ||
"";
2139 browser.__SS_restore_tab =
tab;
2140 browser.__SS_restore = this.restoreDocument_proxy;
2141 browser.addEventListener(
"load", browser.__SS_restore,
true);
2146 if (tabData.userTypedValue) {
2147 browser.userTypedValue = tabData.userTypedValue;
2148 if (tabData.userTypedClear)
2149 browser.loadURI(tabData.userTypedValue,
null,
null,
true);
2152 aWindow.setTimeout(
function(){ _this.restoreHistory(aWindow,
aTabs,
aTabData,
aIdMap); }, 0);
2163 _deserializeHistoryEntry:
function sss_deserializeHistoryEntry(aEntry,
aIdMap) {
2164 var
shEntry =
Cc[
"@mozilla.org/browser/session-history-entry;1"].
2169 shEntry.setURI(ioService.newURI(aEntry.url,
null,
null));
2170 shEntry.setTitle(aEntry.title || aEntry.url);
2171 if (aEntry.subframe)
2172 shEntry.setIsSubFrame(aEntry.subframe ||
false);
2173 shEntry.loadType =
Ci.nsIDocShellLoadInfo.loadHistory;
2174 if (aEntry.contentType)
2175 shEntry.contentType = aEntry.contentType;
2176 if (aEntry.referrer)
2177 shEntry.referrerURI = ioService.newURI(aEntry.referrer,
null,
null);
2179 if (aEntry.cacheKey) {
2180 var cacheKey =
Cc[
"@mozilla.org/supports-PRUint32;1"].
2182 cacheKey.data = aEntry.cacheKey;
2183 shEntry.cacheKey = cacheKey;
2189 var
id =
aIdMap[aEntry.ID] || 0;
2191 for (
id = Date.now();
id in
aIdMap.used;
id++);
2198 if (aEntry.scroll) {
2199 var scrollPos = (aEntry.scroll ||
"0,0").split(
",");
2200 scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
2201 shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
2205 if (aEntry.postdata_b64) {
2206 postdata = atob(aEntry.postdata_b64);
2207 }
else if (aEntry.postdata) {
2208 postdata = aEntry.postdata;
2212 var stream =
Cc[
"@mozilla.org/io/string-input-stream;1"].
2214 stream.setData(postdata, postdata.length);
2215 shEntry.postData = stream;
2218 if (aEntry.owner_b64) {
2219 var ownerInput =
Cc[
"@mozilla.org/io/string-input-stream;1"].
2221 var binaryData = atob(aEntry.owner_b64);
2222 ownerInput.setData(binaryData, binaryData.length);
2223 var binaryStream =
Cc[
"@mozilla.org/binaryinputstream;1"].
2225 binaryStream.setInputStream(ownerInput);
2227 shEntry.owner = binaryStream.readObject(
true);
2228 }
catch (ex) {
debug(ex); }
2229 }
else if (aEntry.ownerURI) {
2230 var uriObj = ioService.newURI(aEntry.ownerURI,
null,
null);
2231 shEntry.owner =
Cc[
"@mozilla.org/scriptsecuritymanager;1"].
2233 getCodebasePrincipal(uriObj);
2236 if (aEntry.children && shEntry instanceof
Ci.nsISHContainer) {
2237 for (var i = 0; i < aEntry.children.length; i++) {
2239 if (!aEntry.children[i].url)
2241 shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i],
aIdMap), i);
2255 _deserializeSessionStorage:
function sss_deserializeSessionStorage(aStorageData,
aDocShell) {
2256 let ioService =
Cc[
"@mozilla.org/network/io-service;1"].getService(
Ci.nsIIOService);
2257 for (let
url in aStorageData) {
2259 let storage =
aDocShell.getSessionStorageForURI(uri);
2260 for (let
key in aStorageData[
url]) {
2262 storage.setItem(
key, aStorageData[url][
key]);
2264 catch (ex) {
Cu.reportError(ex); }
2272 restoreDocument_proxy:
function sss_restoreDocument_proxy(aEvent) {
2274 if (!aEvent || !aEvent.originalTarget || !aEvent.originalTarget.defaultView || aEvent.originalTarget.defaultView != aEvent.originalTarget.defaultView.top) {
2280 !aURL || aURL.replace(/#.*/,
"") ==
aDocument.location.href.replace(/#.*/,
"");
2285 textArray.forEach(
function(aEntry) {
2286 if (/^((?:\
d+\|)*)(#?)([^\s=]+)=(.*)$/.
test(aEntry) &&
2289 var node = RegExp.$2 ? document.getElementById(RegExp.$3) : document.getElementsByName(RegExp.$3)[0] ||
null;
2290 if (node &&
"value" in node && node.type !=
"file") {
2291 node.value = decodeURI(RegExp.$4);
2293 var
event = document.createEvent(
"UIEvents");
2294 event.initUIEvent(
"input",
true,
true,
aContent, 0);
2295 node.dispatchEvent(
event);
2306 let node =
key.charAt(0) ==
"#" ?
aDocument.getElementById(
key.slice(1)) :
2312 if (typeof value ==
"string" && node.type !=
"file") {
2313 if (node.value == value)
2318 let
event =
aDocument.createEvent(
"UIEvents");
2319 event.initUIEvent(
"input",
true,
true,
aDocument.defaultView, 0);
2320 node.dispatchEvent(
event);
2322 else if (typeof value ==
"boolean")
2323 node.checked =
value;
2324 else if (typeof value ==
"number")
2326 node.selectedIndex =
value;
2328 else if (value && value.fileList && value.type ==
"file" && node.type ==
"file")
2329 node.mozSetFileNameArray(value.fileList, value.fileList.length);
2330 else if (value && typeof value.indexOf ==
"function" && node.options) {
2331 Array.forEach(node.options,
function(aOpt,
aIx) {
2332 aOpt.selected = value.indexOf(
aIx) > -1;
2340 let window = this.ownerDocument.defaultView;
2346 if (
aData.innerHTML) {
2347 window.setTimeout(
function() {
2348 if (
aContent.document.designMode ==
"on" &&
2354 if (
aData.scroll && /(\
d+),(\
d+)/.test(
aData.scroll)) {
2355 aContent.scrollTo(RegExp.$1, RegExp.$2);
2357 Array.forEach(
aContent.document.styleSheets,
function(aSS) {
2358 aSS.disabled = aSS.title && aSS.title != selectedPageStyle;
2360 for (var i = 0; i <
aContent.frames.length; i++) {
2370 if (
hasExpectedURL(aEvent.originalTarget,
this.__SS_restore_data.url)) {
2371 var content = aEvent.originalTarget.defaultView;
2372 if (this.currentURI.spec ==
"about:config") {
2375 content = content.wrappedJSObject;
2378 this.markupDocumentViewer.authorStyleDisabled = selectedPageStyle ==
"_nostyle";
2381 var
event = this.ownerDocument.createEvent(
"Events");
2382 event.initEvent(
"SSTabRestored",
true,
false);
2401 restoreWindowFeatures:
function sss_restoreWindowFeatures(aWindow,
aWinData) {
2404 aWindow[aItem].visible = hidden.indexOf(aItem) == -1;
2408 this._windows[aWindow.__SSi].isPopup =
true;
2409 if (aWindow.gURLBar) {
2410 aWindow.gURLBar.readOnly =
true;
2411 aWindow.gURLBar.setAttribute(
"enablehistory",
"false");
2415 delete this._windows[aWindow.__SSi].isPopup;
2416 if (aWindow.gURLBar) {
2417 aWindow.gURLBar.readOnly =
false;
2418 aWindow.gURLBar.setAttribute(
"enablehistory",
"true");
2423 aWindow.setTimeout(
function() {
2424 _this.restoreDimensions.apply(_this, [aWindow,
aWinData.width || 0,
2473 var sidebar = aWindow.document.getElementById(
"sidebar-box");
2474 if (sidebar.getAttribute(
"sidebarcommand") !=
aSidebar) {
2479 if (this.windowToFocus && this.windowToFocus.content) {
2480 this.windowToFocus.content.focus();
2489 restoreCookies:
function sss_restoreCookies(
aCookies) {
2495 var parsed =
aCookies[
"value" +
i].match(/^([^=;]+)=([^;]*);(?:domain=[^;]+;)?(?:
path=([^;]*);)?(secure;)?(httponly;)?/);
2496 if (parsed && /^https?:\/\/([^\/]+)/.test(
aCookies[
"domain" + i]))
2498 host: RegExp.$1,
path: parsed[3],
name: parsed[1],
value: parsed[2],
2499 secure: parsed[4], httponly: parsed[5]
2508 var MAX_EXPIRY = Math.pow(2, 62);
2509 for (i = 0; i <
aCookies.length; i++) {
2512 cookieManager.add(cookie.host, cookie.path ||
"", cookie.name ||
"", cookie.value, !!cookie.secure, !!cookie.httponly,
true,
"expiry" in cookie ? cookie.expiry : MAX_EXPIRY);
2514 catch (ex) {
Cu.reportError(ex); }
2528 saveStateDelayed:
function sss_saveStateDelayed(aWindow,
aDelay) {
2533 if (!this._saveTimer && this._resume_from_crash &&
2534 !this._inPrivateBrowsing) {
2536 var minimalDelay = this.
_lastSaveTime + this._interval - Date.now();
2541 this._saveTimer =
Cc[
"@mozilla.org/timer;1"].createInstance(
Ci.nsITimer);
2542 this._saveTimer.init(
this,
aDelay,
Ci.nsITimer.TYPE_ONE_SHOT);
2555 saveState:
function sss_saveState(aUpdateAll) {
2557 if (!this._resume_from_crash && this._loadState ==
STATE_RUNNING)
2561 if (this._inPrivateBrowsing)
2564 var
oState = this._getCurrentState(aUpdateAll);
2567 lastUpdate: Date.now()
2569 if (this._recentCrashes)
2570 oState.session.recentCrashes = this._recentCrashes;
2579 var stateString =
Cc[
"@mozilla.org/supports-string;1"].
2582 stateString.data =
"(" + this._toJSONString(aStateObj) +
")";
2584 this._observerService.notifyObservers(stateString,
2585 "sessionstore-state-write",
"");
2588 if (stateString.data)
2589 this._writeFile(this._sessionFile, stateString.data);
2597 _clearDisk:
function sss_clearDisk() {
2598 if (this._sessionFile.exists()) {
2600 this._sessionFile.remove(
false);
2602 catch (ex) { dump(ex +
'\n'); }
2604 if (this._sessionFileBackup.exists()) {
2606 this._sessionFileBackup.remove(
false);
2608 catch (ex) { dump(ex +
'\n'); }
2620 _forEachBrowserWindow:
function sss_forEachBrowserWindow(aFunc) {
2621 var windowMediator =
Cc[
"@mozilla.org/appshell/window-mediator;1"].
2625 while (windowsEnum.hasMoreElements()) {
2626 var window = windowsEnum.getNext();
2627 if (window.__SSi && !window.closed) {
2628 aFunc.call(
this, window);
2637 _getMostRecentBrowserWindow:
function sss_getMostRecentBrowserWindow() {
2638 var
wm =
Cc[
"@mozilla.org/appshell/window-mediator;1"].
2641 var win = wm.getMostRecentWindow(
"navigator:browser");
2647 #ifdef BROKEN_WM_Z_ORDER
2649 var windowsEnum = wm.getEnumerator(
"navigator:browser");
2651 while (windowsEnum.hasMoreElements()) {
2652 let nextWin = windowsEnum.getNext();
2653 if (!nextWin.closed)
2658 var windowsEnum = wm.getZOrderDOMWindowEnumerator(
"navigator:browser",
true);
2659 while (windowsEnum.hasMoreElements()) {
2660 win = windowsEnum.getNext();
2674 _openWindowWithState:
function sss_openWindowWithState(aState) {
2675 var argString =
Cc[
"@mozilla.org/supports-string;1"].
2677 argString.data =
"";
2680 var window =
Cc[
"@mozilla.org/embedcomp/window-watcher;1"].
2683 "chrome,dialog=no,all", argString);
2686 var ID =
"window" + Math.random();
2687 }
while (ID in this._statesToRestore);
2688 this._statesToRestore[(window.__SS_restoreID = ID)] = aState;
2697 _doResumeSession:
function sss_doResumeSession() {
2698 if (this._clearingOnShutdown)
2701 return this.
_prefBranch.getIntPref(
"startup.page") == 3 ||
2702 this.
_prefBranch.getBoolPref(
"sessionstore.resume_session_once");
2711 _isCmdLineEmpty:
function sss_isCmdLineEmpty(aWindow) {
2712 var defaultArgs =
Cc[
"@mozilla.org/browser/clh;1"].
2714 if (aWindow.arguments && aWindow.arguments[0] &&
2715 aWindow.arguments[0] == defaultArgs)
2716 aWindow.arguments[0] =
null;
2718 return !aWindow.arguments || !aWindow.arguments[0];
2728 _checkPrivacyLevel:
function sss_checkPrivacyLevel(aIsHTTPS) {
2743 _getWindowDimension:
function sss_getWindowDimension(aWindow,
aAttribute) {
2745 switch (aWindow.windowState) {
2746 case aWindow.STATE_FULLSCREEN:
2747 case aWindow.STATE_MAXIMIZED:
2749 case aWindow.STATE_MINIMIZED:
2759 dimension = aWindow.outerWidth;
2762 dimension = aWindow.outerHeight;
2769 if (aWindow.windowState == aWindow.STATE_NORMAL) {
2772 return aWindow.document.documentElement.getAttribute(
aAttribute) || dimension;
2780 _getURIFromString:
function sss_getURIFromString(aString) {
2781 var ioService =
Cc[
"@mozilla.org/network/io-service;1"].
2783 return ioService.newURI(aString,
null,
null);
2789 _updateCrashReportURL:
function sss_updateCrashReportURL(aWindow) {
2790 if (!
Ci.nsICrashReporter) {
2792 this._updateCrashReportURL =
function(aWindow) {};
2796 var currentURI = aWindow.getBrowser().currentURI.clone();
2799 currentURI.userPass =
"";
2803 var
cr =
Cc[
"@mozilla.org/xre/app-info;1"].getService(
Ci.nsICrashReporter);
2804 cr.annotateCrashReport(
"URL", currentURI.spec);
2808 if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED)
2819 const SIX_HOURS_IN_MS = 6 * 60 * 60 * 1000;
2822 let winData = aState.windows ||
null;
2823 if (!winData || winData.length == 0)
2827 if (winData.length == 1 && winData[0].tabs &&
2828 winData[0].tabs.length == 1 && winData[0].tabs[0].entries &&
2829 winData[0].tabs[0].entries.length == 1 &&
2830 winData[0].tabs[0].entries[0].url ==
"about:sessionrestore")
2834 let
XRE =
Cc[
"@mozilla.org/xre/app-info;1"].getService(
Ci.nsIXULRuntime);
2839 this.
_prefBranch.getIntPref(
"sessionstore.max_resumed_crashes");
2841 (Date.now() - aState.session.lastUpdate);
2843 return max_resumed_crashes != -1 &&
2845 sessionAge && sessionAge >= SIX_HOURS_IN_MS);
2851 _safeEval:
function sss_safeEval(aStr) {
2852 return Cu.evalInSandbox(aStr,
new Cu.Sandbox(
"about:blank"));
2864 _toJSONString:
function sss_toJSONString(aJSObject) {
2869 if (/[\u2028\u2029]/.
test(jsonString)) {
2872 jsonString = jsonString.replace(/[\u2028\u2029]/g,
2873 function($0)
"\\u" + $0.charCodeAt(0).toString(16));
2880 function sss_sendRestoreCompletedNotifications(aOnWindowClose) {
2881 if (this._restoreCount && !aOnWindowClose)
2882 this._restoreCount--;
2884 if (this._restoreCount == 0 && this._closingWindows.length == 0) {
2886 this._observerService.notifyObservers(
null,
2889 this._browserSetState =
false;
2899 _isWindowLoaded:
function sss_isWindowLoaded(aWindow) {
2900 return !aWindow.__SS_restoreID;
2912 if (aString ==
aTabbrowser.mStringBundle.getString(
"tabs.loading")) {
2914 [aString,
aTab.label] = [
aTab.label, aString];
2924 _capClosedWindows :
function sss_capClosedWindows() {
2925 let maxWindowsUndo = this.
_prefBranch.getIntPref(
"sessionstore.max_windows_undo");
2926 if (this._closedWindows.length <= maxWindowsUndo)
2932 while (normalWindowIndex < this._closedWindows.length &&
2933 !!
this._closedWindows[normalWindowIndex].isPopup)
2934 normalWindowIndex++;
2935 if (normalWindowIndex >= maxWindowsUndo)
2936 spliceTo = normalWindowIndex + 1;
2938 this._closedWindows.splice(spliceTo);
2950 _writeFile:
function sss_writeFile(aFile,
aData) {
2952 var ostream =
Cc[
"@mozilla.org/network/safe-file-output-stream;1"].
2954 ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, 0);
2959 converter.charset =
"UTF-8";
2964 NetUtil.asyncCopy(istream, ostream,
function(rc) {
2965 if (Components.isSuccessCode(rc)) {
2966 self._observerService.notifyObservers(
null,
2967 "sessionstore-state-write-complete",
2976 namespaceURIs: {
"xhtml":
"http://www.w3.org/1999/xhtml" },
2977 namespacePrefixes: {
"http://www.w3.org/1999/xhtml":
"xhtml" },
2982 generate:
function sss_xph_generate(aNode) {
2984 if (!aNode.parentNode)
2987 let prefix = this.namespacePrefixes[aNode.namespaceURI] ||
null;
2988 let
tag = (prefix ? prefix +
":" :
"") + this.escapeName(aNode.localName);
2992 return "//" + tag +
"[@id=" + this.quoteArgument(aNode.id) +
"]";
2997 let nName = aNode.name ||
null;
2998 for (let n = aNode; (n = n.previousSibling); )
2999 if (n.localName == aNode.localName && n.namespaceURI == aNode.namespaceURI &&
3000 (!nName || n.name == nName))
3004 return this.generate(aNode.parentNode) +
"/" + tag +
3005 (nName ?
"[@name=" + this.quoteArgument(nName) +
"]" :
"") +
3006 (count ?
"[" + (count + 1) +
"]" :
"");
3012 resolve:
function sss_xph_resolve(
aDocument, aQuery) {
3013 let xptype =
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE;
3020 resolveNS:
function sss_xph_resolveNS(aPrefix) {
3021 return XPathHelper.namespaceURIs[aPrefix] ||
null;
3027 escapeName:
function sss_xph_escapeName(
aName) {
3031 "*[local-name()=" + this.quoteArgument(
aName) +
"]";
3037 quoteArgument:
function sss_xph_quoteArgument(aArg) {
3038 return !/
'/.test(aArg) ? "'" + aArg + "'" :
3039 !/"/.test(aArg) ? '"' + aArg + '"' :
3040 "concat('" + aArg.replace(/'+/g, "',\"$&\",'") + "')";
3046 get restorableFormNodes() {
3047 // for a comprehensive list of all available <INPUT> types see
3048 // http://mxr.mozilla.org/mozilla-central/search?string=kInputTypeTable
3049 let ignoreTypes = ["password", "hidden", "button", "image", "submit", "reset"];
3050 // XXXzeniko work-around until lower-case has been implemented (bug 398389)
3051 let toLowerCase = '"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz"';
3052 let ignore = "not(translate(@type, " + toLowerCase + ")='" +
3053 ignoreTypes.join("' or translate(@type, " + toLowerCase + ")='") + "')";
3054 let formNodesXPath = "//textarea|//select|//xhtml:textarea|//xhtml:select|" +
3055 "//input[" + ignore + "]|//xhtml:input[" + ignore + "]";
3057 delete this.restorableFormNodes;
3058 return (this.restorableFormNodes = formNodesXPath);
3062 // see nsPrivateBrowsingService.js
3063 String.prototype.hasRootDomain = function hasRootDomain(aDomain)
3065 let index = this.indexOf(aDomain);
3069 if (this == aDomain)
3072 let prevChar = this[index - 1];
3073 return (index == (this.length - aDomain.length)) &&
3074 (prevChar == "." || prevChar == "/");
3077 function NSGetModule(aComMgr, aFileSpec)
3078 XPCOMUtils.generateModule([SessionStoreService]);
_collectFormDataForFrame XPathHelper Ci nsIDOMXPathResult null
this restoreHistory(aWindow, aTabs, aTabData, idMap)
const NOTIFY_WINDOWS_RESTORED
function restoreTextDataAndScrolling(aContent, aData, aPrefix)
restoreDimensions aSidebar
this _updateTextAndScrollData(aWindow)
_collectFormDataForFrame XPathHelper resolveNS
getService(Ci.nsIWindowMediator)
aHash[aHost][aPath][aName]
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
restoreDimensions aSizeMode
function undoCloseWindow(aIndex)
this _dirtyWindows[aWindow.__SSi]
sbDeviceFirmwareAutoCheckForUpdate prototype classDescription
function restoreFormData(aDocument, aData, aURL)
delete this __SS_restore_data
this _saveWindowHistory(aWindow)
this _updateCookies(total)
SessionStoreService aDocShell
restoreDimensions aHeight
delete this __SS_restore_tab
ostream init(aFile, 0x02|0x08|0x20, 0600, 0)
_collectFormDataForFrame aDocument
const NOTIFY_BROWSER_STATE_RESTORED
let lastClosedWindowsCopy
_updateTextAndScrollDataForTab aTabData
function restoreTextData(aContent, aPrefix, aURL)
_updateTextAndScrollDataForFrame aContent
this _updateCookieHosts(aWindow)
if(hasContent) aTabData.storage
const MAX_GENERATED_XPATHS
SessionStoreService _serializeSessionStorage
this _windows[aWindow.__SSi] tabs forEach(function(aTabData){aTabData.entries.forEach(extractHosts);})
function openWindow(aOnloadCallback)
_replaceLoadingTitle aTabbrowser
this _statesToRestore[(window.__SS_restoreID=ID)]
this restoreHistoryPrecursor(aWindow, tabs, winData.tabs,(aOverwriteTabs?(parseInt(winData.selected)||1):0), 0, 0)
restoreHistoryPrecursor aIx
return!aWindow arguments!aWindow arguments[0]
history QueryInterface(Ci.nsISHistoryInternal)
this _saveStateObject(oState)
delete this __SS_restore_pageStyle
createInstance(Ci.nsISupportsString)
_updateTextAndScrollDataForTab aBrowser
this _sendRestoreCompletedNotifications()
saveStateDelayed saveState
delete this __SS_restore_text
SessionStoreService aHistory
const WINDOW_HIDEABLE_FEATURES
sbDeviceFirmwareAutoCheckForUpdate prototype classID
_replaceLoadingTitle aTab
_needsRestorePage aRecentCrashes
function onTabClose(event)
function hasExpectedURL(aDocument, aURL)!aURL||aURL.replace(/var textArray
restoreHistoryPrecursor aCount
this removeEventListener("load", this.__SS_restore, true)
dataSBGenres SBProperties tag
function extractHosts(aEntry)
_updateTextAndScrollDataForFrame aUpdateFormData
_getWindowDimension aAttribute
restoreWindow aOverwriteTabs
__defineGetter__("NetUtil", function(){delete this.NetUtil;Cu.import("resource://gre/modules/NetUtil.jsm");return NetUtil;})
this _updateTextAndScrollDataForFrame(aWindow, aBrowser.contentWindow, aTabData.entries[tabIndex],!aTabData._formDataSaved, aFullData)
_getSelectedPageStyle s i
function SessionStoreService()
SessionStoreService aFullData
restoreHistoryPrecursor aSelectTab
restoreHistoryPrecursor aTabs
this _updateWindowFeatures(aWindow)
_updateTextAndScrollDataForFrame aData
sbDeviceFirmwareAutoCheckForUpdate prototype observe
function undoCloseTab(aIndex)
restoreWindowFeatures aWinData