зеркало из https://github.com/mozilla/gecko-dev.git
Bug 448976 - turn the Session Restore prompt into an error page, r=dietrich
This commit is contained in:
Родитель
67e34b974d
Коммит
59dd39bb0e
|
@ -695,6 +695,9 @@ pref("browser.sessionstore.postdata", 0);
|
|||
pref("browser.sessionstore.privacy_level", 1);
|
||||
// how many tabs can be reopened (per window)
|
||||
pref("browser.sessionstore.max_tabs_undo", 10);
|
||||
// number of crashes that can occur before the about:sessionrestore page is displayed
|
||||
// (this pref has no effect if more than 6 hours have passed since the last crash)
|
||||
pref("browser.sessionstore.max_resumed_crashes", 1);
|
||||
|
||||
// allow META refresh by default
|
||||
pref("accessibility.blockautorefresh", false);
|
||||
|
|
|
@ -0,0 +1,323 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the nsSessionStore component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Simon Bünzli <zeniko@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var gStateObject;
|
||||
var gTreeData;
|
||||
|
||||
// Page initialization
|
||||
|
||||
window.onload = function() {
|
||||
// the crashed session state is kept inside a textbox so that SessionStore picks it up
|
||||
// (for when the tab is closed or the session crashes right again)
|
||||
var sessionData = document.getElementById("sessionData");
|
||||
if (!sessionData.value) {
|
||||
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].getService(Ci.nsISessionStartup);
|
||||
sessionData.value = ss.state;
|
||||
if (!sessionData.value)
|
||||
return;
|
||||
}
|
||||
// make sure the data is tracked to be restored in case of a subsequent crash
|
||||
var event = document.createEvent("UIEvents");
|
||||
event.initUIEvent("input", true, true, window, 0);
|
||||
sessionData.dispatchEvent(event);
|
||||
|
||||
var s = new Components.utils.Sandbox("about:blank");
|
||||
gStateObject = Components.utils.evalInSandbox("(" + sessionData.value + ")", s);
|
||||
|
||||
initTreeView();
|
||||
|
||||
document.getElementById("errorTryAgain").focus();
|
||||
};
|
||||
|
||||
function initTreeView() {
|
||||
var tabList = document.getElementById("tabList");
|
||||
var winLabel = tabList.getAttribute("_window_label");
|
||||
|
||||
gTreeData = [];
|
||||
gStateObject.windows.forEach(function(aWinData, aIx) {
|
||||
var winState = {
|
||||
label: winLabel.replace("%S", (aIx + 1)),
|
||||
open: true,
|
||||
checked: true,
|
||||
ix: aIx
|
||||
};
|
||||
winState.tabs = aWinData.tabs.map(function(aTabData) {
|
||||
var entry = aTabData.entries[aTabData.index - 1] || { url: "about:blank" };
|
||||
return {
|
||||
label: entry.title || entry.url,
|
||||
checked: true,
|
||||
src: aTabData.attributes.image || null,
|
||||
parent: winState
|
||||
};
|
||||
});
|
||||
gTreeData.push(winState);
|
||||
for each (var tab in winState.tabs)
|
||||
gTreeData.push(tab);
|
||||
}, this);
|
||||
|
||||
tabList.view = treeView;
|
||||
tabList.view.selection.select(0);
|
||||
}
|
||||
|
||||
// User actions
|
||||
|
||||
function restoreSession() {
|
||||
// remove all unselected tabs from the state before restoring it
|
||||
var ix = gStateObject.windows.length - 1;
|
||||
for (var t = gTreeData.length - 1; t >= 0; t--) {
|
||||
if (treeView.isContainer(t)) {
|
||||
if (gTreeData[t].checked === 0)
|
||||
// this window will be restored partially
|
||||
gStateObject.windows[ix].tabs =
|
||||
gStateObject.windows[ix].tabs.filter(function(aTabData, aIx)
|
||||
gTreeData[t].tabs[aIx].checked);
|
||||
else if (!gTreeData[t].checked)
|
||||
// this window won't be restored at all
|
||||
gStateObject.windows.splice(ix, 1);
|
||||
ix--;
|
||||
}
|
||||
}
|
||||
var stateString = gStateObject.toSource();
|
||||
|
||||
// restore the session into a new window and close the current tab
|
||||
var top = getBrowserWindow();
|
||||
var selfBrowser = top.gBrowser.getBrowserForDocument(document);
|
||||
var newWindow = top.openDialog(top.location, "_blank", "chrome,dialog=no,all");
|
||||
newWindow.addEventListener("load", function() {
|
||||
newWindow.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
ss.setWindowState(newWindow, stateString, true);
|
||||
|
||||
var tabbrowser = top.gBrowser;
|
||||
if (tabbrowser.tabContainer.childNodes.length == 1)
|
||||
top.close();
|
||||
else
|
||||
tabbrowser.removeTab(getTabForBrowser(selfBrowser));
|
||||
}, true);
|
||||
}
|
||||
|
||||
function startNewSession() {
|
||||
getBrowserWindow().BrowserHome();
|
||||
}
|
||||
|
||||
function onListClick(aEvent) {
|
||||
// don't react to right-clicks
|
||||
if (aEvent.button == 2)
|
||||
return;
|
||||
|
||||
var row = {}, col = {};
|
||||
treeView.treeBox.getCellAt(aEvent.clientX, aEvent.clientY, row, col, {});
|
||||
if (col.value) {
|
||||
// restore this specific tab in the same window for middle-clicking
|
||||
// or Ctrl+clicking on a tab's title
|
||||
if ((aEvent.button == 1 || aEvent.ctrlKey) && col.value.id == "title" &&
|
||||
!treeView.isContainer(row.value))
|
||||
restoreSingleTab(row.value, aEvent.shiftKey);
|
||||
else if (col.value.id == "restore")
|
||||
toggleRowChecked(row.value);
|
||||
}
|
||||
}
|
||||
|
||||
function onListKeyDown(aEvent) {
|
||||
switch (aEvent.keyCode)
|
||||
{
|
||||
case KeyEvent.DOM_VK_SPACE:
|
||||
toggleRowChecked(document.getElementById("tabList").currentIndex);
|
||||
break;
|
||||
case KeyEvent.DOM_VK_RETURN:
|
||||
var ix = document.getElementById("tabList").currentIndex;
|
||||
if (aEvent.ctrlKey && !treeView.isContainer(ix))
|
||||
restoreSingleTab(ix, aEvent.shiftKey);
|
||||
break;
|
||||
case KeyEvent.DOM_VK_UP:
|
||||
case KeyEvent.DOM_VK_DOWN:
|
||||
case KeyEvent.DOM_VK_PAGE_UP:
|
||||
case KeyEvent.DOM_VK_PAGE_DOWN:
|
||||
case KeyEvent.DOM_VK_HOME:
|
||||
case KeyEvent.DOM_VK_END:
|
||||
aEvent.preventDefault(); // else the page scrolls unwantedly
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
function getBrowserWindow() {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
|
||||
}
|
||||
|
||||
function getTabForBrowser(aBrowser) {
|
||||
return Array.filter(getBrowserWindow().gBrowser.tabContainer.childNodes,
|
||||
function(aTab) aTab.linkedBrowser == aBrowser)[0];
|
||||
}
|
||||
|
||||
function toggleRowChecked(aIx) {
|
||||
var item = gTreeData[aIx];
|
||||
item.checked = !item.checked;
|
||||
treeView.treeBox.invalidateRow(aIx);
|
||||
|
||||
function isChecked(aItem) aItem.checked;
|
||||
|
||||
if (treeView.isContainer(aIx)) {
|
||||
// (un)check all tabs of this window as well
|
||||
for each (var tab in item.tabs) {
|
||||
tab.checked = item.checked;
|
||||
treeView.treeBox.invalidateRow(gTreeData.indexOf(tab));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// update the window's checkmark as well (0 means "partially checked")
|
||||
item.parent.checked = item.parent.tabs.every(isChecked) ? true :
|
||||
item.parent.tabs.some(isChecked) ? 0 : false;
|
||||
treeView.treeBox.invalidateRow(gTreeData.indexOf(item.parent));
|
||||
}
|
||||
|
||||
document.getElementById("errorTryAgain").disabled = !gTreeData.some(isChecked);
|
||||
}
|
||||
|
||||
function restoreSingleTab(aIx, aShifted) {
|
||||
var tabbrowser = getBrowserWindow().gBrowser;
|
||||
var newTab = tabbrowser.addTab();
|
||||
var item = gTreeData[aIx];
|
||||
|
||||
var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
var tabState = gStateObject.windows[item.parent.ix]
|
||||
.tabs[aIx - gTreeData.indexOf(item.parent) - 1];
|
||||
ss.setTabState(newTab, tabState.toSource());
|
||||
|
||||
// respect the preference as to whether to select the tab (the Shift key inverses)
|
||||
var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
if (prefBranch.getBoolPref("browser.tabs.loadInBackground") != !aShifted)
|
||||
tabbrowser.selectedTab = newTab;
|
||||
}
|
||||
|
||||
// Tree controller
|
||||
|
||||
var treeView = {
|
||||
_atoms: {},
|
||||
_getAtom: function(aName)
|
||||
{
|
||||
if (!this._atoms[aName]) {
|
||||
var as = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomService);
|
||||
this._atoms[aName] = as.getAtom(aName);
|
||||
}
|
||||
return this._atoms[aName];
|
||||
},
|
||||
|
||||
treeBox: null,
|
||||
selection: null,
|
||||
|
||||
get rowCount() { return gTreeData.length; },
|
||||
setTree: function(treeBox) { this.treeBox = treeBox; },
|
||||
getCellText: function(idx, column) { return gTreeData[idx].label; },
|
||||
isContainer: function(idx) { return "open" in gTreeData[idx]; },
|
||||
getCellValue: function(idx, column){ return gTreeData[idx].checked; },
|
||||
isContainerOpen: function(idx) { return gTreeData[idx].open; },
|
||||
isContainerEmpty: function(idx) { return false; },
|
||||
isSeparator: function(idx) { return false; },
|
||||
isSorted: function() { return false; },
|
||||
isEditable: function(idx, column) { return false; },
|
||||
getLevel: function(idx) { return this.isContainer(idx) ? 0 : 1; },
|
||||
|
||||
getParentIndex: function(idx) {
|
||||
if (!this.isContainer(idx))
|
||||
for (var t = idx - 1; t >= 0 ; t--)
|
||||
if (this.isContainer(t))
|
||||
return t;
|
||||
return -1;
|
||||
},
|
||||
|
||||
hasNextSibling: function(idx, after) {
|
||||
var thisLevel = this.getLevel(idx);
|
||||
for (var t = idx + 1; t < gTreeData.length && this.getLevel(t) > thisLevel; t++);
|
||||
return thisLevel == this.getLevel(t);
|
||||
},
|
||||
|
||||
toggleOpenState: function(idx) {
|
||||
if (!this.isContainer(idx))
|
||||
return;
|
||||
var item = gTreeData[idx];
|
||||
if (item.open) {
|
||||
// remove this window's tab rows from the view
|
||||
var thisLevel = this.getLevel(idx);
|
||||
for (var t = idx + 1; t < gTreeData.length && this.getLevel(t) > thisLevel; t++);
|
||||
var deletecount = t - idx - 1;
|
||||
gTreeData.splice(idx + 1, deletecount);
|
||||
this.treeBox.rowCountChanged(idx + 1, -deletecount);
|
||||
}
|
||||
else {
|
||||
// add this window's tab rows to the view
|
||||
var toinsert = gTreeData[idx].tabs;
|
||||
for (var i = 0; i < toinsert.length; i++)
|
||||
gTreeData.splice(idx + i + 1, 0, toinsert[i]);
|
||||
this.treeBox.rowCountChanged(idx + 1, toinsert.length);
|
||||
}
|
||||
item.open = !item.open;
|
||||
},
|
||||
|
||||
getCellProperties: function(idx, column, prop) {
|
||||
if (column.id == "restore" && this.isContainer(idx) && gTreeData[idx].checked === 0)
|
||||
prop.AppendElement(this._getAtom("partial"));
|
||||
if (column.id == "title")
|
||||
prop.AppendElement(this._getAtom(this.getImageSrc(idx, column) ? "icon" : "noicon"));
|
||||
},
|
||||
|
||||
getRowProperties: function(idx, prop) {
|
||||
var winState = gTreeData[idx].parent || gTreeData[idx];
|
||||
if (winState.ix % 2 != 0)
|
||||
prop.AppendElement(this._getAtom("alternate"));
|
||||
},
|
||||
|
||||
getImageSrc: function(idx, column) {
|
||||
if (column.id == "title")
|
||||
return gTreeData[idx].src || null;
|
||||
return null;
|
||||
},
|
||||
|
||||
getProgressMode : function(idx, column) { },
|
||||
cycleHeader: function(column) { },
|
||||
cycleCell: function(idx, column) { },
|
||||
selectionChanged: function() { },
|
||||
performAction: function(action) { },
|
||||
performActionOnCell: function(action, index, column) { },
|
||||
getColumnProperties: function(column, prop) { }
|
||||
};
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the nsSessionStore component.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Simon Bünzli <zeniko@gmail.com>
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % netErrorDTD SYSTEM "chrome://global/locale/netError.dtd">
|
||||
%netErrorDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % restorepageDTD SYSTEM "chrome://browser/locale/aboutSessionRestore.dtd">
|
||||
%restorepageDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&restorepage.title;</title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutSessionRestore.css" type="text/css" media="all"/>
|
||||
<link rel="icon" type="image/png" href="chrome://global/skin/icons/question-16.png"/>
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/aboutSessionRestore.js"/>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
|
||||
<!-- PAGE CONTAINER (for styling purposes only) -->
|
||||
<div id="errorPageContainer">
|
||||
|
||||
<!-- Error Title -->
|
||||
<div id="errorTitle">
|
||||
<h1 id="errorTitleText">&restorepage.titletext;</h1>
|
||||
</div>
|
||||
|
||||
<!-- LONG CONTENT (the section most likely to require scrolling) -->
|
||||
<div id="errorLongContent">
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorShortDesc">
|
||||
<p id="errorShortDescText">&restorepage.shortDesc;</p>
|
||||
</div>
|
||||
|
||||
<!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
|
||||
<div id="errorLongDesc">
|
||||
<p>&restorepage.remedies;</p>
|
||||
<ul>
|
||||
<li>&restorepage.dueToChrome;</li>
|
||||
<li>&restorepage.dueToContent;</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorTrailerDesc">
|
||||
<tree xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="tabList" flex="1" seltype="single" hidecolumnpicker="true"
|
||||
onclick="onListClick(event);" onkeydown="onListKeyDown(event);"
|
||||
_window_label="&restorepage.windowLabel;">
|
||||
<treecols>
|
||||
<treecol id="restore" type="checkbox" label="&restorepage.restoreHeader;"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol primary="true" id="title" label="&restorepage.listHeader;" flex="1"/>
|
||||
</treecols>
|
||||
<treechildren flex="1"/>
|
||||
</tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="buttons">
|
||||
<button id="errorTryAgain" label="&restorepage.restoreButton;"
|
||||
accesskey="&restorepage.restore.access;"
|
||||
oncommand="restoreSession();"/>
|
||||
<button id="errorCancel" label="&restorepage.cancelButton;"
|
||||
accesskey="&restorepage.cancel.access;"
|
||||
oncommand="startNewSession();"/>
|
||||
</hbox>
|
||||
<!-- holds the session data for when the tab is closed -->
|
||||
<input type="text" id="sessionData" style="display: none;"/>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
browser.jar:
|
||||
* content/browser/aboutSessionRestore.xhtml (content/aboutSessionRestore.xhtml)
|
||||
content/browser/aboutSessionRestore.js (content/aboutSessionRestore.js)
|
|
@ -42,6 +42,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||
EXTRA_PP_COMPONENTS = \
|
||||
nsSessionStore.js \
|
||||
nsSessionStartup.js \
|
||||
aboutSessionRestore.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the nsSessionStore component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Simon Bünzli <zeniko@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function AboutSessionRestore() { }
|
||||
AboutSessionRestore.prototype = {
|
||||
classDescription: "about:sessionrestore",
|
||||
contractID: "@mozilla.org/network/protocol/about;1?what=sessionrestore",
|
||||
classID: Components.ID("{7c65e6f0-7605-11dd-ad8b-0800200c9a66}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
|
||||
|
||||
getURIFlags: function(aURI) {
|
||||
return Ci.nsIAboutModule.ALLOW_SCRIPT;
|
||||
},
|
||||
|
||||
newChannel: function(aURI) {
|
||||
let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
let channel = ios.newChannel("chrome://browser/content/aboutSessionRestore.xhtml",
|
||||
null, null);
|
||||
channel.originalURI = aURI;
|
||||
return channel;
|
||||
}
|
||||
};
|
||||
|
||||
function NSGetModule(compMgr, fileSpec)
|
||||
XPCOMUtils.generateModule([AboutSessionRestore]);
|
|
@ -95,8 +95,8 @@ SessionStartup.prototype = {
|
|||
* Initialize the component
|
||||
*/
|
||||
init: function sss_init() {
|
||||
this._prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).getBranch("browser.");
|
||||
let prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).getBranch("browser.");
|
||||
|
||||
// get file references
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
|
@ -104,11 +104,11 @@ SessionStartup.prototype = {
|
|||
let sessionFile = dirService.get("ProfD", Ci.nsILocalFile);
|
||||
sessionFile.append("sessionstore.js");
|
||||
|
||||
let doResumeSession = this._prefBranch.getBoolPref("sessionstore.resume_session_once") ||
|
||||
this._prefBranch.getIntPref("startup.page") == 3;
|
||||
let doResumeSession = prefBranch.getBoolPref("sessionstore.resume_session_once") ||
|
||||
prefBranch.getIntPref("startup.page") == 3;
|
||||
|
||||
// only read the session file if config allows possibility of restoring
|
||||
var resumeFromCrash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
||||
var resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
||||
if (!resumeFromCrash && !doResumeSession || !sessionFile.exists())
|
||||
return;
|
||||
|
||||
|
@ -129,7 +129,7 @@ SessionStartup.prototype = {
|
|||
initialState.session.state == STATE_RUNNING_STR;
|
||||
|
||||
// set the startup type
|
||||
if (lastSessionCrashed && resumeFromCrash && this._doRecoverSession())
|
||||
if (lastSessionCrashed && resumeFromCrash)
|
||||
this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
|
||||
else if (!lastSessionCrashed && doResumeSession)
|
||||
this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
|
||||
|
@ -235,74 +235,6 @@ SessionStartup.prototype = {
|
|||
return this._sessionType;
|
||||
},
|
||||
|
||||
/* ........ Auxiliary Functions .............. */
|
||||
|
||||
/**
|
||||
* prompt user whether or not to restore the previous session,
|
||||
* if the browser crashed
|
||||
* @returns bool
|
||||
*/
|
||||
_doRecoverSession: function sss_doRecoverSession() {
|
||||
// if the prompt fails, recover anyway
|
||||
var recover = true;
|
||||
|
||||
// allow extensions to hook in a more elaborate restore prompt
|
||||
// XXXzeniko drop this when we're using our own dialog instead of a standard prompt
|
||||
var dialogURI = null;
|
||||
try {
|
||||
dialogURI = this._prefBranch.getCharPref("sessionstore.restore_prompt_uri");
|
||||
}
|
||||
catch (ex) { }
|
||||
|
||||
try {
|
||||
if (dialogURI) { // extension provided dialog
|
||||
var params = Cc["@mozilla.org/embedcomp/dialogparam;1"].
|
||||
createInstance(Ci.nsIDialogParamBlock);
|
||||
// default to recovering
|
||||
params.SetInt(0, 0);
|
||||
Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher).
|
||||
openWindow(null, dialogURI, "_blank",
|
||||
"chrome,modal,centerscreen,titlebar", params);
|
||||
recover = params.GetInt(0) == 0;
|
||||
}
|
||||
else { // basic prompt with no options
|
||||
// get app name from branding properties
|
||||
const brandShortName = this._getStringBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
// create prompt strings
|
||||
var ssStringBundle = this._getStringBundle("chrome://browser/locale/sessionstore.properties");
|
||||
var restoreTitle = ssStringBundle.formatStringFromName("restoredTitle", [brandShortName], 1);
|
||||
var restoreText = ssStringBundle.formatStringFromName("restoredMsg", [brandShortName], 1);
|
||||
var okTitle = ssStringBundle.GetStringFromName("okTitle");
|
||||
var cancelTitle = ssStringBundle.GetStringFromName("cancelTitle");
|
||||
|
||||
var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
|
||||
getService(Ci.nsIPromptService);
|
||||
// set the buttons that will appear on the dialog
|
||||
var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
|
||||
promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
|
||||
promptService.BUTTON_POS_0_DEFAULT;
|
||||
var buttonChoice = promptService.confirmEx(null, restoreTitle, restoreText,
|
||||
flags, okTitle, cancelTitle, null,
|
||||
null, {});
|
||||
recover = (buttonChoice == 0);
|
||||
}
|
||||
}
|
||||
catch (ex) { dump(ex + "\n"); } // if the prompt fails, recover anyway
|
||||
return recover;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convenience method to get localized string bundles
|
||||
* @param aURI
|
||||
* @returns nsIStringBundle
|
||||
*/
|
||||
_getStringBundle: function sss_getStringBundle(aURI) {
|
||||
return Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).createBundle(aURI);
|
||||
},
|
||||
|
||||
/* ........ Storage API .............. */
|
||||
|
||||
/**
|
||||
|
|
|
@ -122,8 +122,9 @@ SessionStoreService.prototype = {
|
|||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
// xul:tab attributes to (re)store (extensions might want to hook in here)
|
||||
xulAttributes: [],
|
||||
// xul:tab attributes to (re)store (extensions might want to hook in here);
|
||||
// the favicon is always saved for the about:sessionrestore page
|
||||
xulAttributes: ["image"],
|
||||
|
||||
// set default load state
|
||||
_loadState: STATE_STOPPED,
|
||||
|
@ -150,6 +151,9 @@ SessionStoreService.prototype = {
|
|||
// not-"dirty" windows usually don't need to have their data updated
|
||||
_dirtyWindows: {},
|
||||
|
||||
// counts the number of crashes since the last clean start
|
||||
_recentCrashes: 0,
|
||||
|
||||
/* ........ Global Event Handlers .............. */
|
||||
|
||||
/**
|
||||
|
@ -218,6 +222,23 @@ SessionStoreService.prototype = {
|
|||
this._writeFile(this._sessionFileBackup, iniString);
|
||||
}
|
||||
catch (ex) { } // nothing else we can do here
|
||||
|
||||
this._recentCrashes = (this._initialState.session &&
|
||||
this._initialState.session.recentCrashes || 0) + 1;
|
||||
|
||||
const SIX_HOURS_IN_MS = 6 * 60 * 60 * 1000;
|
||||
let max_resumed_crashes =
|
||||
this._prefBranch.getIntPref("sessionstore.max_resumed_crashes");
|
||||
let sessionAge = this._initialState.session &&
|
||||
this._initialState.session.lastUpdate &&
|
||||
(Date.now() - this._initialState.session.lastUpdate);
|
||||
let needsRestorePage = max_resumed_crashes != -1 &&
|
||||
(this._recentCrashes > max_resumed_crashes ||
|
||||
sessionAge && sessionAge >= SIX_HOURS_IN_MS);
|
||||
if (needsRestorePage)
|
||||
// replace the crashed session with a restore-page-only session
|
||||
this._initialState =
|
||||
{ windows: [{ tabs: [{ entries: [{ url: "about:sessionrestore"}] }] }] };
|
||||
}
|
||||
|
||||
// make sure that at least the first window doesn't have anything hidden
|
||||
|
@ -1208,7 +1229,8 @@ SessionStoreService.prototype = {
|
|||
}
|
||||
var isHTTPS = this._getURIFromString((aContent.parent || aContent).
|
||||
document.location.href).schemeIs("https");
|
||||
if (aFullData || this._checkPrivacyLevel(isHTTPS)) {
|
||||
if (aFullData || this._checkPrivacyLevel(isHTTPS) ||
|
||||
aContent.top.document.location.href == "about:sessionrestore") {
|
||||
if (aFullData || aUpdateFormData) {
|
||||
let formData = this._collectFormDataForFrame(aContent.document);
|
||||
if (formData)
|
||||
|
@ -2102,7 +2124,12 @@ SessionStoreService.prototype = {
|
|||
return;
|
||||
|
||||
var oState = this._getCurrentState(aUpdateAll);
|
||||
oState.session = { state: ((this._loadState == STATE_RUNNING) ? STATE_RUNNING_STR : STATE_STOPPED_STR) };
|
||||
oState.session = {
|
||||
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
|
||||
lastUpdate: Date.now()
|
||||
};
|
||||
if (this._recentCrashes)
|
||||
oState.session.recentCrashes = this._recentCrashes;
|
||||
|
||||
var stateString = Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
|
|
|
@ -226,6 +226,7 @@ bin/components/extensions.xpt
|
|||
bin/components/update.xpt
|
||||
bin/components/nsSessionStartup.js
|
||||
bin/components/nsSessionStore.js
|
||||
bin/components/aboutSessionRestore.js
|
||||
bin/components/sessionstore.xpt
|
||||
bin/components/nsURLFormatter.js
|
||||
bin/components/urlformatter.xpt
|
||||
|
|
|
@ -233,6 +233,7 @@ bin\components\extensions.xpt
|
|||
bin\components\update.xpt
|
||||
bin\components\nsSessionStartup.js
|
||||
bin\components\nsSessionStore.js
|
||||
bin\components\aboutSessionRestore.js
|
||||
bin\components\sessionstore.xpt
|
||||
bin\components\nsURLFormatter.js
|
||||
bin\components\urlformatter.xpt
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<!ENTITY restorepage.title "Restore Previous Session">
|
||||
<!ENTITY restorepage.titletext "Your Last &brandShortName; Session Closed Unexpectedly">
|
||||
<!ENTITY restorepage.shortDesc "You can restore the tabs and windows from your previous session, or start a new session if they are no longer needed. Our apologies for the inconvenience.">
|
||||
<!ENTITY restorepage.remedies "If &brandShortName; closes repeatedly:">
|
||||
<!ENTITY restorepage.dueToChrome "Try disabling any recently added extensions in the Add-ons Manager.">
|
||||
<!ENTITY restorepage.dueToContent "Try restoring your session without any Web pages you suspect might be causing the crash:">
|
||||
|
||||
<!ENTITY restorepage.restoreButton "Restore Previous Session">
|
||||
<!ENTITY restorepage.restore.access "R">
|
||||
<!ENTITY restorepage.cancelButton "Start New Session">
|
||||
<!ENTITY restorepage.cancel.access "S">
|
||||
|
||||
<!ENTITY restorepage.restoreHeader "Restore">
|
||||
<!ENTITY restorepage.listHeader "Windows and Tabs">
|
||||
<!-- LOCALIZATION NOTE: %S will be replaced with a number. -->
|
||||
<!ENTITY restorepage.windowLabel "Window #%S">
|
|
@ -1,7 +0,0 @@
|
|||
restoredTitle= %S - Restore Previous Session
|
||||
restoredMsg=Your last %S session closed unexpectedly. You can restore the tabs and windows from your previous session, or start a new session if you think the problem was related to a page you were viewing.
|
||||
|
||||
# Localization note: It is recommended that okTitle be longer than cancelTitle
|
||||
# so that hitting the more prominent button doesn't lead to dataloss (see bug 346264).
|
||||
okTitle=Restore Previous Session
|
||||
cancelTitle=Start New Session
|
|
@ -4,6 +4,7 @@
|
|||
% locale browser @AB_CD@ %locale/browser/
|
||||
locale/browser/aboutDialog.dtd (%chrome/browser/aboutDialog.dtd)
|
||||
locale/browser/aboutRobots.dtd (%chrome/browser/aboutRobots.dtd)
|
||||
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
|
||||
locale/browser/credits.dtd (%chrome/browser/credits.dtd)
|
||||
* locale/browser/browser.dtd (%chrome/browser/browser.dtd)
|
||||
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
%if 0
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the nsSessionStore component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Simon Bünzli <zeniko@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
%endif
|
||||
|
||||
#errorPageContainer {
|
||||
background-image: url("chrome://global/skin/icons/question-48.png");
|
||||
}
|
||||
|
||||
#tabList {
|
||||
width: 100%;
|
||||
height: 12em;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(icon),
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
padding-right: 2px;
|
||||
margin: 0px 2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
|
||||
}
|
||||
treechildren::-moz-tree-image(container, noicon) {
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png");
|
||||
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||
}
|
||||
treechildren::-moz-tree-image(container, open, noicon) {
|
||||
-moz-image-region: rect(16px, 32px, 32px, 16px);
|
||||
}
|
||||
treechildren::-moz-tree-image(checked) {
|
||||
list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif");
|
||||
}
|
||||
treechildren::-moz-tree-image(partial) {
|
||||
list-style-image: url("chrome://global/skin/checkbox/cbox-check-dis.gif");
|
||||
}
|
||||
|
||||
/* XXXzeniko will need an appropriate color here (or none?) */
|
||||
treechildren::-moz-tree-row(alternate) {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
treechildren::-moz-tree-row(alternate, selected) {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
width: 100%;
|
||||
}
|
||||
#buttons > button {
|
||||
margin-top: 2em;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
classic.jar:
|
||||
% skin browser classic/1.0 %skin/classic/browser/
|
||||
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
|
||||
* skin/classic/browser/browser.css (browser.css)
|
||||
skin/classic/browser/browser.xml
|
||||
* skin/classic/browser/engineManager.css (engineManager.css)
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
%if 0
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the nsSessionStore component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Simon Bünzli <zeniko@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
%endif
|
||||
|
||||
#errorPageContainer {
|
||||
background-image: url("chrome://global/skin/icons/question-48.png");
|
||||
}
|
||||
|
||||
#tabList {
|
||||
width: 100%;
|
||||
height: 12em;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(icon),
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
padding-right: 2px;
|
||||
margin: 0px 2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
|
||||
}
|
||||
treechildren::-moz-tree-image(container, noicon) {
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png");
|
||||
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||
}
|
||||
treechildren::-moz-tree-image(container, open, noicon) {
|
||||
-moz-image-region: rect(16px, 32px, 32px, 16px);
|
||||
}
|
||||
treechildren::-moz-tree-image(checked) {
|
||||
list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif");
|
||||
}
|
||||
treechildren::-moz-tree-image(partial) {
|
||||
list-style-image: url("chrome://global/skin/checkbox/cbox-check-dis.gif");
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-row(odd) {
|
||||
background-color: -moz-field;
|
||||
}
|
||||
treechildren::-moz-tree-row(alternate) {
|
||||
background-color: -moz-oddtreerow;
|
||||
}
|
||||
treechildren::-moz-tree-row(alternate, selected) {
|
||||
background-color: -moz-mac-secondaryhighlight;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
width: 100%;
|
||||
}
|
||||
#buttons > button {
|
||||
margin-top: 2em;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
classic.jar:
|
||||
% skin browser classic/1.0 %skin/classic/browser/
|
||||
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
|
||||
skin/classic/browser/bookmark_toolbar_background.png
|
||||
skin/classic/browser/bookmark-open-left.png
|
||||
skin/classic/browser/bookmark-open-mid.png
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
%if 0
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the nsSessionStore component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Simon Bünzli <zeniko@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
%endif
|
||||
|
||||
#errorPageContainer {
|
||||
background-image: url("chrome://global/skin/icons/question-48.png");
|
||||
}
|
||||
|
||||
#tabList {
|
||||
width: 100%;
|
||||
height: 12em;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(icon),
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
padding-right: 2px;
|
||||
margin: 0px 2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
|
||||
}
|
||||
treechildren::-moz-tree-image(container, noicon) {
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png");
|
||||
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||
}
|
||||
treechildren::-moz-tree-image(container, open, noicon) {
|
||||
-moz-image-region: rect(16px, 32px, 32px, 16px);
|
||||
}
|
||||
treechildren::-moz-tree-image(checked) {
|
||||
list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif");
|
||||
}
|
||||
treechildren::-moz-tree-image(partial) {
|
||||
list-style-image: url("chrome://global/skin/checkbox/cbox-check-dis.gif");
|
||||
}
|
||||
|
||||
/* XXXzeniko will need an appropriate color here (or none?) */
|
||||
treechildren::-moz-tree-row(alternate) {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
treechildren::-moz-tree-row(alternate, selected) {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
width: 100%;
|
||||
}
|
||||
#buttons > button {
|
||||
margin-top: 2em;
|
||||
}
|
|
@ -3,6 +3,7 @@ classic.jar:
|
|||
% skin browser classic/1.0 %skin/classic/browser/ os!=WINNT
|
||||
# NOTE: If you add a new file here, you'll need to add it to the aero
|
||||
# section at the bottom of this file
|
||||
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
|
||||
* skin/classic/browser/browser.css (browser.css)
|
||||
skin/classic/browser/browser.xml
|
||||
* skin/classic/browser/engineManager.css (engineManager.css)
|
||||
|
@ -91,6 +92,7 @@ classic.jar:
|
|||
#ifdef XP_WIN
|
||||
classic.jar:
|
||||
% skin browser classic/1.0 %skin/classic/aero/browser/ os=WINNT osversion>=6
|
||||
* skin/classic/aero/browser/aboutSessionRestore.css (aboutSessionRestore.css)
|
||||
* skin/classic/aero/browser/browser.css (browser-aero.css)
|
||||
skin/classic/aero/browser/browser.xml
|
||||
* skin/classic/aero/browser/engineManager.css (engineManager.css)
|
||||
|
|
Загрузка…
Ссылка в новой задаче