diff --git a/mobile/app/mobile.js b/mobile/app/mobile.js
index 65fb53e88cc1..753215b1072d 100644
--- a/mobile/app/mobile.js
+++ b/mobile/app/mobile.js
@@ -228,3 +228,14 @@ pref("places.frecency.tempRedirectVisitBonus", 0);
pref("places.frecency.defaultVisitBonus", 0);
pref("places.frecency.unvisitedBookmarkBonus", 140);
pref("places.frecency.unvisitedTypedBonus", 200);
+
+// controls which bits of private data to clear. by default we clear them all.
+pref("privacy.sanitize.promptOnSanitize", false);
+pref("privacy.item.cache", true);
+pref("privacy.item.cookies", true);
+pref("privacy.item.offlineApps", true);
+pref("privacy.item.history", true);
+pref("privacy.item.formdata", true);
+pref("privacy.item.downloads", true);
+pref("privacy.item.passwords", true);
+pref("privacy.item.sessions", true);
diff --git a/mobile/chrome/content/browser-ui.js b/mobile/chrome/content/browser-ui.js
index 08f84373d7bf..ab9f8582d974 100644
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -1,3 +1,4 @@
+// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@@ -48,6 +49,7 @@ const PANELMODE_ADDONS = 5;
const PANELMODE_SIDEBAR = 6;
const PANELMODE_TABLIST = 7;
const PANELMODE_FULL = 8;
+const PANELMODE_PREFS = 9;
const kDefaultFavIconURL = "chrome://browser/skin/images/default-favicon.png";
@@ -452,6 +454,11 @@ var BrowserUI = {
var tablist = document.getElementById("tab-list-container");
var addons = document.getElementById("addons-container");
var container = document.getElementById("browser-container");
+ var prefs = document.getElementById("pref-pane");
+
+ // Make sure the UI elements are sized correctly since the window size can change
+ sidebar.left = container.boxObject.width;
+ sidebar.height = tablist.height = container.boxObject.height;
if (aMode == PANELMODE_URLVIEW || aMode == PANELMODE_SIDEBAR ||
aMode == PANELMODE_TABLIST || aMode == PANELMODE_FULL)
@@ -464,6 +471,7 @@ var BrowserUI = {
bookmark.hidden = true;
urllist.hidden = true;
addons.hidden = true;
+ prefs.hidden = true;
let sidebarTo = toolbar.boxObject.width;
let tablistTo = -tablist.boxObject.width;
@@ -484,6 +492,8 @@ var BrowserUI = {
bookmark.hidden = true;
urllist.hidden = true;
addons.hidden = true;
+ prefs.hidden = true;
+
sidebar.left = toolbar.boxObject.width;
tablist.left = -tablist.boxObject.width;
}
@@ -500,6 +510,8 @@ var BrowserUI = {
bookmark.hidden = false;
addons.hidden = true;
+ prefs.hidden = true;
+
bookmark.width = container.boxObject.width;
}
else if (aMode == PANELMODE_BOOKMARKLIST) {
@@ -511,6 +523,8 @@ var BrowserUI = {
bookmark.hidden = true;
addons.hidden = true;
+ prefs.hidden = true;
+
sidebar.left = toolbar.boxObject.width;
tablist.left = -tablist.boxObject.width;
@@ -526,6 +540,7 @@ var BrowserUI = {
this._caption.hidden = false;
bookmark.hidden = true;
+ prefs.hidden = true;
sidebar.left = toolbar.boxObject.width;
tablist.left = -tablist.boxObject.width;
@@ -537,8 +552,28 @@ var BrowserUI = {
addons.width = container.boxObject.width;
addons.height = container.boxObject.height - toolbar.boxObject.height;
}
- else if (aMode == PANELMODE_NONE) {
+ else if (aMode == PANELMODE_PREFS) {
+ this._showToolbar();
+ toolbar.setAttribute("mode", "view");
+ this._edit.hidden = true;
+ this._edit.reallyClosePopup();
+ this._caption.hidden = false;
+
+ bookmark.hidden = true;
+ urllist.hidden = true;
+ addons.hidden = true;
+ prefs.hidden = false;
+ sidebar.left = toolbar.boxObject.width;
+ tablist.left = -tablist.boxObject.width;
+
+ prefs.width = container.boxObject.width;
+ prefs.height = container.boxObject.height - toolbar.boxObject.height;
+
+ PreferencesUI.init();
+ }
+ else if (aMode == PANELMODE_NONE) {
this._hideToolbar();
+
sidebar.left = toolbar.boxObject.width;
tablist.left = -tablist.boxObject.width;
@@ -546,6 +581,7 @@ var BrowserUI = {
urllist.hidden = true;
bookmark.hidden = true;
addons.hidden = true;
+ prefs.hidden = true;
}
},
@@ -685,6 +721,8 @@ var BrowserUI = {
case "cmd_closeTab":
case "cmd_addons":
case "cmd_actions":
+ case "cmd_prefs":
+ case "cmd_sanitize":
isSupported = true;
break;
default:
@@ -750,7 +788,7 @@ var BrowserUI = {
break;
case "cmd_menu":
// XXX Remove PANELMODE_ADDON when design changes
- if (this.mode == PANELMODE_FULL || this.mode == PANELMODE_ADDONS)
+ if (this.mode == PANELMODE_FULL || this.mode == PANELMODE_ADDONS || this.mode == PANELMODE_PREFS)
this.show(PANELMODE_NONE);
else
this.show(PANELMODE_FULL);
@@ -762,9 +800,15 @@ var BrowserUI = {
Browser.content.removeTab(Browser.content.browser);
break;
case "cmd_addons":
- case "cmd_actions":
this.show(PANELMODE_ADDONS);
break;
+ case "cmd_prefs":
+ case "cmd_actions":
+ this.show(PANELMODE_PREFS);
+ break;
+ case "cmd_sanitize":
+ Sanitizer.sanitize();
+ break;
}
}
};
diff --git a/mobile/chrome/content/browser.css b/mobile/chrome/content/browser.css
index 78e4f8caa141..17dd3b3afc3b 100644
--- a/mobile/chrome/content/browser.css
+++ b/mobile/chrome/content/browser.css
@@ -9,3 +9,19 @@ deckbrowser {
richlistitem[type="documenttab"] {
-moz-binding: url("chrome://browser/content/deckbrowser.xml#documenttab");
}
+
+richpreflist {
+ -moz-binding: url("chrome://browser/content/preferences/richpref.xml#richpreflist");
+}
+
+richpref[type="bool"] {
+ -moz-binding: url("chrome://browser/content/preferences/richpref.xml#richpref-bool");
+}
+
+richpref[type="boolint"] {
+ -moz-binding: url("chrome://browser/content/preferences/richpref.xml#richpref-boolint");
+}
+
+richpref[type="button"] {
+ -moz-binding: url("chrome://browser/content/preferences/richpref.xml#richpref-button");
+}
diff --git a/mobile/chrome/content/browser.xul b/mobile/chrome/content/browser.xul
index 49be59062533..3cd17144f52b 100644
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -40,12 +40,15 @@
+
%browserDTD;
%brandDTD;
+
+%prefsDTD;
]>
+
@@ -90,6 +94,7 @@
+
@@ -271,6 +276,39 @@
+
+
+
+
+
+
+
+
+ &permissions.default.image.description;
+
+
+ &javascript.enabled.description;
+
+
+ &plugins.enabled.description;
+
+
+
+
+
+
+ &network.cookie.cookieBehavior.description;
+
+
+ &clear.private.data.description;
+
+
+
+
+
+
+
+
diff --git a/mobile/chrome/content/preferences/richpref.xml b/mobile/chrome/content/preferences/richpref.xml
new file mode 100644
index 000000000000..38e6a793865d
--- /dev/null
+++ b/mobile/chrome/content/preferences/richpref.xml
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+ this.pref._setValue(this.pref.valueFromPreferences, false);
+ this.prefChanged();
+
+
+
+
+ this.pref.value = this.value;
+
+
+
+
+
+ this.value = this.pref.value;
+
+
+
+
+ this.getAttribute("type");
+ document.getAnonymousElementByAttribute(this, "anonid", "pref");
+ document.getAnonymousElementByAttribute(this, "anonid", "input");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this.pref.value = this.getAttribute(this.value ? "on" : "off");
+
+
+
+
+
+ this.value = this.pref.value == this.getAttribute("on");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/chrome/content/sanitize.js b/mobile/chrome/content/sanitize.js
new file mode 100644
index 000000000000..709a06cb48fe
--- /dev/null
+++ b/mobile/chrome/content/sanitize.js
@@ -0,0 +1,336 @@
+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# ***** 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 Firefox Sanitizer.
+#
+# The Initial Developer of the Original Code is
+# Ben Goodger.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Ben Goodger
+# Giorgio Maone
+#
+# 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 *****
+
+function Sanitizer() {}
+Sanitizer.prototype = {
+ // warning to the caller: this one may raise an exception (e.g. bug #265028)
+ clearItem: function (aItemName)
+ {
+ if (this.items[aItemName].canClear)
+ this.items[aItemName].clear();
+ },
+
+ canClearItem: function (aItemName)
+ {
+ return this.items[aItemName].canClear;
+ },
+
+ _prefDomain: "privacy.item.",
+ getNameFromPreference: function (aPreferenceName)
+ {
+ return aPreferenceName.substr(this._prefDomain.length);
+ },
+
+ /**
+ * Deletes privacy sensitive data in a batch, according to user preferences
+ *
+ * @returns null if everything's fine; an object in the form
+ * { itemName: error, ... } on (partial) failure
+ */
+ sanitize: function ()
+ {
+ var psvc = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefService);
+ var branch = psvc.getBranch(this._prefDomain);
+ var errors = null;
+ for (var itemName in this.items) {
+ var item = this.items[itemName];
+ if ("clear" in item && item.canClear && branch.getBoolPref(itemName)) {
+ // Some of these clear() may raise exceptions (see bug #265028)
+ // to sanitize as much as possible, we catch and store them,
+ // rather than fail fast.
+ // Callers should check returned errors and give user feedback
+ // about items that could not be sanitized
+ try {
+ item.clear();
+ } catch(er) {
+ if (!errors)
+ errors = {};
+ errors[itemName] = er;
+ dump("Error sanitizing " + itemName + ": " + er + "\n");
+ }
+ }
+ }
+ return errors;
+ },
+
+ items: {
+ cache: {
+ clear: function ()
+ {
+ const cc = Components.classes;
+ const ci = Components.interfaces;
+ var cacheService = cc["@mozilla.org/network/cache-service;1"]
+ .getService(ci.nsICacheService);
+ try {
+ cacheService.evictEntries(ci.nsICache.STORE_ANYWHERE);
+ } catch(er) {}
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ cookies: {
+ clear: function ()
+ {
+ var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"]
+ .getService(Components.interfaces.nsICookieManager);
+ cookieMgr.removeAll();
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ offlineApps: {
+ clear: function ()
+ {
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ var cacheService = Cc["@mozilla.org/network/cache-service;1"].
+ getService(Ci.nsICacheService);
+ try {
+ cacheService.evictEntries(Ci.nsICache.STORE_OFFLINE);
+ } catch(er) {}
+
+ var storageManagerService = Cc["@mozilla.org/dom/storagemanager;1"].
+ getService(Ci.nsIDOMStorageManager);
+ storageManagerService.clearOfflineApps();
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ history: {
+ clear: function ()
+ {
+ var globalHistory = Components.classes["@mozilla.org/browser/global-history;2"]
+ .getService(Components.interfaces.nsIBrowserHistory);
+ globalHistory.removeAllPages();
+
+ try {
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ os.notifyObservers(null, "browser:purge-session-history", "");
+ }
+ catch (e) { }
+
+ // Clear last URL of the Open Web Location dialog
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch2);
+ try {
+ prefs.clearUserPref("general.open_location.last_url");
+ }
+ catch (e) { }
+ },
+
+ get canClear()
+ {
+ // bug 347231: Always allow clearing history due to dependencies on
+ // the browser:purge-session-history notification. (like error console)
+ return true;
+ }
+ },
+
+ formdata: {
+ clear: function ()
+ {
+ //Clear undo history of all searchBars
+ var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
+ var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
+ var windows = windowManagerInterface.getEnumerator("navigator:browser");
+ while (windows.hasMoreElements()) {
+ var searchBar = windows.getNext().document.getElementById("searchbar");
+ if (searchBar) {
+ searchBar.value = "";
+ searchBar.textbox.editor.transactionManager.clear();
+ }
+ }
+
+ var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
+ .getService(Components.interfaces.nsIFormHistory2);
+ formHistory.removeAllEntries();
+ },
+
+ get canClear()
+ {
+ var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
+ .getService(Components.interfaces.nsIFormHistory2);
+ return formHistory.hasEntries;
+ }
+ },
+
+ downloads: {
+ clear: function ()
+ {
+ var dlMgr = Components.classes["@mozilla.org/download-manager;1"]
+ .getService(Components.interfaces.nsIDownloadManager);
+ dlMgr.cleanUp();
+ },
+
+ get canClear()
+ {
+ var dlMgr = Components.classes["@mozilla.org/download-manager;1"]
+ .getService(Components.interfaces.nsIDownloadManager);
+ return dlMgr.canCleanUp;
+ }
+ },
+
+ passwords: {
+ clear: function ()
+ {
+ var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
+ .getService(Components.interfaces.nsILoginManager);
+ pwmgr.removeAllLogins();
+ },
+
+ get canClear()
+ {
+ var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
+ .getService(Components.interfaces.nsILoginManager);
+ var count = pwmgr.countLogins("", "", ""); // count all logins
+ return (count > 0);
+ }
+ },
+
+ sessions: {
+ clear: function ()
+ {
+ // clear all auth tokens
+ var sdr = Components.classes["@mozilla.org/security/sdr;1"]
+ .getService(Components.interfaces.nsISecretDecoderRing);
+ sdr.logoutAndTeardown();
+
+ // clear plain HTTP auth sessions
+ var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1']
+ .getService(Components.interfaces.nsIHttpAuthManager);
+ authMgr.clearAll();
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ }
+ }
+};
+
+
+
+// "Static" members
+Sanitizer.prefDomain = "privacy.sanitize.";
+Sanitizer.prefPrompt = "promptOnSanitize";
+Sanitizer.prefShutdown = "sanitizeOnShutdown";
+Sanitizer.prefDidShutdown = "didShutdownSanitize";
+
+Sanitizer._prefs = null;
+Sanitizer.__defineGetter__("prefs", function()
+{
+ return Sanitizer._prefs ? Sanitizer._prefs
+ : Sanitizer._prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefService)
+ .getBranch(Sanitizer.prefDomain);
+});
+
+// Shows sanitization UI
+Sanitizer.showUI = function(aParentWindow)
+{
+ var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Components.interfaces.nsIWindowWatcher);
+#ifdef XP_MACOSX
+ ww.openWindow(null, // make this an app-modal window on Mac
+#else
+ ww.openWindow(aParentWindow,
+#endif
+ "chrome://browser/content/sanitize.xul",
+ "Sanitize",
+ "chrome,titlebar,centerscreen,modal",
+ null);
+};
+
+/**
+ * Deletes privacy sensitive data in a batch, optionally showing the
+ * sanitize UI, according to user preferences
+ *
+ * @returns null if everything's fine (no error or displayed UI, which
+ * should handle errors);
+ * an object in the form { itemName: error, ... } on (partial) failure
+ */
+Sanitizer.sanitize = function(aParentWindow)
+{
+ if (Sanitizer.prefs.getBoolPref(Sanitizer.prefPrompt)) {
+ Sanitizer.showUI(aParentWindow);
+ return null;
+ }
+ return new Sanitizer().sanitize();
+};
+
+Sanitizer.onStartup = function()
+{
+ // we check for unclean exit with pending sanitization
+ Sanitizer._checkAndSanitize();
+};
+
+Sanitizer.onShutdown = function()
+{
+ // we check if sanitization is needed and perform it
+ Sanitizer._checkAndSanitize();
+};
+
+// this is called on startup and shutdown, to perform pending sanitizations
+Sanitizer._checkAndSanitize = function()
+{
+ const prefs = Sanitizer.prefs;
+ if (prefs.getBoolPref(Sanitizer.prefShutdown) &&
+ !prefs.prefHasUserValue(Sanitizer.prefDidShutdown)) {
+ // this is a shutdown or a startup after an unclean exit
+ Sanitizer.sanitize(null) || // sanitize() returns null on full success
+ prefs.setBoolPref(Sanitizer.prefDidShutdown, true);
+ }
+};
+
+
diff --git a/mobile/chrome/content/sanitize.xul b/mobile/chrome/content/sanitize.xul
new file mode 100644
index 000000000000..97dd04a2108f
--- /dev/null
+++ b/mobile/chrome/content/sanitize.xul
@@ -0,0 +1,201 @@
+
+
+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# ***** 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 Firefox Sanitizer.
+#
+# The Initial Developer of the Original Code is
+# Ben Goodger.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Ben Goodger
+# Giorgio Maone
+#
+# 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 *****
+
+
+
+
+
+ %brandDTD;
+ %sanitizeDTD;
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &sanitizeItems.label;
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/chrome/jar.mn b/mobile/chrome/jar.mn
index 1b71dad91e32..fef5afd0caf1 100644
--- a/mobile/chrome/jar.mn
+++ b/mobile/chrome/jar.mn
@@ -16,6 +16,9 @@ browser.jar:
branding/brand.dtd (locale/@AB_CD@/brand/brand.dtd)
branding/brand.properties (locale/@AB_CD@/brand/brand.properties)
% style chrome://mozapps/content/extensions/extensions.xul chrome://browser/skin/extensions.css
+ content/preferences/richpref.xml
+* content/sanitize.xul
+* content/sanitize.js
classic.jar:
% skin browser classic/1.0 %
@@ -33,6 +36,8 @@ classic.jar:
images/toolbar.png (skin/images/toolbar.png)
images/mono-toolbar.png (skin/images/mono-toolbar.png)
images/toolbar-background.png (skin/images/toolbar-background.png)
+ section.css (skin/section.css)
+ richpref.css (skin/richpref.css)
@AB_CD@.jar:
% locale browser @AB_CD@ %
@@ -40,3 +45,4 @@ classic.jar:
browser.properties (locale/@AB_CD@/browser.properties)
search.properties (locale/@AB_CD@/search.properties)
region.properties (locale/@AB_CD@/region.properties)
+ preferences.dtd (locale/@AB_CD@/preferences.dtd)
diff --git a/mobile/chrome/locale/en-US/preferences.dtd b/mobile/chrome/locale/en-US/preferences.dtd
new file mode 100644
index 000000000000..397e597d9147
--- /dev/null
+++ b/mobile/chrome/locale/en-US/preferences.dtd
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/chrome/skin/browser.css b/mobile/chrome/skin/browser.css
index 9013033a6f62..b06a6e7b153b 100644
--- a/mobile/chrome/skin/browser.css
+++ b/mobile/chrome/skin/browser.css
@@ -451,3 +451,7 @@ findbar {
min-width: 280px;
padding: 10px;
}
+
+#pref-pane {
+ background-color: rgba(123,125,123,0.9);
+}
diff --git a/mobile/chrome/skin/richpref.css b/mobile/chrome/skin/richpref.css
new file mode 100644
index 000000000000..d43b41e95c9d
--- /dev/null
+++ b/mobile/chrome/skin/richpref.css
@@ -0,0 +1,20 @@
+richlistitem.section {
+ font-size: 1.5em ! important;
+ color: white;
+ background-color: grey;
+}
+
+.prefbox {
+ padding: .3em .3em .3em .5em;
+ border: thin solid lightgrey;
+}
+
+.preftitle {
+ font-size: 1.2em ! important;
+}
+
+.prefdesc {
+ font-size: 1em ! important;
+ color: grey;
+ background-color: white;
+}
diff --git a/mobile/chrome/skin/section.css b/mobile/chrome/skin/section.css
new file mode 100644
index 000000000000..fef8a3d307b5
--- /dev/null
+++ b/mobile/chrome/skin/section.css
@@ -0,0 +1,22 @@
+section .section-head {
+ font-size: larger;
+ font-weight: bolder;
+ display: list-item;
+}
+
+section .section-indicator {
+ width: 16px;
+ height: 16px;
+}
+
+section image.closed {
+ list-style-image: url("chrome://global/skin/arrow/arrow-rit-sharp.gif");
+}
+
+section image.open {
+ list-style-image: url("chrome://global/skin/arrow/arrow-dn-sharp.gif");
+}
+
+section > vbox > vbox {
+ margin-left: 16px;
+}